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".
......
......@@ -16,19 +16,30 @@
*/
/*! \page docblocks Documenting the code
\section specialblock Special documentation blocks
This chapter covers two topics:
1. How to put comments in your code such that doxygen incorporates them in
the documentation it generates.
This is further detailed in the \ref specialblock "next section".
2. Ways to structure the contents of a comment block such that the output
looks good, as explained in section \ref docstructure.
A special documentation block is a C or C++ style comment block with some
additional markings, so doxygen knows it is a piece of documentation that
needs to end up in the generated documentation. For Python, VHDL, Fortran, and
Tcl code there are different comment conventions, which can be found in sections
\ref pythonblocks, \ref vhdlblocks, \ref fortranblocks, and \ref tclblocks
respectively.
\section specialblock Special comment blocks
For each code item there are two (or in some cases three) types of descriptions,
which together form the documentation: a \e brief description and \e detailed
A special comment block is a C or C++ style comment block with some
additional markings, so doxygen knows it is a piece of structured text that
needs to end up in the generated documentation. The \ref cppblock "next" section
presents the various styles supported by doxygen.
For Python, VHDL, Fortran, and Tcl code there are different commenting
conventions, which can be found in sections \ref pythonblocks, \ref vhdlblocks,
\ref fortranblocks, and \ref tclblocks respectively.
\subsection cppblock Comment blocks for C-like languages (C/C++/C#/Objective-C/PHP/Java)
For each entity in the code there are two (or in some cases three) types of descriptions,
which together form the documentation for that entity; a *brief* description and *detailed*
description, both are optional. For methods and functions there is also a third
type of description, the so called "in body" description, which consists of
type of description, the so called *in body* description, which consists of
the concatenation of all comment blocks found within the body of the method or function.
Having more than one brief or detailed description is allowed (but not recommended,
......@@ -39,7 +50,7 @@ a short one-liner, whereas the detailed description provides longer,
more detailed documentation. An "in body" description can also act as a detailed
description or can describe a collection of implementation details.
For the HTML output brief descriptions are also
use to provide tooltips at places where an item is referenced.
used to provide tooltips at places where an item is referenced.
There are several ways to mark a comment block as a detailed description:
<ol>
......@@ -183,49 +194,6 @@ They will be joined. Note that this is also the case if the descriptions
are at different places in the code! In this case the order will depend
on the order in which doxygen parses the code.
Here is an example of a documented piece of C++ code using the Qt style:
\include qtstyle.cpp
\htmlonly
Click <a href="$(DOXYGEN_DOCDIR)/examples/qtstyle/html/class_test.html">here</a>
for the corresponding HTML documentation that is generated by doxygen.
\endhtmlonly
The one-line comments contain a brief description,
whereas the multi-line comment blocks contain a more detailed description.
The brief descriptions are included in the member overview of a
class, namespace or file and are printed using a small italic font
(this description can be hidden by setting
\ref cfg_brief_member_desc "BRIEF_MEMBER_DESC" to \c NO in
the config file). By default the brief descriptions become the first
sentence of the detailed descriptions
(but this can be changed by setting the \ref cfg_repeat_brief "REPEAT_BRIEF"
tag to \c NO). Both the brief and the detailed descriptions are optional
for the Qt style.
By default a JavaDoc style documentation block behaves the same way as a
Qt style documentation block. This is not according the JavaDoc specification
however, where the first sentence of the documentation block is automatically
treated as a brief description. To enable this behavior you should set
\ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" to YES in the configuration
file. If you enable this option and want to put a dot in the middle of a
sentence without ending it, you should put a backslash and a space after it.
Here is an example:
\verbatim
/** Brief description (e.g.\ using only a few words). Details follow. */
\endverbatim
Here is the same piece of code as shown above, this time documented using the
JavaDoc style and \ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" set to YES:
\include jdstyle.cpp
\htmlonly
Click <a href="$(DOXYGEN_DOCDIR)/examples/jdstyle/html/class_test.html">here</a>
for the corresponding HTML documentation that is generated by doxygen.
\endhtmlonly
Similarly, if one wishes the first sentence of a Qt style documentation
block to automatically be treated as a brief description, one may set
\ref cfg_qt_autobrief "QT_AUTOBRIEF" to YES in the configuration file.
Unlike most other documentation systems, doxygen also allows you to put
the documentation of members (including global functions) in front of
......@@ -235,10 +203,9 @@ implementer of the members more direct access to the documentation.
As a compromise the brief description could be placed before the
declaration and the detailed description before the member definition.
\section memberdoc Putting documentation after members
\subsubsection memberdoc Putting documentation after members
If you want to document the members of a file, struct, union, class, or enum,
and you want to put the documentation for these members inside the compound,
it is sometimes desired to place the documentation block after the member
instead of before. For this purpose you have to put an additional \< marker
in the comment block. Note that this also works for the parameters
......@@ -275,7 +242,7 @@ or
int var; ///< Brief description after the member
\endverbatim
For functions one can use \@param to document the parameters
For functions one can use the \ref cmdparam "\@param" command to document the parameters
and then use <code>[in]</code>, <code>[out]</code>, <code>[in,out]</code>
to document the direction. For inline documentation this is also possible
by starting with the direction attribute, e.g.
......@@ -302,11 +269,54 @@ Here is an example of the use of these comment blocks:
(like <code>\\class</code>) are not allowed
inside these comment blocks.
\section structuralcommands Documentation at other places
\subsubsection docexamples Examples
Here is an example of a documented piece of C++ code using the Qt style:
\include qtstyle.cpp
\htmlonly
Click <a href="$(DOXYGEN_DOCDIR)/examples/qtstyle/html/class_test.html">here</a>
for the corresponding HTML documentation that is generated by doxygen.
\endhtmlonly
The brief descriptions are included in the member overview of a
class, namespace or file and are printed using a small italic font
(this description can be hidden by setting
\ref cfg_brief_member_desc "BRIEF_MEMBER_DESC" to \c NO in
the config file). By default the brief descriptions become the first
sentence of the detailed descriptions
(but this can be changed by setting the \ref cfg_repeat_brief "REPEAT_BRIEF"
tag to \c NO). Both the brief and the detailed descriptions are optional
for the Qt style.
By default a JavaDoc style documentation block behaves the same way as a
Qt style documentation block. This is not according the JavaDoc specification
however, where the first sentence of the documentation block is automatically
treated as a brief description. To enable this behavior you should set
\ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" to YES in the configuration
file. If you enable this option and want to put a dot in the middle of a
sentence without ending it, you should put a backslash and a space after it.
Here is an example:
\verbatim
/** Brief description (e.g.\ using only a few words). Details follow. */
\endverbatim
Here is the same piece of code as shown above, this time documented using the
JavaDoc style and \ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" set to YES:
\include jdstyle.cpp
\htmlonly
Click <a href="$(DOXYGEN_DOCDIR)/examples/jdstyle/html/class_test.html">here</a>
for the corresponding HTML documentation that is generated by doxygen.
\endhtmlonly
Similarly, if one wishes the first sentence of a Qt style documentation
block to automatically be treated as a brief description, one may set
\ref cfg_qt_autobrief "QT_AUTOBRIEF" to YES in the configuration file.
\subsubsection structuralcommands Documentation at other places
So far we have assumed that the documentation blocks are always located \e in
\e front of the declaration or definition of a file, class or namespace or in
front or after one of its members.
In the examples in the previous section the comment blocks were always located *in
front* of the declaration or definition of a file, class or namespace or *in
front* or *after* one of its members.
Although this is often comfortable, there may sometimes be reasons to put the
documentation somewhere else. For documenting a file this is even
required since there is no such thing as "in front of a file".
......@@ -321,7 +331,7 @@ structural command inside the documentation block, which leads to some
duplication of information. So in practice you should \e avoid the use of
structural commands \e unless other requirements force you to do so.
Structural commands (like all other commands) start with a backslash
Structural commands (like \ref cmd_intro "all other commands") start with a backslash
(<tt>\\</tt>), or an at-sign (<tt>\@</tt>) if you prefer JavaDoc style,
followed by a command name and one or more parameters.
For instance, if you want to document the class \c Test in the example
......@@ -384,7 +394,7 @@ using structural commands:
in comment blocks which are place in front of a function. This is clearly
a case where the \\fn command is redundant and will only lead to problems.
\section pythonblocks Special documentation blocks in Python
\subsection pythonblocks Comment blocks in Python
For Python there is a standard way of documenting the code using
so called documentation strings. Such strings are stored in \c __doc__
......@@ -423,7 +433,7 @@ Go to the <a href="lists.html">next</a> section or return to the
<a href="index.html">index</a>.
\endhtmlonly
\section vhdlblocks Special documentation blocks in VHDL
\subsection vhdlblocks Comment blocks in VHDL
For VHDL a comment normally start with "--". Doxygen will extract comments
starting with "--!". There are only two types of comment blocks in VHDL;
......@@ -449,7 +459,7 @@ config file. This will also affect a number of other settings. When they
were not already set correctly doxygen will produce a warning telling which
settings where overruled.
\section fortranblocks Special documentation blocks in Fortran
\subsection fortranblocks Comment blocks in Fortran
When using doxygen for Fortran code you should
set \ref cfg_optimize_for_fortran "OPTIMIZE_FOR_FORTRAN" to \c YES.
......@@ -481,7 +491,7 @@ C> input parameter
end function A
\endverbatim
\section tclblocks Documentation blocks in Tcl
\subsection tclblocks Comment blocks in Tcl
Doxygen documentation can be included in normal Tcl comments.
......@@ -548,4 +558,42 @@ Go to the <a href="lists.html">next</a> section or return to the
<a href="index.html">index</a>.
\endhtmlonly
\section docstructure Anatomy of a comment block
The previous section focussed on how to make the comments in your code known
to doxygen, it explained the difference between a brief and a detailed description, and
the use of structural commands.
In this section we look at the contents of the comment block itself.
Doxygen supports various styles of formatting your comments.
The simplest form is to use plain text. This will appear as-is in the output
and is ideal for a short description.
For longer descriptions you often will find the
need for some more structure, like a block of verbatim text, a list, or a
simple table. For this doxygen supports the
<a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a>
syntax, including parts of the
<a href="http://michelf.com/projects/php-markdown/extra/">Markdown Extra</a>
extension.
Markdown is designed to be very easy to read and write.
It's formatting is inspired by plain text mail.
Markdown works great for simple, generic formatting, like an introduction
page for your project. Doxygen also supports reading of markdown files
directly. See \ref markdown "here" for more details regards Markdown support.
For programming language specific formatting doxygen has two
forms of additional markup on top of Markdown formatting.
1. <a href="http://en.wikipedia.org/wiki/Javadoc">Javadoc</a> like markup.
See \ref cmd_intro "here" for a complete overview of all commands supported by doxygen.
2. <a href="http://en.wikipedia.org/wiki/C_Sharp_(programming_language)#XML_documentation_system">XML</a> markup
as specified in the C# standard. See \ref xmlcmds "here" for the XML commands supported by doxygen.
If this is still not enough doxygen also supports a \ref htmlcmds "subset" of
the <a href="http://en.wikipedia.org/wiki/HTML">HTML</a> markup language.
*/
......@@ -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 ----------------
......
/* The standard CSS for doxygen */
body, table, div, p, dl {
font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
font-size: 13px;
line-height: 1.3;
}
/* @group Heading Levels */
h1 {
font-size: 150%;
}
.title {
font-size: 150%;
font-weight: bold;
margin: 10px 2px;
}
h2 {
font-size: 120%;
}
h3 {
font-size: 100%;
}
dt {
font-weight: bold;
}
div.multicol {
-moz-column-gap: 1em;
-webkit-column-gap: 1em;
-moz-column-count: 3;
-webkit-column-count: 3;
}
p.startli, p.startdd, p.starttd {
margin-top: 2px;
}
p.endli {
margin-bottom: 0px;
}
p.enddd {
margin-bottom: 4px;
}
p.endtd {
margin-bottom: 2px;
}
/* @end */
caption {
font-weight: bold;
}
span.legend {
font-size: 70%;
text-align: center;
}
h3.version {
font-size: 90%;
text-align: center;
}
div.qindex, div.navtab{
background-color: #F1F1F1;
border: 1px solid #BDBDBD;
text-align: center;
}
div.qindex, div.navpath {
width: 100%;
line-height: 140%;
}
div.navtab {
margin-right: 15px;
}
/* @group Link Styling */
a {
color: #646494;
font-weight: normal;
text-decoration: none;
}
.contents a:visited {
color: #7474A4;
}
a:hover {
text-decoration: underline;
}
a.qindex {
font-weight: bold;
}
a.qindexHL {
font-weight: bold;
background-color: #B8B8B8;
color: #ffffff;
border: 1px double #A8A8A8;
}
.contents a.qindexHL:visited {
color: #ffffff;
}
a.el {
font-weight: bold;
}
a.elRef {
}
a.code, a.code:visited {
color: #4665A2;
}
a.codeRef, a.codeRef:visited {
color: #4665A2;
}
/* @end */
dl.el {
margin-left: -1cm;
}
.fragment {
font-family: monospace, fixed;
font-size: 105%;
}
pre.fragment {
border: 1px solid #D5D5D5;
background-color: #FCFCFC;
padding: 4px 6px;
margin: 4px 8px 4px 2px;
overflow: auto;
word-wrap: break-word;
font-size: 9pt;
line-height: 125%;
}
div.ah {
background-color: black;
font-weight: bold;
color: #ffffff;
margin-bottom: 3px;
margin-top: 3px;
padding: 0.2em;
border: solid thin #333;
border-radius: 0.5em;
-webkit-border-radius: .5em;
-moz-border-radius: .5em;
box-shadow: 2px 2px 3px #999;
-webkit-box-shadow: 2px 2px 3px #999;
-moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444));
background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000);
}
div.groupHeader {
margin-left: 16px;
margin-top: 12px;
font-weight: bold;
}
div.groupText {
margin-left: 16px;
font-style: italic;
}
body {
background-color: #CCCCCC;
color: black;
margin: 0;
}
div.contents {
margin-bottom: 10px;
padding: 8px;
margin-left: auto;
margin-right: auto;
width: 800px;
background-color: white;
-moz-border-radius-bottomleft: 8px;
-moz-border-radius-bottomright: 8px;
/* firefox specific markup */
-moz-box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 5px;
/* webkit specific markup */
-webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.15);
}
td.indexkey {
background-color: #F1F1F1;
font-weight: bold;
border: 1px solid #D5D5D5;
margin: 2px 0px 2px 0;
padding: 2px 10px;
white-space: nowrap;
vertical-align: top;
}
td.indexvalue {
background-color: #F1F1F1;
border: 1px solid #D5D5D5;
padding: 2px 10px;
margin: 2px 0px;
}
tr.memlist {
background-color: #F2F2F2;
}
p.formulaDsp {
text-align: center;
}
img.formulaDsp {
}
img.formulaInl {
vertical-align: middle;
}
div.center {
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
padding: 0px;
}
div.center img {
border: 0px;
}
address.footer {
text-align: right;
padding-right: 12px;
background-color: #8080A0;
color: white;
}
img.footer {
border: 0px;
vertical-align: middle;
}
/* @group Code Colorization */
span.keyword {
color: #008000
}
span.keywordtype {
color: #604020
}
span.keywordflow {
color: #e08000
}
span.comment {
color: #800000
}
span.preprocessor {
color: #806020
}
span.stringliteral {
color: #002080
}
span.charliteral {
color: #008080
}
span.vhdldigit {
color: #ff00ff
}
span.vhdlchar {
color: #000000
}
span.vhdlkeyword {
color: #700070
}
span.vhdllogic {
color: #ff0000
}
blockquote {
background-color: #F9F9F9;
border-left: 2px solid #B8B8B8;
margin: 0 24px 0 4px;
padding: 0 12px 0 16px;
}
/* @end */
/*
.search {
color: #003399;
font-weight: bold;
}
form.search {
margin-bottom: 0px;
margin-top: 0px;
}
input.search {
font-size: 75%;
color: #000080;
font-weight: normal;
background-color: #e8eef2;
}
*/
td.tiny {
font-size: 75%;
}
.dirtab {
padding: 4px;
border-collapse: collapse;
border: 1px solid #BDBDBD;
}
th.dirtab {
background: #F1F1F1;
font-weight: bold;
}
hr {
height: 0px;
border: none;
border-top: 1px solid #7A7A7A;
}
hr.footer {
display: none;
}
/* @group Member Descriptions */
table.memberdecls {
border-spacing: 0px;
padding: 0px;
}
.mdescLeft, .mdescRight,
.memItemLeft, .memItemRight,
.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
background-color: #FAFAFA;
border: none;
margin: 4px;
padding: 1px 0 0 8px;
}
.mdescLeft, .mdescRight {
padding: 0px 8px 4px 8px;
color: #555;
}
.memItemLeft, .memItemRight, .memTemplParams {
border-top: 1px solid #D5D5D5;
}
.memItemLeft, .memTemplItemLeft {
white-space: nowrap;
}
.memItemRight {
width: 100%;
}
.memTemplParams {
color: #747474;
white-space: nowrap;
}
/* @end */
/* @group Member Details */
/* Styles for detailed member documentation */
.memtemplate {
font-size: 80%;
color: #747474;
font-weight: normal;
margin-left: 9px;
}
.memnav {
background-color: #F1F1F1;
border: 1px solid #BDBDBD;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
.mempage {
width: 100%;
}
.memitem {
padding: 0;
margin-bottom: 10px;
margin-right: 5px;
}
.memname {
white-space: nowrap;
font-weight: bold;
margin-left: 6px;
}
.memproto, dl.reflist dt {
border-top: 1px solid #C0C0C0;
border-left: 1px solid #C0C0C0;
border-right: 1px solid #C0C0C0;
padding: 6px 0px 6px 0px;
color: #3D3D3D;
font-weight: bold;
text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9);
/* opera specific markup */
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
border-top-right-radius: 8px;
border-top-left-radius: 8px;
/* firefox specific markup */
-moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
-moz-border-radius-topright: 8px;
-moz-border-radius-topleft: 8px;
/* webkit specific markup */
-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
-webkit-border-top-right-radius: 8px;
-webkit-border-top-left-radius: 8px;
background-image:url('nav_f.png');
background-repeat:repeat-x;
background-color: #EAEAEA;
}
.memdoc, dl.reflist dd {
border-bottom: 1px solid #C0C0C0;
border-left: 1px solid #C0C0C0;
border-right: 1px solid #C0C0C0;
padding: 2px 5px;
background-color: #FCFCFC;
border-top-width: 0;
/* opera specific markup */
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
/* firefox specific markup */
-moz-border-radius-bottomleft: 8px;
-moz-border-radius-bottomright: 8px;
-moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px;
background-image: -moz-linear-gradient(center top, #FFFFFF 0%, #FFFFFF 60%, #F9F9F9 95%, #F2F2F2);
/* webkit specific markup */
-webkit-border-bottom-left-radius: 8px;
-webkit-border-bottom-right-radius: 8px;
-webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
background-image: -webkit-gradient(linear,center top,center bottom,from(#FFFFFF), color-stop(0.6,#FFFFFF), color-stop(0.60,#FFFFFF), color-stop(0.95,#F9F9F9), to(#F2F2F2));
}
dl.reflist dt {
padding: 5px;
}
dl.reflist dd {
margin: 0px 0px 10px 0px;
padding: 5px;
}
.paramkey {
text-align: right;
}
.paramtype {
white-space: nowrap;
}
.paramname {
color: #602020;
white-space: nowrap;
}
.paramname em {
font-style: normal;
}
.params, .retval, .exception, .tparams {
border-spacing: 6px 2px;
}
.params .paramname, .retval .paramname {
font-weight: bold;
vertical-align: top;
}
.params .paramtype {
font-style: italic;
vertical-align: top;
}
.params .paramdir {
font-family: "courier new",courier,monospace;
vertical-align: top;
}
/* @end */
/* @group Directory (tree) */
/* for the tree view */
.ftvtree {
font-family: sans-serif;
margin: 0px;
}
/* these are for tree view when used as main index */
.directory {
font-size: 9pt;
font-weight: bold;
margin: 5px;
}
.directory h3 {
margin: 0px;
margin-top: 1em;
font-size: 11pt;
}
/*
The following two styles can be used to replace the root node title
with an image of your choice. Simply uncomment the next two styles,
specify the name of your image and be sure to set 'height' to the
proper pixel height of your image.
*/
/*
.directory h3.swap {
height: 61px;
background-repeat: no-repeat;
background-image: url("yourimage.gif");
}
.directory h3.swap span {
display: none;
}
*/
.directory > h3 {
margin-top: 0;
}
.directory p {
margin: 0px;
white-space: nowrap;
}
.directory div {
display: none;
margin: 0px;
}
.directory img {
vertical-align: -30%;
}
/* these are for tree view when not used as main index */
.directory-alt {
font-size: 100%;
font-weight: bold;
}
.directory-alt h3 {
margin: 0px;
margin-top: 1em;
font-size: 11pt;
}
.directory-alt > h3 {
margin-top: 0;
}
.directory-alt p {
margin: 0px;
white-space: nowrap;
}
.directory-alt div {
display: none;
margin: 0px;
}
.directory-alt img {
vertical-align: -30%;
}
/* @end */
div.dynheader {
margin-top: 8px;
}
address {
font-style: normal;
color: #464646;
}
table.doxtable {
border-collapse:collapse;
margin-top: 4px;
margin-bottom: 4px;
}
table.doxtable td, table.doxtable th {
border: 1px solid #4A4A4A;
padding: 3px 7px 2px;
}
table.doxtable th {
background-color: #5B5B5B;
color: #FFFFFF;
font-size: 110%;
padding-bottom: 4px;
padding-top: 5px;
text-align:left;
}
table.fieldtable {
width: 100%;
margin-bottom: 10px;
border: 1px solid #C0C0C0;
border-spacing: 0px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px;
-webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15);
}
.fieldtable td, .fieldtable th {
padding: 3px 7px 2px;
}
.fieldtable td.fieldtype, .fieldtable td.fieldname {
white-space: nowrap;
border-right: 1px solid #C0C0C0;
border-bottom: 1px solid #C0C0C0;
vertical-align: top;
}
.fieldtable td.fielddoc {
border-bottom: 1px solid #C0C0C0;
width: 100%;
}
.fieldtable tr:last-child td {
border-bottom: none;
}
.fieldtable th {
background-image:url('nav_f.png');
background-repeat:repeat-x;
background-color: #EAEAEA;
font-size: 90%;
color: #3D3D3D;
padding-bottom: 4px;
padding-top: 5px;
text-align:left;
-moz-border-radius-topleft: 4px;
-moz-border-radius-topright: 4px;
-webkit-border-top-left-radius: 4px;
-webkit-border-top-right-radius: 4px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom: 1px solid #C0C0C0;
}
.tabsearch {
top: 0px;
left: 10px;
height: 36px;
background-image: url('tab_b.png');
z-index: 101;
overflow: hidden;
font-size: 13px;
}
.navpath ul
{
font-size: 11px;
background-image:url('tab_b.png');
background-repeat:repeat-x;
height:30px;
line-height:30px;
color:#ABABAB;
border:solid 1px #D3D3D3;
overflow:hidden;
margin:0px;
padding:0px;
}
.navpath li
{
list-style-type:none;
float:left;
padding-left:10px;
padding-right:15px;
background-image:url('bc_s.png');
background-repeat:no-repeat;
background-position:right;
color:#595959;
}
.navpath li.navelem a
{
height:32px;
display:block;
text-decoration: none;
outline: none;
}
.navpath li.navelem a:hover
{
color:#929292;
}
.navpath li.footer
{
list-style-type:none;
float:right;
padding-left:10px;
padding-right:15px;
background-image:none;
background-repeat:no-repeat;
background-position:right;
color:#595959;
font-size: 8pt;
}
div.summary
{
float: right;
font-size: 8pt;
padding-right: 5px;
width: 50%;
text-align: right;
}
div.summary a
{
white-space: nowrap;
}
div.ingroups
{
margin-left: 5px;
font-size: 8pt;
padding-left: 5px;
width: 50%;
text-align: left;
}
div.ingroups a
{
white-space: nowrap;
}
div.header
{
background-image:url('nav_h.png');
background-repeat:repeat-x;
background-color: #FAFAFA;
border-bottom: 1px solid #D5D5D5;
margin-left: auto;
margin-right: auto;
width: 800px;
padding-left: 8px;
padding-right: 8px;
/* firefox specific markup */
-moz-box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 5px;
/* webkit specific markup */
-webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.15);
}
div.headertitle
{
padding: 5px 5px 5px 7px;
}
dl
{
padding: 0 0 0 10px;
}
dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug
{
border-left:4px solid;
padding: 0 0 0 6px;
}
dl.note
{
border-color: #D0C000;
}
dl.warning, dl.attention
{
border-color: #FF0000;
}
dl.pre, dl.post, dl.invariant
{
border-color: #00D000;
}
dl.deprecated
{
border-color: #505050;
}
dl.todo
{
border-color: #00C0E0;
}
dl.test
{
border-color: #3030E0;
}
dl.bug
{
border-color: #C08050;
}
#projectlogo
{
text-align: center;
vertical-align: bottom;
border-collapse: separate;
}
#projectlogo img
{
border: 0px none;
}
#projectname
{
font: 300% Tahoma, Arial,sans-serif;
margin: 0px;
padding: 2px 0px;
}
#projectbrief
{
font: 120% Tahoma, Arial,sans-serif;
margin: 0px;
padding: 0px;
}
#projectnumber
{
font: 50% Tahoma, Arial,sans-serif;
margin: 0px;
padding: 0px;
}
#titlearea
{
padding: 0px;
margin: 0px;
width: 100%;
border-bottom: 1px solid #848484;
}
.image
{
text-align: center;
}
.dotgraph
{
text-align: center;
}
.mscgraph
{
text-align: center;
}
.caption
{
font-weight: bold;
}
div.zoom
{
border: 1px solid #AFAFAF;
}
dl.citelist {
margin-bottom:50px;
}
dl.citelist dt {
color:#545454;
float:left;
font-weight:bold;
margin-right:10px;
padding:5px;
}
dl.citelist dd {
margin:2px 0;
padding:5px 0;
}
@media print
{
#top { display: none; }
#side-nav { display: none; }
#nav-path { display: none; }
body { overflow:visible; }
h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
.summary { display: none; }
.memitem { page-break-inside: avoid; }
#doc-content
{
margin-left:0 !important;
height:auto !important;
width:auto !important;
overflow:inherit;
display:inline;
}
pre.fragment
{
overflow: visible;
text-wrap: unrestricted;
white-space: -moz-pre-wrap; /* Moz */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
white-space: pre-wrap; /* CSS3 */
word-wrap: break-word; /* IE 5.5+ */
}
}
......@@ -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:
......
/******************************************************************************
*
*
*
* Copyright (C) 1997-2011 by Dimitri van Heesch.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation under the terms of the GNU General Public License is hereby
* granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
* Documents produced by Doxygen are derivative works derived from the
* input used in their production; they are not affected by this license.
*
*/
/*! \page markdown Markdown support
Table of contents
- \ref markdown_std
- \ref md_para
- \ref md_headers
- \ref md_blockquotes
- \ref md_lists
- \ref md_codeblock
- \ref md_rulers
- \ref md_emphasis
- \ref md_codespan
- \ref md_links
- \ref md_inlinelinks
- \ref md_reflinks
- \ref md_images
- \ref md_autolink
- \ref markdown_extra
- \ref md_tables
- \ref md_fenced
- \ref md_header_id
- \ref markdown_dox
- \ref md_page_header
- \ref md_html_blocks
- \ref mddox_code_blocks
- \ref mddox_code_spans
- \ref mddox_lists
- \ref mddox_stars
- \ref mddox_limits
- \ref markdown_debug
[Markdown] support
was introduced in doxygen version 1.8.0. It is a plain text formatting
syntax written by John Gruber, with the following underlying design goal:
> The design goal for Markdown’s formatting syntax is to
> make it as readable as possible. The idea is that a Markdown-formatted
> document should be publishable as-is, as plain text, without
> looking like it’s been marked up with tags or formatting instructions.
> While Markdown’s syntax has been influenced by several existing
> text-to-HTML filters, the single biggest source of inspiration
> for Markdown’s syntax is the format of plain text email.
In the \ref markdown_std "next section" the standard markdown features
are briefly discussed. The reader is referred to the [Markdown site][markdown]
for more details.
Some enhancements were made, for instance [PHP Markdown Extra][mdextra], and
[GitHub flavored Markdown][github]. The section \ref markdown_extra discusses
the extensions that doxygen supports.
Finally section \ref markdown_dox discusses some specifics for doxygen's
implementation of the Markdown standard.
[markdown]: http://daringfireball.net/projects/markdown
[mdextra]: http://michelf.com/projects/php-markdown/extra/
[github]: http://github.github.com/github-flavored-markdown/
\section markdown_std Standard Markdown
\subsection md_para Paragraphs
Even before doxygen had Markdown support it supported the same way
of paragraph handling as Markdown: to make a paragraph you just separate
consecutive lines of text by one or more blank lines.
An example:
Here is text for one paragraph.
We continue with more text in another paragraph.
\subsection md_headers Headers
Just like Markdown, doxygen supports two types of headers
Level 1 or 2 headers can be made as the follows
This is an level 1 header
=========================
This is an level 2 header
-------------------------
A header is followed by a line containing only ='s or -'s.
Note that the exact amount of ='s or -'s is not important.
Alternatively, you can use #'s at the start of a line to make a header.
The number of #'s at the start of the line determines the level (up to 6 levels are supported).
You can end a header by any number of #'s.
Here is an example:
# This is a level 1 header
### This is level 3 header #######
\subsection md_blockquotes Block quotes
Block quotes can be created by starting each line with one or more >'s,
similar to what is used in text-only emails.
> This is a block quote
> spanning multiple lines
Lists and code blocks (see below) can appear inside a quote block.
Quote blocks can also be nested.
Note that doxygen requires that you put a space after the (last) > character
to avoid false positives, i.e. when writing
0 if OK\n
>1 if NOK
the second line will not seen as a block quote.
\subsection md_lists Lists
Simple bullet lists can be made by starting a line with -, +, or *.
- Item 1
More text for this item.
- Item 2
+ nested list item.
+ another nested item.
- Item 3
List items can span multiple paragraphs (if each paragraph starts with
the proper indentation) and lists can be nested.
You can also make a numbered list like so
1. First item.
2. Second item.
\subsection md_codeblock Code Blocks
Preformatted verbatim blocks can be created by indenting
each line in a block of text by at least 4 extra spaces
This a normal paragraph
This is a code block
We continue with a normal paragraph again.
Doxygen will remove the mandatory indentation from the code block.
Note that you cannot start a code block in the middle of a paragraph
(i.e. the line preceding the code block must be empty).
See section \ref mddox_code_blocks for more info how doxygen handles
indentation as this is slightly different than standard Markdown.
\subsection md_rulers Horizontal Rulers
A horizontal ruler will be produced for lines containing at least three or more
hyphens, asterisks, or underscores. The line may also include any amount of whitespace.
Examples:
- - -
______
Note that using asterisks in comment blocks does not work. See
\ref mddox_stars for details.
\subsection md_emphasis Emphasis
To emphasize a text fragment you start and end the fragment with an underscore or star.
Using two stars or underscores will produce strong emphasis.
Examples:
*single asterisks*
_single underscores_
**double asterisks**
__double underscores__
Note that unlike standard Markdown, doxygen will not touch internal underscores or
stars, so the following will appear as-is:
a_nice_identifier
\subsection md_codespan code spans
To indicate a span of code, you should wrap it in backticks (`). Unlike code blocks,
code spans appear inline in a paragraph. An example:
Use the `printf()` function.
To show a literal backtick inside a code span use double backticks, i.e.
To assign the output of command `ls` to `var` use ``var=`ls```.
See section \ref mddox_code_spans for more info how doxygen handles
code spans slightly different than standard Markdown.
\subsection md_links Links
Doxygen supports both styles of make links defined by Markdown: *inline* and *reference*.
For both styles the link definition starts with the link text delimited by [square
brackets].
\subsubsection md_inlinelinks Inline Links
For an inline link the link text is followed by a URL and an optional link title which
together are enclosed in a set of regular parenthesis.
The link title itself is surrounded by quotes.
Examples:
[The link text](http://example.net/)
[The link text](http://example.net/ "Link title")
[The link text](/relative/path/to/index.html "Link title")
[The link text](somefile.html)
In addition doxygen provides a similar way to link a documented entity:
[The link text](@ref MyClass)
\subsubsection md_reflinks Reference Links
Instead of putting the URL inline, you can also define the link separately
and then refer to it from within the text.
The link definition looks as follows:
[link name]: http://www.example.com "Optional title"
Instead of double quotes also single quotes or parenthesis can
be used for the title part.
Once defined, the link looks as follows
[link text][link name]
If the link text and name are the same, also
[link name][]
or even
[link name]
can be used to refer to the link.
Note that the link name matching is not case sensitive
as is shown in the following example:
I get 10 times more traffic from [Google] than from
[Yahoo] or [MSN].
[google]: http://google.com/ "Google"
[yahoo]: http://search.yahoo.com/ "Yahoo Search"
[msn]: http://search.msn.com/ "MSN Search"
Link definitions will not be visible in the output.
Like for inline links doxygen also supports \@ref inside a link definition:
[myclass]: @ref MyClass "My class"
\subsection md_images Images
Markdown syntax for images is similar to that for links.
The only difference is an additional ! before the link text.
Examples:
![Caption text](/path/to/img.jpg)
![Caption text](/path/to/img.jpg "Image title")
![Caption text][img def]
![img def]
[img def]: /path/to/img.jpg "Optional Title"
Also here you can use \@ref to link to an image:
![Caption text](@ref image.png)
![img def]
[img def]: @ref image.png "Caption text"
The caption text is optional.
\subsection md_autolink Automatic Linking
To create a link to an URL or e-mail address Markdown supports the following
syntax:
<http://www.example.com>
<address@example.com>
Note that doxygen will also produce the links without the angle brackets.
\section markdown_extra Markdown Extensions
\subsection md_tables Tables
Of the features defined by "Markdown Extra" is support for
<a href="http://michelf.com/projects/php-markdown/extra/#table">simple tables</a>:
A table consists of a header line, a separator line, and at least one
row line. Table columns are separated by the pipe (!) character.
Here is an example:
First Header | Second Header
------------- | -------------
Content Cell | Content Cell
Content Cell | Content Cell
which will produce the following table:
First Header | Second Header
------------- | -------------
Content Cell | Content Cell
Content Cell | Content Cell
Column alignment can be controlled via one or two colons
at the header separator line:
| Right | Center | Left |
| ----: | :----: | :---- |
| 10 | 10 | 10 |
| 1000 | 1000 | 1000 |
which will look as follows:
| Right | Center | Left |
| ----: | :----: | :---- |
| 10 | 10 | 10 |
| 1000 | 1000 | 1000 |
\subsection md_fenced Fenced Code Blocks
Another feature defined by "Markdown Extra" is support for
<a href="http://michelf.com/projects/php-markdown/extra/#fenced-code-blocks">
fenced code blocks</a>:
A fenced code block does not require indentation, and is
defined by a pair of "fence lines". Such a line consists of 3 or
more tile (~) characters on a line. The end of the block should have the
same number of tildes. Here is an example:
This is a paragraph introducing:
~~~~~~~~~~~~~~~~~~~~~
a one-line code block
~~~~~~~~~~~~~~~~~~~~~
The contents of the code block is syntax highlighted.
The default language is based on the file it was found in
(i.e. a fenced block in a Python file is assumed to be Python code).
In case the language is not clear from the context or you want to
indicate a specific language you can add the language's extension after
the opening fence:
~~~~~~~~~~~~~{.py}
# A class
class Dummy:
pass
~~~~~~~~~~~~~
will produce:
~~~~~~~~~~~~~{.py}
# A class
class Dummy:
pass
~~~~~~~~~~~~~
and
~~~~~~~~~~~~~~~{.c}
int func(int a,int b) { return a*b; }
~~~~~~~~~~~~~~~
will produce:
~~~~~~~~~~~~~~~{.c}
int func(int a,int b) { return a*b; }
~~~~~~~~~~~~~~~
The curly brances and dot are optional by the way.
\subsection md_header_id Header Id Attributes
Standard Markdown has no support for labeling headers, which
is a problem if you want to link to a section.
PHP Markdown Extra allows you to label a header by adding
the following to the header
Header 1 {#labelid}
========
## Header 2 ## {#labelid2}
To link to a section in the same comment block you can use
[Link text](#labelid)
to link to a section in general, doxygen allows you to use \@ref
[Link text](@ref labelid)
Note this only works for the headers of level 1 to 4.
\section markdown_dox Doxygen specifics
Even doxygen tries to following the Markdown standard as closely as
possible, there are couple of deviation and doxygen specifics additions.
\subsection md_page_header Including Markdown files as pages
Doxygen can process files with Markdown formatting.
For this to work the extension for such a file should
be `.md` or `.markdown` (see
\ref cfg_extension_mapping "EXTENSION_MAPPING" if your Markdown files have
a different extension, and use `md` as the name of the parser).
Each file is converted to a page (see the \ref cmdpage "page" command for
details).
By default the name and title of the page are derived from the file name.
If the file starts with a level 1 header however, it is used as the title
of the page. If you specify a label for the
header (as shown \ref md_header_id "here") doxygen will use that as the
page name.
If the label is called `index` or `mainpage` doxygen will put the
documentation on the front page (`index.html`).
Here is an example of a file `README.md` that will appear as the main page
when processed by doxygen:
My Main Page {#mainpage}
============
Documentation that will appear on the main page
\subsection md_html_blocks Treatment of HTML blocks
Markdown is quite strict in the way it processes block-level HTML:
> block-level HTML elements — e.g.
> `<div>`, `<table>`, `<pre>`, `<p>`, etc. —
> must be separated from surrounding content by blank lines,
> and the start and end tags of the block should not be indented
> with tabs or spaces.
Doxygen does not have this requirement, and will also process
Markdown formatting inside such HTML blocks. The only exception is
`<pre>` blocks, which are passed untouched (handy for ASCII art).
Doxygen will not process Markdown formatting inside verbatim or code blocks,
and in other sections that need to be processed without changes
(for instance formulas or inline dot graphs).
\subsection mddox_code_blocks Code Block Indentation
With markdown any block that is indented by 4 spaces (and 8 spaces
inside lists) is treated as a code block. This indentation amount
is absolute, i.e. counting from the start of the line.
Since doxygen comments can appear at any indentation level
that is required by the programming language, it
uses a relative indentation instead. The amount of
indentation is counted relative to the preceding paragraph.
In case there is no preceding paragraph (i.e. you want to start with a
code block), the minimal amount of indentation of the whole comment block
is used as a reference.
In most cases this difference does not result in different output.
Only if you play with the indentation of paragraphs the difference
is noticeable:
text
text
text
code
In this case Markdown will put the word code in a code block,
whereas Doxygen will treat it as normal text, since although the absolute
indentation is 4, the indentation with respect to the previous paragraph
is only 1.
Note that list markers are not counted when determining the
relative indent:
1. Item1
More text for item1
2. Item2
Code block for item2
For Item1 the indentation is 4 (when treating the list marker as whitespace),
so the next paragraph "More text..." starts at the same indentation level
and is therefore not seen as a code block.
\subsection mddox_code_spans Code Spans Limits
Note that unlike standard Markdown, doxygen leaves the following untouched.
A `cool' word in a `nice' sentence.
In other words; a single quote cancels the special treatment of a code span
wrapped in a pair of backtick characters. This extra restriction was
added for backward compatibility reasons.
\subsection mddox_lists Lists Extensions
With Markdown two lists separated by an empty line are joined together into
a single list which can be rather unexpected and many people consider it to
be a bug. Doxygen, however, will make two separate lists as you would expect.
Example:
- Item1 of list 1
- Item2 of list 1
1. Item1 of list 2
2. Item2 of list 2
Historically doxygen has an additional way to create numbered
lists by using `-#` markers:
-# item1
-# item2
\subsection mddox_stars Use of asterisks
Special care has to be taken when using *'s in a comment block
to start a list or make a ruler.
Doxygen will strip off any leading *'s from the comment before doing
Markdown processing. So although the following works fine
@verbatim
/** A list:
* * item1
* * item2
*/
@endverbatim
When you remove the leading *'s doxygen will strip the other stars
as well, making the list disappear!
Rulers created with *'s will not be visible at all. They only work
in Markdown files.
\subsection mddox_limits Limits on markup scope
To avoid that a stray * or _ matches something many paragraphs later,
and shows everything in between with emphasis, doxygen limits the scope
of a * and _ to a single paragraph.
For code span, between the starting and ending backtick only two
new lines are allowed.
Also for links there are limits; the link text, and link title each can
contain only one new line, the URL may not contain any newlines.
\section markdown_debug Debugging problems
When doxygen parses the source code it first extracts the comments blocks,
then passes these through the Markdown preprocessor. The output of the
Markdown preprocessing consists of text with \ref cmd_intro "special commands"
and \ref htmlcmds "HTML commands".
A second pass takes the output of the Markdown preprocessor and
converts it into the various output formats.
During Markdown preprocessing no errors are produced. Anything that
does not fit the Markdown syntax is simply passed on as-is. In the subsequent
parsing phase this could lead to errors, which may not always be obvious
as they are based on the intermediate format.
To see the result after Markdown processing you can run doxygen with the
`-d Markdown` option. It will then print each comment block before and
after Markdown processing.
*/
......@@ -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>
......
......@@ -30,7 +30,7 @@ The following figure shows the relation between the tools and the flow
of information between them (it looks complex but that's only because it
tries to be complete):
\image html infoflow.gif "Doxygen information flow"
\image html infoflow.png "Doxygen information flow"
\image latex infoflow.eps "Doxygen information flow" width=14cm
\section step0 Step 0: Check if doxygen supports your programming language
......@@ -90,26 +90,50 @@ If you have a larger project consisting of a source directory or tree
you should assign the root directory or
directories to the \ref cfg_input "INPUT" tag, and add one or more file
patterns to the \ref cfg_file_patterns "FILE_PATTERNS" tag
(for instance <code>*.cpp *.h</code>). Only files that match one of the
(for instance `*.cpp *.h`). Only files that match one of the
patterns will be parsed (if the patterns are omitted a list of
source extensions is used).
typical patterns is used for the types of files doxygen supports).
For recursive parsing of a source tree you must set
the \ref cfg_recursive "RECURSIVE" tag to \c YES. To further fine-tune the
list of files that is parsed the \ref cfg_exclude "EXCLUDE" and
\ref cfg_exclude_patterns "EXCLUDE_PATTERNS" tags can be used.
To omit all \c test directories from a source tree for instance, one could use:
\verbatim EXCLUDE_PATTERNS = */test/*
\endverbatim
Doxygen looks at the file's extension to determine how to parse a file.
If a file has an <code>.idl</code> or <code>.odl</code> extension it is
treated as an IDL file. If it has a <code>.java</code> extension it is
treated as a file written in Java. Files ending with <code>.cs</code> are
treated as C# files and the <code>.py</code> extension selects the
Python parser. Finally, files with the extensions <code>.php</code>, <code>.php4</code>,
<code>.inc</code> or <code>.phtml</code> are treated as PHP sources.
Any other extension is parsed as if it is a C/C++ file, where files that
end with <code>.m</code> are treated as Objective-C source files.
Doxygen looks at the file's extension to determine how to parse a file,
using the following table:
Extension | Language
---------:|---------
.idl |IDL
.ddl |IDL
.odl |IDL
.java |Java
.cs |C#
.d |D
.php |PHP
.php4 |PHP
.php5 |PHP
.inc |PHP
.phtml |PHP
.m |Objective-C
.M |Objective-C
.mm |Objective-C
.py |Python
.f |Fortran
.for |Fortran
.f90 |Fortran
.vhd |VHDL
.vhdl |VHDL
.tcl |TCL
.ucf |VHDL
.qsf |VHDL
.md |Markdown
.markdown |Markdown
Any other extension is parsed as if it is a C/C++ file.
\anchor extract_all
If you start using doxygen for an existing project (thus without any
......@@ -159,12 +183,12 @@ a whole path recursively, like <code>mkdir -p</code> does).
The generated HTML documentation can be viewed by pointing a HTML browser
to the \c index.html file in the \c html directory. For the best results
a browser that supports cascading style sheets (CSS) should be used
(I'm using Mozilla, Safari, Konqueror, and sometimes IE6 to test the
generated output).
(I'm using Mozilla Firefox, Google Chrome, Safari, and sometimes
IE8, IE9, and Opera to test the generated output).
Some of the features the HTML section (such as
\ref cfg_generate_treeview "GENERATE_TREEVIEW" or the search engine)
require a browser that supports DHTML and Javascript.
require a browser that supports Dynamic HTML and Javascript enabled.
\subsection latex_out LaTeX output
\addindex LaTeX
......@@ -176,18 +200,18 @@ documentation, \c doxygen writes a \c Makefile into the \c latex directory.
The contents and targets in the \c Makefile depend on the setting of
\ref cfg_use_pdflatex "USE_PDFLATEX". If it is disabled (set to \c NO), then
typing \c make in the \c latex directory a dvi file called \c refman.dvi
typing \c make in the \c latex directory a \c dvi file called \c refman.dvi
will be generated. This file can then be viewed using \c xdvi or
converted into a PostScript file \c refman.ps by
typing <code>make ps</code> (this requires <code>dvips</code>).
typing `make ps` (this requires `dvips`).
To put 2 pages on one physical page use <code>make ps_2on1</code> instead.
To put 2 pages on one physical page use `make ps_2on1` instead.
The resulting PostScript file can be send to a PostScript
printer. If you do not have a PostScript printer, you can try to use
ghostscript to convert PostScript into something your printer understands.
Conversion to PDF is also possible if you have installed the ghostscript
interpreter; just type <code>make pdf</code> (or <code>make pdf_2on1</code>).
interpreter; just type `make pdf` (or `make pdf_2on1`).
To get the best results for PDF output you should set
the \ref cfg_pdf_hyperlinks "PDF_HYPERLINKS"
......@@ -207,21 +231,21 @@ the option from the drop down menu).
\addindex XML
The XML output consists of a structured "dump" of the information gathered
by doxygen. Each compound (class/namespace/file/...) has its own XML file
and there is also an index file called index.xml.
and there is also an index file called `index.xml`.
A file called combine.xslt
A file called `combine.xslt`
XSLT script is also generated and can be used to combine all XML files
into a single file.
Doxygen also generates two XML schema files index.xsd
(for the index file) and compound.xsd (for the compound files).
Doxygen also generates two XML schema files `index.xsd`
(for the index file) and `compound.xsd` (for the compound files).
This schema file describes the possible elements, their attributes and
how they are structured, i.e. it the describes the grammar of the XML
files and can be used for validation or to steer XSLT scripts.
In the addon/doxmlparser directory you can find a parser library for reading
In the `addon/doxmlparser` directory you can find a parser library for reading
the XML output produced by doxygen in an incremental way
(see addon/doxmlparser/include/doxmlintf.h for the interface of the library)
(see `addon/doxmlparser/include/doxmlintf.h` for the interface of the library)
\subsection man_out Man page output
The generated man pages can be viewed using the \c man program. You do need
......@@ -235,56 +259,63 @@ capabilities of the man page format, so some information
Although documenting the sources is presented as step 3, in a new project
this should of course be step 1. Here I assume
you already have some code and you want doxygen to generate a nice document
describing the API and maybe the internals as well.
describing the API and maybe the internals and some related design
documentation as well.
If the \ref cfg_extract_all "EXTRACT_ALL" option is set to \c NO in the
configuration file (the default), then doxygen will only generate
documentation for \e documented members, files, classes and namespaces. So
documentation for \e documented entities. So
how do you document these? For members, classes and namespaces there are
basically two options:
<ol>
<li>Place a \e special documentation block in front of the declaration or
1. Place a \e special documentation block in front of the declaration or
definition of the member, class or namespace. For file, class and namespace
members it is also allowed to place the documentation directly after the
member. See section \ref specialblock to learn more about special
member.
See section \ref specialblock to learn more about special
documentation blocks.
<li>Place a special documentation block somewhere else (another file or
2. Place a special documentation block somewhere else (another file or
another location) \e and put a <em>structural command</em> in the
documentation block. A structural command links a documentation block
to a certain entity that can be documented (e.g. a member, class,
namespace or file). See section \ref structuralcommands to learn more
namespace or file).
See section \ref structuralcommands to learn more
about structural commands.
</ol>
The advantage of the first option is that you do not have to repeat the
name of the entity.
Files can only be documented using the second option, since there is
no way to put a documentation block before a file. Of course, file members
(functions, variables, typedefs, defines) do not need an explicit
structural command; just putting a special documentation block in front or
behind them will do.
behind them will work fine.
The text inside a special documentation block is parsed
before it is written to the HTML and/or \f$\mbox{\LaTeX}\f$ output files.
\addindex parsing
During parsing the following steps take place:
<ul>
<li> The special commands inside the documentation are executed. See
section \ref commands for an overview of all commands.
<li> If a line starts with some whitespace followed by one or more asterisks
(<tt>*</tt>) and then optionally more whitespace,
then all whitespace and asterisks are removed.
<li> All resulting blank lines are treated as a paragraph separators.
This saves you from placing new-paragraph commands yourself
in order to make the generated documentation readable.
<li> Links are created for words corresponding to documented classes
(unless the word is preceded by a \%; then the word will not be linked and
the \% sign is removed).
<li> Links to members are created when certain patterns are found in the
text. See section \ref autolink
for more information on how the automatic link generation works.
<li> HTML tags that are in the documentation are interpreted and converted
to \f$\mbox{\LaTeX}\f$ equivalents for the \f$\mbox{\LaTeX}\f$ output.
See section \ref htmlcmds for an overview of all supported HTML tags.
</ul>
- Markdown formatting is replaced by corresponding HTML or special
commands.
- The special commands inside the documentation are executed. See
section \ref commands for an overview of all commands.
- If a line starts with some whitespace followed by one or more asterisks
(`*`) and then optionally more whitespace,
then all whitespace and asterisks are removed.
- All resulting blank lines are treated as a paragraph separators.
This saves you from placing new-paragraph commands yourself
in order to make the generated documentation readable.
- Links are created for words corresponding to documented classes
(unless the word is preceded by a \%; then the word will not be linked and
the \% sign is removed).
- Links to members are created when certain patterns are found in the
text. See section \ref autolink
for more information on how the automatic link generation works.
- HTML tags that are in the documentation are interpreted and converted
to \f$\mbox{\LaTeX}\f$ equivalents for the \f$\mbox{\LaTeX}\f$ output.
See section \ref htmlcmds for an overview of all supported HTML tags.
\htmlonly
Go to the <a href="docblocks.html">next</a> section or return to the
......
......@@ -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 );
}
......
......@@ -285,7 +285,7 @@ void replaceComment(int offset);
%%
<Scan>[^"'!\/\n\\#\\-]* { /* eat anything that is not " / or \n */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<Scan>"\"\"\""! { /* start of python long comment */
if (g_lang!=SrcLangExt_Python)
......@@ -295,7 +295,7 @@ void replaceComment(int offset);
else
{
g_pythonDocString = TRUE;
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
}
}
......@@ -306,22 +306,22 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
}
}
<Scan>"\"" { /* start of a string */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
g_stringContext = YY_START;
BEGIN(SkipString);
}
<Scan>' {
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
g_charContext = YY_START;
BEGIN(SkipChar);
}
<Scan>\n { /* new line */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<Scan>("//!"|"///").*/\n[ \t]*"//"[\/!][^\/] { /* start C++ style special comment block */
if (g_mlBrief)
......@@ -352,13 +352,13 @@ void replaceComment(int offset);
BEGIN(SComment);
}
<Scan>"//"/.*\n { /* one line C++ comment */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
g_readLineCtx=YY_START;
BEGIN(ReadLine);
}
<Scan>"/*"[*!]? { /* start of a C comment */
g_specialComment=yyleng==3;
copyToOutput(yytext,yyleng);
g_specialComment=(int)yyleng==3;
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
}
<Scan>"#"("#")? {
......@@ -368,7 +368,7 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
}
}
......@@ -379,7 +379,7 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
}
}
......@@ -390,7 +390,7 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(CComment);
}
}
......@@ -402,14 +402,14 @@ void replaceComment(int offset);
BEGIN(VerbatimCode);
}
<CComment,ReadLine>[\\@]("dot"|"code"|"msc")/[^a-z_A-Z0-9] { /* start of a verbatim block */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
g_lastCommentContext = YY_START;
g_javaBlock=0;
g_blockName=&yytext[1];
BEGIN(VerbatimCode);
}
<CComment,ReadLine>[\\@]("f$"|"f["|"f{"[a-z]*) {
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
g_blockName=&yytext[1];
if (g_blockName.at(1)=='[')
{
......@@ -423,16 +423,16 @@ void replaceComment(int offset);
BEGIN(Verbatim);
}
<CComment,ReadLine>[\\@]("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"rtfonly"|"manonly")/[^a-z_A-Z0-9] { /* start of a verbatim block */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
g_blockName=&yytext[1];
g_lastCommentContext = YY_START;
BEGIN(Verbatim);
}
<Scan>. { /* any other character */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<Verbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"endrtfonly"|"endmanonly"|"f$"|"f]"|"f}") { /* end of verbatim block */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
if (yytext[1]=='f') // end of formula
{
BEGIN(g_lastCommentContext);
......@@ -450,7 +450,7 @@ void replaceComment(int offset);
else
{
g_javaBlock++;
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
}
<VerbatimCode>"}" {
......@@ -468,12 +468,12 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
}
}
<VerbatimCode>[\\@]("enddot"|"endcode"|"endmsc") { /* end of verbatim block */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
if (&yytext[4]==g_blockName)
{
BEGIN(g_lastCommentContext);
......@@ -482,14 +482,14 @@ void replaceComment(int offset);
<VerbatimCode>^[ \t]*"//"[\!\/]? { /* skip leading comments */
if (!g_inSpecialComment)
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
}
<Verbatim,VerbatimCode>[^@\/\\\n{}]* { /* any character not a backslash or new line or } */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<Verbatim,VerbatimCode>\n { /* new line in verbatim block */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<Verbatim,VerbatimCode>^[ \t]*"///" {
if (g_blockName=="dot" || g_blockName=="msc" || g_blockName.at(0)=='f')
......@@ -503,40 +503,40 @@ void replaceComment(int offset);
}
}
<Verbatim,VerbatimCode>. { /* any other character */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<SkipString>\\. { /* escaped character in string */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<SkipString>"\"" { /* end of string */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(g_stringContext);
}
<SkipString>. { /* any other string character */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<SkipString>\n { /* new line inside string (illegal for some compilers) */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<SkipChar>\\. { /* escaped character */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<SkipChar>' { /* end of character literal */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(g_charContext);
}
<SkipChar>. { /* any other string character */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<SkipChar>\n { /* new line character */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<CComment>[^\\!@*\n{\"]* { /* anything that is not a '*' or command */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<CComment>"*"+[^*/\\@\n{\"]* { /* stars without slashes */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<CComment>"\"\"\"" { /* end of Python docstring */
if (g_lang!=SrcLangExt_Python)
......@@ -546,12 +546,12 @@ void replaceComment(int offset);
else
{
g_pythonDocString = FALSE;
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
}
<CComment>\n { /* new line in comment */
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<CComment>"*"+"/" { /* end of C comment */
if (g_lang==SrcLangExt_Python)
......@@ -560,7 +560,7 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
}
......@@ -571,7 +571,7 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
}
......@@ -582,7 +582,7 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
}
......@@ -593,22 +593,22 @@ void replaceComment(int offset);
}
else
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
}
<CComment>"'" {
g_charContext = YY_START;
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(SkipChar);
}
<CComment>"\"" {
g_stringContext = YY_START;
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(SkipString);
}
<CComment>. {
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<SComment>^[ \t]*"///"[\/]*/\n {
replaceComment(0);
......@@ -666,17 +666,17 @@ void replaceComment(int offset);
}
<SComment>\n { /* end of special comment */
copyToOutput(" */",3);
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
g_inSpecialComment=FALSE;
g_inRoseComment=FALSE;
BEGIN(Scan);
}
<ReadLine>[^\\@\n]*/\n {
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(g_readLineCtx);
}
<CComment,ReadLine>[\\@][\\@][~a-z_A-Z][a-z_A-Z0-9]*[ \t]* { // escaped command
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
<CComment,ReadLine>[\\@]"cond"[ \t]+ { // conditional section
g_condCtx = YY_START;
......@@ -756,7 +756,7 @@ void replaceComment(int offset);
else // abort the alias, restart scanning
{
copyToOutput(g_aliasString,g_aliasString.length());
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
}
......@@ -794,7 +794,7 @@ void replaceComment(int offset);
g_lastEscaped=FALSE;
}
<ReadLine>. {
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
%%
......@@ -803,7 +803,7 @@ void replaceComment(int offset)
{
if (g_mlBrief)
{
copyToOutput(yytext,yyleng);
copyToOutput(yytext,(int)yyleng);
}
else
{
......@@ -811,12 +811,12 @@ void replaceComment(int offset)
int i=computeIndent(&yytext[offset]);
if (i==g_blockHeadCol)
{
replaceCommentMarker(yytext,yyleng);
replaceCommentMarker(yytext,(int)yyleng);
}
else
{
copyToOutput(" */",3);
int i;for (i=yyleng-1;i>=0;i--) unput(yytext[i]);
int i;for (i=(int)yyleng-1;i>=0;i--) unput(yytext[i]);
g_inSpecialComment=FALSE;
BEGIN(Scan);
}
......
......@@ -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";
......
......@@ -43,6 +43,14 @@
#include "util.h"
#include "doxygen.h"
#include "commentscan.h"
#include "entry.h"
//-----------
#define isIdChar(i) \
((data[(i)]>='a' && data[(i)]<='z') || \
(data[(i)]>='A' && data[(i)]<='Z') || \
(data[(i)]>='0' && data[(i)]<='9')) \
//----------
......@@ -62,6 +70,8 @@ enum Alignment { AlignNone, AlignLeft, AlignCenter, AlignRight };
static QDict<LinkRef> g_linkRefs(257);
static action_t g_actions[256];
static Entry *g_current;
static QCString g_fileName;
//static QDict<void> g_htmlBlockTags(17);
//----------
......@@ -206,11 +216,7 @@ static int findEmphasisChar(const char *data, int size, char c)
if (data[i] == c)
{
if (i<size-1 && ((data[i+1]>='a' && data[i+1]<='z') ||
(data[i+1]>='A' && data[i+1]<='Z') ||
(data[i+1]>='0' && data[i+1]<='9')
)
) // to prevent touching some_underscore_identifier
if (i<size-1 && isIdChar(i+1)) // to prevent touching some_underscore_identifier
{
i++;
continue;
......@@ -397,11 +403,110 @@ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c)
return 0;
}
static int processEmphasis(GrowBuf &out,const char *data,int,int size)
static int processHtmlTag(GrowBuf &out,const char *data,int offset,int size)
{
if (offset>0 && data[-1]=='\\') return 0; // escaped <
// find the end of the html tag
int i=1;
int l=0;
// compute length of the tag name
while (i<size && isIdChar(i)) i++,l++;
QCString tagName;
convertStringFragment(tagName,data+1,i-1);
if (tagName.lower()=="pre") // found <pre> tag
{
bool insideStr=FALSE;
while (i<size-6)
{
char c=data[i];
if (!insideStr && c=='<') // potential start of html tag
{
if (data[i+1]=='/' &&
tolower(data[i+2])=='p' && tolower(data[i+3])=='r' &&
tolower(data[i+4])=='e' && tolower(data[i+5])=='>')
{ // found </pre> tag, copy from start to end of tag
out.addStr(data,i+6);
//printf("found <pre>..</pre> [%d..%d]\n",0,i+6);
return i+6;
}
}
else if (insideStr && c=='"')
{
if (data[i-1]!='\\') insideStr=FALSE;
}
else if (c=='"')
{
insideStr=TRUE;
}
i++;
}
}
else // some other html tag
{
if (l>0 && i<size)
{
if (data[i]=='/' && i<size-1 && data[i+1]=='>') // <bla/>
{
//printf("Found htmlTag={%s}\n",QCString(data).left(i+2).data());
out.addStr(data,i+2);
return i+2;
}
else if (data[i]=='>') // <bla>
{
//printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data());
out.addStr(data,i+1);
return i+1;
}
else if (data[i]==' ') // <bla attr=...
{
i++;
bool insideAttr=FALSE;
while (i<size)
{
if (!insideAttr && data[i]=='"')
{
insideAttr=TRUE;
}
else if (data[i]=='"' && data[i-1]!='\\')
{
insideAttr=FALSE;
}
else if (!insideAttr && data[i]=='>') // found end of tag
{
//printf("Found htmlTag={%s}\n",QCString(data).left(i+1).data());
out.addStr(data,i+1);
return i+1;
}
i++;
}
}
}
}
//printf("Not a valid html tag\n");
return 0;
}
static int processEmphasis(GrowBuf &out,const char *data,int offset,int size)
{
if (offset>0 && size>1 && (isIdChar(-1) || data[-1]==data[0]))
{
if (isIdChar(1) || data[-1]==data[0])
{
// avoid processing interal * and _ as cmd_id, or 4*10 as emphasis,
// also x**2,y*2 should not be processed
return 0;
}
else if (size>2 && data[0]==data[1] && isIdChar(2))
{
// avoid processing interal ** and __ such as cmd__id__bla,
// or 4**10,5**10 as emphasis
return 0;
}
}
char c = data[0];
size_t ret;
if (size>2 && data[1]!=c)
int ret;
if (size>2 && data[1]!=c) // _bla or *bla
{
// whitespace cannot follow an opening emphasis
if (data[1]==' ' || data[1]=='\n' ||
......@@ -411,7 +516,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int,int size)
}
return ret+1;
}
if (size>3 && data[1]==c && data[2]!=c)
if (size>3 && data[1]==c && data[2]!=c) // __bla or **bla
{
if (data[2]==' ' || data[2]=='\n' ||
(ret = processEmphasis2(out, data+2, size-2, c)) == 0)
......@@ -420,7 +525,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int,int size)
}
return ret+2;
}
if (size>4 && data[1]==c && data[2]==c && data[3]!=c)
if (size>4 && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla
{
if (data[3]==' ' || data[3]=='\n' ||
(ret = processEmphasis3(out, data+3, size-3, c)) == 0)
......@@ -478,7 +583,7 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
contentEnd=i;
convertStringFragment(content,data+contentStart,contentEnd-contentStart);
//printf("processLink: content={%s}\n",content.data());
if (content.isEmpty()) return 0; // no link text
if (!isImageLink && content.isEmpty()) return 0; // no link text
i++; // skip over ]
// skip whitespace
......@@ -588,7 +693,7 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
}
i++;
}
else if (i<size && data[i]!=':') // minimal link ref notation [some id]
else if (i<size && data[i]!=':' && !content.isEmpty()) // minimal link ref notation [some id]
{
LinkRef *lr = g_linkRefs.find(content.lower());
//printf("processLink: minimal link {%s} lr=%p",content.data(),lr);
......@@ -609,28 +714,33 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
{
return 0;
}
if (isImageLink) // TODO: use @image?
static QRegExp re("^[@\\]ref ");
if (isImageLink)
{
out.addStr("<img src=\"");
out.addStr(link);
out.addStr("\" alt=\"");
out.addStr(content);
out.addStr("\"");
if (!title.isEmpty())
if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1)
// assume doxygen symbol link
{
out.addStr(" title=\"");
out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
out.addStr("\"");
out.addStr("@image html ");
out.addStr(link.mid(5));
if (!explicitTitle && !content.isEmpty())
{
out.addStr(" \"");
out.addStr(content);
out.addStr("\"");
}
else if ((content.isEmpty() || explicitTitle) && !title.isEmpty())
{
out.addStr(" \"");
out.addStr(title);
out.addStr("\"");
}
}
out.addStr("/>");
}
else
{
static QRegExp re("^[@\\]ref ");
if (link.find('/')!=-1) // file/url link
else
{
out.addStr("<a href=\"");
out.addStr("<img src=\"");
out.addStr(link);
out.addStr("\" alt=\"");
out.addStr(content);
out.addStr("\"");
if (!title.isEmpty())
{
......@@ -638,11 +748,12 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
out.addStr("\"");
}
out.addStr(">");
out.addStr(content.simplifyWhiteSpace());
out.addStr("</a>");
out.addStr("/>");
}
else if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1)
}
else
{
if (link.find("@ref ")!=-1 || link.find("\\ref ")!=-1)
// assume doxygen symbol link
{
out.addStr(link);
......@@ -657,7 +768,22 @@ static int processLink(GrowBuf &out,const char *data,int,int size)
}
out.addStr("\"");
}
else // avoid link to F[x](y)
else if (link.find('/')!=-1 || link.find('.')!=-1 || link.find('#')!=-1)
{ // file/url link
out.addStr("<a href=\"");
out.addStr(link);
out.addStr("\"");
if (!title.isEmpty())
{
out.addStr(" title=\"");
out.addStr(substitute(title.simplifyWhiteSpace(),"\"","&quot;"));
out.addStr("\"");
}
out.addStr(">");
out.addStr(content.simplifyWhiteSpace());
out.addStr("</a>");
}
else // avoid link to e.g. F[x](y)
{
//printf("no link for '%s'\n",link.data());
return 0;
......@@ -722,17 +848,14 @@ static int processCodeSpan(GrowBuf &out, const char *data, int /*offset*/, int s
i=f_begin;
while (i<f_end-1)
{
if (data[i]=='\'' && !((data[i+1]>='a' && data[i+1]<='z') ||
(data[i+1]>='A' && data[i+1]<='Z') ||
(data[i+1]>='0' && data[i+1]<='9')
)) // reject `some word' and not `it's cool`
if (data[i]=='\'' && !isIdChar(i+1)) // reject `some word' and not `it's cool`
{
return 0;
}
i++;
}
}
printf("found code span '%s'\n",QCString(data+f_begin).left(f_end-f_begin).data());
//printf("found code span '%s'\n",QCString(data+f_begin).left(f_end-f_begin).data());
/* real code span */
if (f_begin < f_end)
......@@ -783,28 +906,6 @@ static int processSpecialCommand(GrowBuf &out, const char *data, int offset, int
return 0;
}
#if 0
static int processHtmlBlock(GrowBuf &out, const char *data, int offset, int size)
{
if (size<2 || data[0]!='<') return 0;
int i=1;
while (i<size && ((data[i]>='0' && data[i]<='9') ||
(data[i]>='A' && data[i]<='Z') ||
(data[i]>='a' && data[i]<='z'))) i++;
if (i<=1 || i>=size) return 0;
QCString tagName;
convertStringFragment(tagName,data+1,i-1);
printf("found html tag '%s'\n",tagName.data());
if (g_htmlBlockTags.find(tagName)!=0)
{
printf("found block tag\n");
// search for end of the block...
}
return 0;
}
#endif
static void processInline(GrowBuf &out,const char *data,int size)
{
int i=0, end=0;
......@@ -856,7 +957,24 @@ static bool isBlockQuote(const char *data,int size,int indent)
{
int i = 0;
while (i<size && data[i]==' ') i++;
return i<size && data[i]=='>' && i<indent+codeBlockIndent;
if (i<indent+codeBlockIndent) // could be a quotation
{
// count >'s and skip spaces
int level=0;
while (i<size && (data[i]=='>' || data[i]==' '))
{
if (data[i]=='>') level++;
i++;
}
// last characters should be a space or newline,
// so a line starting with >= does not match
return level>0 && i<size && ((data[i-1]==' ') || data[i]=='\n');
}
else // too much indentation -> code block
{
return FALSE;
}
//return i<size && data[i]=='>' && i<indent+codeBlockIndent;
}
/** returns end of the link ref if this is indeed a link reference. */
......@@ -979,7 +1097,7 @@ static int isHRuler(const char *data,int size)
static QCString extractTitleId(QCString &title)
{
static QRegExp r1("^[a-z_A-Z][a-z_A-Z0-9\\-]*:");
//static QRegExp r1("^[a-z_A-Z][a-z_A-Z0-9\\-]*:");
static QRegExp r2("\\{#[a-z_A-Z][a-z_A-Z0-9\\-]*\\}$");
int l=0;
int i = r2.match(title,0,&l);
......@@ -990,20 +1108,21 @@ static QCString extractTitleId(QCString &title)
//printf("found id='%s' title='%s'\n",id.data(),title.data());
return id;
}
i = r1.match(title,0,&l);
if (i!=-1) // found id: style id
{
QCString id = title.mid(i,l-1);
title = title.left(i)+title.mid(i+l);
//printf("found id='%s' title='%s'\n",id.data(),title.data());
return id;
}
//i = r1.match(title,0,&l);
//if (i!=-1) // found id: style id
//{
// QCString id = title.mid(i,l-1);
// title = title.left(i)+title.mid(i+l);
// //printf("found id='%s' title='%s'\n",id.data(),title.data());
// return id;
//}
//printf("no id found in title '%s'\n",title.data());
return "";
}
static int isAtxHeader(const char *data,int size,QCString &header)
static int isAtxHeader(const char *data,int size,
QCString &header,QCString &id)
{
int i = 0, end;
int level = 0;
......@@ -1021,6 +1140,13 @@ static int isAtxHeader(const char *data,int size,QCString &header)
// store result
convertStringFragment(header,data+i,end-i);
id = extractTitleId(header);
if (!id.isEmpty()) // strip #'s between title and id
{
i=header.length()-1;
while (i>=0 && header.at(i)=='#' || header.at(i)==' ') i--;
header=header.left(i+1);
}
return level;
}
......@@ -1037,19 +1163,29 @@ static int isEmptyLine(const char *data,int size)
return TRUE;
}
#define isLiTag(i) \
(data[(i)]=='<' && \
(data[(i)+1]=='l' || data[(i)+1]=='L') && \
(data[(i)+2]=='i' || data[(i)+2]=='I') && \
(data[(i)+3]=='>'))
// compute the indent from the start of the input, excluding list markers
// such as -, *, +, and 1.
// such as -, -#, *, +, 1., and <li>
static int computeIndentExcludingListMarkers(const char *data,int size)
{
int i=0;
int indent=0;
bool isDigit=FALSE;
bool isLi=FALSE;
bool listMarkerSkipped=FALSE;
while (i<size &&
(data[i]==' ' || // space
(!listMarkerSkipped && // first list marker
(data[i]=='+' || data[i]=='-' || data[i]=='*' || // unordered list char
(isDigit=(data[i]>='1' && data[i]<='9'))) // ordered list marker?
(data[i]=='#' && i>0 && data[i-1]=='-') || // -# item
(isDigit=(data[i]>='1' && data[i]<='9')) || // ordered list marker?
(isLi=(i<size-3 && isLiTag(i))) // <li> tag
)
)
)
)
......@@ -1076,12 +1212,24 @@ static int computeIndentExcludingListMarkers(const char *data,int size)
j++;
}
}
else if (data[i]!=' ' && i<size-1 && data[i+1]==' ')
else if (isLi)
{
i+=3; // skip over <li>
indent+=3;
listMarkerSkipped=TRUE;
}
else if (data[i]=='-' && i<size-2 && data[i+1]=='#' && data[i+2]==' ')
{ // case "-# "
listMarkerSkipped=TRUE; // only a single list marker is accepted
i++; // skip over #
indent++;
}
else if (data[i]!=' ' && i<size-1 && data[i+1]==' ')
{ // case "- " or "+ " or "* "
listMarkerSkipped=TRUE; // only a single list marker is accepted
}
if (data[i]!=' ' && !listMarkerSkipped)
{
{ // end of indent
break;
}
indent++,i++;
......@@ -1090,6 +1238,44 @@ static int computeIndentExcludingListMarkers(const char *data,int size)
return indent;
}
static bool isFencedCodeBlock(const char *data,int size,int refIndent,
QCString &lang,int &start,int &end,int &offset)
{
// TODO: implement me...
// rules: at least 3 ~~~, end of the block same amount of ~~~'s, otherwise
// return FALSE
int i=0;
int indent=0;
int startTildes=0;
while (i<size && data[i]==' ') indent++,i++;
if (indent>=refIndent+4) return FALSE; // part of code block
while (i<size && data[i]=='~') startTildes++,i++;
if (startTildes<3) return FALSE; // not enough tildes
if (i<size && data[i]=='{') i++; // skip over optional {
int startLang=i;
while (i<size && (data[i]!='\n' && data[i]!='}' && data[i]!=' ')) i++;
convertStringFragment(lang,data+startLang,i-startLang);
while (i<size && data[i]!='\n') i++; // proceed to the end of the line
start=i;
while (i<size)
{
if (data[i]=='~')
{
end=i-1;
int endTildes=0;
while (i<size && data[i]=='~') endTildes++,i++;
while (i<size && data[i]==' ') i++;
if (i==size || data[i]=='\n')
{
offset=i;
return endTildes==startTildes;
}
}
i++;
}
return FALSE;
}
static bool isCodeBlock(const char *data,int offset,int size,int &indent)
{
//printf("<isCodeBlock(offset=%d,size=%d,indent=%d)\n",offset,size,indent);
......@@ -1244,16 +1430,9 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size)
// write table header, in range [start..end]
out.addStr("<tr>");
j=start;
for (k=0;k<columns;k++)
{
out.addStr("<th>");
while (j<=end && (data[j]!='|' || (j>0 && data[j-1]=='\\')))
{
out.addChar(data[j++]);
}
j++;
}
int headerStart = start;
int headerEnd = end;
// read cell alignments
int ret = findTableColumns(data+i,size-i,start,end,cc);
......@@ -1295,6 +1474,25 @@ static int writeTableBlock(GrowBuf &out,const char *data,int size)
// proceed to next line
i+=ret;
int m=headerStart;
for (k=0;k<columns;k++)
{
out.addStr("<th");
switch (columnAlignment[k])
{
case AlignLeft: out.addStr(" align=left"); break;
case AlignRight: out.addStr(" align=right"); break;
case AlignCenter: out.addStr(" align=center"); break;
case AlignNone: break;
}
out.addStr(">");
while (m<=headerEnd && (data[m]!='|' || (m>0 && data[m-1]=='\\')))
{
out.addChar(data[m++]);
}
m++;
}
// write table cells
while (i<size)
{
......@@ -1348,17 +1546,44 @@ void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size)
{
int level;
QCString header;
QCString id;
if (isHRuler(data,size))
{
out.addStr("<hr>\n");
}
else if ((level=isAtxHeader(data,size,header)))
else if ((level=isAtxHeader(data,size,header,id)))
{
QCString hTag;
hTag.sprintf("h%d",level);
out.addStr("<"+hTag+">");
out.addStr(header);
out.addStr("</"+hTag+">\n");
if (level<5 && !id.isEmpty())
{
switch(level)
{
case 1: out.addStr("@section "); break;
case 2: out.addStr("@subsection "); break;
case 3: out.addStr("@subsubsection "); break;
default: out.addStr("@paragraph "); break;
}
out.addStr(id);
out.addStr(" ");
out.addStr(header);
SectionInfo *si = new SectionInfo(g_fileName,id,header,SectionInfo::Anchor,level);
if (g_current)
{
g_current->anchors->append(si);
}
Doxygen::sectionDict.append(header,si);
}
else
{
if (!id.isEmpty())
{
out.addStr("\\anchor "+id+"\n");
}
hTag.sprintf("h%d",level);
out.addStr("<"+hTag+">");
out.addStr(header);
out.addStr("</"+hTag+">\n");
}
}
else // nothing interesting -> just output the line
{
......@@ -1387,6 +1612,11 @@ static int writeBlockQuote(GrowBuf &out,const char *data,int size)
else if (j>0 && data[j-1]=='>') indent=j+1;
j++;
}
if (j>0 && data[j-1]=='>') // disqualify last > if not followed by space
{
indent--;
j--;
}
if (level>curLevel) // quote level increased => add start markers
{
for (l=curLevel;l<level;l++)
......@@ -1458,11 +1688,12 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size,
int &pi,int&i,int &end)
{
// find end of the line
int nb=0;
for (end=i+1; end<size && data[end-1]!='\n'; end++)
{
// while looking for the end of the line we might encounter a block
// that needs to be passed unprocessed.
if ((data[end-1]=='\\' || data[end-1]=='@') && // command
if ((data[end-1]=='\\' || data[end-1]=='@') && // command
(end<=1 || (data[end-2]!='\\' && data[end-2]!='@')) // not escaped
)
{
......@@ -1493,6 +1724,36 @@ static void findEndOfLine(GrowBuf &out,const char *data,int size,
}
}
}
else if (nb==0 && data[end-1]=='<' && end<size-6 &&
(end<=1 || (data[end-2]!='\\' && data[end-2]!='@'))
)
{
if (tolower(data[end])=='p' && tolower(data[end+1])=='r' &&
tolower(data[end+2])=='e' && data[end+3]=='>') // <pre> tag
{
if (pi!=-1) // output previous line if available
{
out.addStr(data+pi,i-pi);
}
// output part until <pre>
out.addStr(data+i,end-1-i);
// output part until </pre>
i = end-1 + processHtmlTag(out,data+end-1,end-1,size-end+1);
pi=-1;
end = i+1;
break;
}
}
else if (nb==0 && data[end-1]=='`')
{
while (end<size && data[end-1]=='`') end++,nb++;
}
else if (nb>0 && data[end-1]=='`')
{
int enb=0;
while (end<size && data[end-1]=='`') end++,enb++;
if (enb==nb) nb=0;
}
}
}
......@@ -1578,17 +1839,38 @@ static QCString processBlocks(const QCString &s,int indent)
if (pi!=-1)
{
int blockStart,blockEnd,blockOffset;
QCString lang;
blockIndent = indent;
//printf("isHeaderLine(%s)=%d\n",QCString(data+i).left(size-i).data(),level);
if ((level=isHeaderline(data+i,size-i))>0)
{
//printf("Found header at %d-%d\n",i,end);
while (pi<size && data[pi]==' ') pi++;
if (i-pi>1)
QCString header,id;
convertStringFragment(header,data+pi,i-pi-1);
id = extractTitleId(header);
if (!header.isEmpty())
{
out.addStr(level==1?"<h1>":"<h2>");
out.addStr(data+pi,i-pi-1);
out.addStr(level==1?"</h1>\n":"</h2>\n");
if (!id.isEmpty())
{
out.addStr(level==1?"@section ":"@subsection ");
out.addStr(id);
out.addStr(" ");
out.addStr(header);
SectionInfo *si = new SectionInfo(g_fileName,id,header,SectionInfo::Anchor,level);
if (g_current)
{
g_current->anchors->append(si);
}
Doxygen::sectionDict.append(header,si);
}
else
{
out.addStr(level==1?"<h1>":"<h2>");
out.addStr(header);
out.addStr(level==1?"</h1>\n":"</h2>\n");
}
}
else
{
......@@ -1608,6 +1890,23 @@ static QCString processBlocks(const QCString &s,int indent)
pi=-1;
end=i+1;
}
else if (isFencedCodeBlock(data+pi,size-pi,indent,lang,blockStart,blockEnd,blockOffset))
{
//printf("Found FencedCodeBlock lang='%s' start=%d end=%d code={%s}\n",
// lang.data(),blockStart,blockEnd,QCString(data+pi+blockStart).left(blockEnd-blockStart).data());
out.addStr("@code");
if (!lang.isEmpty() && lang.at(0)=='.') lang=lang.mid(1);
if (!lang.isEmpty())
{
out.addStr("{"+lang+"}");
}
out.addStr(data+pi+blockStart,blockEnd-blockStart);
out.addStr("\n@endcode");
i=pi+blockOffset;
pi=-1;
end=i+1;
continue;
}
else if (isCodeBlock(data+i,i,end-i,blockIndent))
//if (isCodeBlock(data+pi,pi,end-pi,blockIndent))
{
......@@ -1651,7 +1950,7 @@ static QCString processBlocks(const QCString &s,int indent)
return out.get();
}
static QCString extractPageTitle(QCString &docs)
static QCString extractPageTitle(QCString &docs,QCString &id)
{
// first first non-empty line
QCString title;
......@@ -1671,16 +1970,19 @@ static QCString extractPageTitle(QCString &docs)
while (end2<size && data[end2-1]!='\n') end2++;
if (isHeaderline(data+end1,size-end1))
{
convertStringFragment(title,data+i,end1-i);
convertStringFragment(title,data+i,end1-i-1);
docs=docs.mid(end2);
id = extractTitleId(title);
//printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
return title;
}
}
if (i<end1 && isAtxHeader(data+i,end1-i,title)>0)
if (i<end1 && isAtxHeader(data+i,end1-i,title,id)>0)
{
docs=docs.mid(end1);
}
//printf("extractPageTitle(title='%s' docs='%s')\n",title.data(),docs.data());
id = extractTitleId(title);
//printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data());
return title;
}
......@@ -1727,36 +2029,12 @@ static QCString detab(const QCString &s,int &refIndent)
//---------------------------------------------------------------------------
QCString processMarkdown(const QCString &input)
QCString processMarkdown(const QCString &fileName,Entry *e,const QCString &input)
{
#if 0
static bool g_init = FALSE;
if (!g_init)
{
g_htmlBlockTags.insert("p",(void*)0x8);
g_htmlBlockTags.insert("dl",(void*)0x8);
g_htmlBlockTags.insert("h1",(void*)0x8);
g_htmlBlockTags.insert("h2",(void*)0x8);
g_htmlBlockTags.insert("h3",(void*)0x8);
g_htmlBlockTags.insert("h4",(void*)0x8);
g_htmlBlockTags.insert("h5",(void*)0x8);
g_htmlBlockTags.insert("h6",(void*)0x8);
g_htmlBlockTags.insert("ol",(void*)0x8);
g_htmlBlockTags.insert("ul",(void*)0x8);
g_htmlBlockTags.insert("div",(void*)0x8);
g_htmlBlockTags.insert("pre",(void*)0x8);
g_htmlBlockTags.insert("form",(void*)0x8);
g_htmlBlockTags.insert("math",(void*)0x8);
g_htmlBlockTags.insert("table",(void*)0x8);
g_htmlBlockTags.insert("iframe",(void*)0x8);
g_htmlBlockTags.insert("script",(void*)0x8);
g_htmlBlockTags.insert("fieldset",(void*)0x8);
g_htmlBlockTags.insert("noscript",(void*)0x8);
g_init=TRUE;
}
#endif
g_linkRefs.setAutoDelete(TRUE);
g_linkRefs.clear();
g_current = e;
g_fileName = fileName;
static GrowBuf out;
if (input.isEmpty()) return input;
out.clear();
......@@ -1777,7 +2055,7 @@ QCString processMarkdown(const QCString &input)
g_actions['@']=processSpecialCommand;
g_actions['[']=processLink;
g_actions['!']=processLink;
//g_actions['<']=processHtmlBlock;
g_actions['<']=processHtmlTag;
// finally process the inline markup (links, emphasis and code spans)
processInline(out,s,size);
out.addChar(0);
......@@ -1794,10 +2072,11 @@ void MarkdownFileParser::parseInput(const char *fileName,
Entry *current = new Entry;
current->lang = SrcLangExt_Markdown;
QCString docs = fileBuf;
QCString title=extractPageTitle(docs).stripWhiteSpace();
QCString id=extractTitleId(title);
QCString id;
QCString title=extractPageTitle(docs,id).stripWhiteSpace();
QCString baseName = substitute(QFileInfo(fileName).baseName().utf8()," ","_");
if (id.isEmpty()) id = "md_"+baseName;
if (title.isEmpty()) title = baseName;
if (id=="mainpage" || id=="index")
{
docs.prepend("@mainpage "+title+"\n");
......
......@@ -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;
......
......@@ -69,6 +69,7 @@ static int lastPreLineCtrlContext;
static int lastSkipVerbStringContext;
static int lastCommentInArgContext;
static int lastCSConstraint;
static int lastHereDocContext;
static Protection protection;
static Protection baseProt;
static int sharpCount = 0 ;
......@@ -138,6 +139,7 @@ static QCString *pCopyCurlyString;
static QGString *pCopyCurlyGString;
static QGString *pCopyRoundGString;
static QGString *pCopyQuotedGString;
static QGString *pCopyHereDocGString;
static QGString *pSkipVerbString;
static QStack<Grouping> autoGroupStack;
......@@ -698,6 +700,8 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
%x CopyArgVerbatim
%x HereDoc
%x HereDocEnd
%x CopyHereDoc
%x CopyHereDocEnd
%x IDLAttribute
%x IDLProp
......@@ -1833,13 +1837,14 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
else
BEGIN( EndTemplate );
}
<EndTemplate>"<<<" {
<EndTemplate>"<<<" {
if (!insidePHP)
{
REJECT;
}
else
{
lastHereDocContext = YY_START;
BEGIN(HereDoc);
}
}
......@@ -1922,20 +1927,44 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
else
REJECT;
}
<CopyHereDoc>{ID} { // PHP heredoc
g_hereDocId = yytext;
*pCopyHereDocGString += yytext;
BEGIN(CopyHereDocEnd);
}
<CopyHereDoc>"'"{ID}/"'" { // PHP nowdoc
g_hereDocId = &yytext[1];
*pCopyHereDocGString += yytext;
BEGIN(CopyHereDocEnd);
}
<HereDoc>{ID} { // PHP heredoc
g_hereDocId = yytext;
BEGIN(HereDocEnd);
}
<HereDoc>"'"{ID}/"'" { // PHP nowdoc
g_hereDocId = &yytext[1];
BEGIN(HereDocEnd);
}
<HereDocEnd>^{ID} { // id at start of the line could mark the end of the block
if (g_hereDocId==yytext) // it is the end marker
{
BEGIN(FindMembers);
BEGIN(lastHereDocContext);
}
}
<HereDocEnd>. { }
<CopyHereDocEnd>^{ID} { // id at start of the line could mark the end of the block
*pCopyHereDocGString += yytext;
if (g_hereDocId==yytext) // it is the end marker
{
BEGIN(lastHereDocContext);
}
}
<CopyHereDocEnd>\n {
*pCopyHereDocGString += yytext;
}
<CopyHereDocEnd>. {
*pCopyHereDocGString += yytext;
}
<FindMembers>"Q_OBJECT" { // Qt object macro
}
<FindMembers>"Q_PROPERTY" { // Qt property declaration
......@@ -3130,7 +3159,7 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
/*
<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); }
*/
<ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/]* { current->program += yytext ; }
<ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { current->program += yytext ; }
<ReadBody,ReadNSBody,ReadBodyIntf>"//".* { current->program += yytext ; }
<ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!insidePHP)
REJECT;
......@@ -3142,6 +3171,18 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
lastSkipVerbStringContext=YY_START;
BEGIN( SkipVerbString );
}
<ReadBody,ReadNSBody,ReadBodyIntf>"<<<" { if (insidePHP)
{
current->program += yytext ;
pCopyHereDocGString = &current->program;
lastHereDocContext=YY_START;
BEGIN( CopyHereDoc );
}
else
{
REJECT;
}
}
<ReadBody,ReadNSBody,ReadBodyIntf>\" { current->program += yytext ;
pCopyQuotedGString = &current->program;
lastStringContext=YY_START;
......@@ -4470,7 +4511,18 @@ TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?)
yyLineNr++;
//addToBody(yytext);
}
<SkipCurly,SkipCurlyCpp>[^\n#"'@\\/{}]+ {
<SkipCurly,SkipCurlyCpp>"<<<" {
if (!insidePHP)
{
REJECT;
}
else
{
lastHereDocContext = YY_START;
BEGIN(HereDoc);
}
}
<SkipCurly,SkipCurlyCpp>[^\n#"'@\\/{}<]+ {
//addToBody(yytext);
}
<SkipCurlyCpp>\n {
......
......@@ -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
......
......@@ -5908,13 +5908,13 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle,
file=pd->getOutputFileBase();
}
SectionInfo *si=new SectionInfo(
file,pd->name(),pd->title(),SectionInfo::Page,pd->getReference());
file,pd->name(),pd->title(),SectionInfo::Page,0,pd->getReference());
//printf("si->label=`%s' si->definition=%s si->fileName=`%s'\n",
// si->label.data(),si->definition?si->definition->name().data():"<none>",
// si->fileName.data());
//printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,si->fileName.data());
//printf("Adding section key=%s si->fileName=%s\n",pageName.data(),si->fileName.data());
Doxygen::sectionDict.insert(pd->name(),si);
Doxygen::sectionDict.append(pd->name(),si);
}
}
return pd;
......@@ -6303,6 +6303,7 @@ bool updateLanguageMapping(const QCString &extension,const QCString &language)
void initDefaultExtensionMapping()
{
g_extLookup.setAutoDelete(TRUE);
// extension parser id
updateLanguageMapping(".idl", "idl");
updateLanguageMapping(".ddl", "idl");
updateLanguageMapping(".odl", "idl");
......@@ -7166,20 +7167,21 @@ QCString langToString(SrcLangExt lang)
{
switch(lang)
{
case SrcLangExt_Unknown: return "Unknown";
case SrcLangExt_IDL: return "IDL";
case SrcLangExt_Java: return "Java";
case SrcLangExt_CSharp: return "C#";
case SrcLangExt_D: return "D";
case SrcLangExt_PHP: return "PHP";
case SrcLangExt_ObjC: return "Objective-C";
case SrcLangExt_Cpp: return "C++";
case SrcLangExt_JS: return "Javascript";
case SrcLangExt_Python: return "Python";
case SrcLangExt_Fortran: return "Fortran";
case SrcLangExt_VHDL: return "VHDL";
case SrcLangExt_XML: return "XML";
case SrcLangExt_Tcl: return "Tcl";
case SrcLangExt_Unknown: return "Unknown";
case SrcLangExt_IDL: return "IDL";
case SrcLangExt_Java: return "Java";
case SrcLangExt_CSharp: return "C#";
case SrcLangExt_D: return "D";
case SrcLangExt_PHP: return "PHP";
case SrcLangExt_ObjC: return "Objective-C";
case SrcLangExt_Cpp: return "C++";
case SrcLangExt_JS: return "Javascript";
case SrcLangExt_Python: return "Python";
case SrcLangExt_Fortran: return "Fortran";
case SrcLangExt_VHDL: return "VHDL";
case SrcLangExt_XML: return "XML";
case SrcLangExt_Tcl: return "Tcl";
case SrcLangExt_Markdown: return "Markdown";
}
return "Unknown";
}
......
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