summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri van Heesch <doxygen@gmail.com>2021-01-11 19:21:55 (GMT)
committerGitHub <noreply@github.com>2021-01-11 19:21:55 (GMT)
commit735203d07ce01c587b6807122e7a220a2c89de7d (patch)
tree50accac4dd8cdd3eb8f754fb5476d8b9208a9748
parentf81308d9a8f535c8a149a8173fcccd772bf0cd92 (diff)
parentc44fd3b5049ff3b16403c95ec51d1fa3f83412ce (diff)
downloadDoxygen-735203d07ce01c587b6807122e7a220a2c89de7d.zip
Doxygen-735203d07ce01c587b6807122e7a220a2c89de7d.tar.gz
Doxygen-735203d07ce01c587b6807122e7a220a2c89de7d.tar.bz2
Merge pull request #8309 from albert-github/feature/bug_668003
bug 668003 Default LaTeX header misses $-placeholders
-rw-r--r--src/cite.cpp43
-rw-r--r--src/cite.h5
-rw-r--r--src/config.xml201
-rw-r--r--src/htmlgen.cpp113
-rw-r--r--src/index.cpp5
-rw-r--r--src/latexgen.cpp584
-rw-r--r--src/util.cpp114
-rw-r--r--src/util.h5
-rwxr-xr-xtemplates/latex/footer.tex50
-rw-r--r--templates/latex/header.tex249
10 files changed, 770 insertions, 599 deletions
diff --git a/src/cite.cpp b/src/cite.cpp
index e02641a..ab090e0 100644
--- a/src/cite.cpp
+++ b/src/cite.cpp
@@ -417,35 +417,9 @@ void CitationManager::generatePage()
}
}
-void CitationManager::writeLatexBibliography(FTextStream &t) const
+QCString CitationManager::latexBibFiles()
{
- if (p->entries.empty()) return;
-
- QCString style = Config_getString(LATEX_BIB_STYLE);
- if (style.isEmpty())
- {
- style="plain";
- }
- QCString unit;
- if (Config_getBool(COMPACT_LATEX))
- {
- unit = "section";
- }
- else
- {
- unit = "chapter";
- }
- t << "% Bibliography\n"
- "\\newpage\n"
- "\\phantomsection\n";
- bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
- if (!pdfHyperlinks)
- {
- t << "\\clearemptydoublepage\n";
- t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n";
- }
- t << "\\bibliographystyle{" << style << "}\n"
- "\\bibliography{";
+ QCString result;
const StringVector &citeDataList = Config_getList(CITE_BIB_FILES);
int i = 0;
for (const auto &bibdata : citeDataList)
@@ -458,17 +432,12 @@ void CitationManager::writeLatexBibliography(FTextStream &t) const
{
if (!bibFile.isEmpty())
{
- if (i) t << ",";
+ if (i) result += ",";
i++;
- t << bibTmpFile << QCString().setNum(i);
+ result += bibTmpFile;
+ result += QCString().setNum(i);
}
}
}
- t << "}\n";
- if (pdfHyperlinks)
- {
- t << "\\addcontentsline{toc}{" << unit << "}{" << theTranslator->trCiteReferences() << "}\n";
- }
- t << "\n";
+ return result;
}
-
diff --git a/src/cite.h b/src/cite.h
index 9fea954..adf0840 100644
--- a/src/cite.h
+++ b/src/cite.h
@@ -59,10 +59,9 @@ class CitationManager
*/
bool isEmpty() const;
- /** writes the latex code for the standard bibliography
- * section to text stream \a t
+ /** lists the bibtex cite files in a comma separated list
*/
- void writeLatexBibliography(FTextStream &t) const;
+ QCString latexBibFiles();
const char *fileName() const;
const char *anchorPrefix() const;
diff --git a/src/config.xml b/src/config.xml
index c0b846a..9c0ccc8 100644
--- a/src/config.xml
+++ b/src/config.xml
@@ -1853,34 +1853,50 @@ doxygen -w html new_header.html new_footer.html new_stylesheet.css YourConfigFil
<![CDATA[
The following markers have a special meaning inside the header and footer:
<dl>
- <dt><code>\$title</code><dd>will be replaced with the title of the page.
- <dt><code>\$datetime</code><dd>will be replaced with current the date and time.
- <dt><code>\$date</code><dd>will be replaced with the current date.
- <dt><code>\$year</code><dd>will be replaces with the current year.
- <dt><code>\$doxygenversion</code><dd>will be replaced with the version of doxygen
- <dt><code>\$projectname</code><dd>will be replaced with the name of
+ <dt><code>$title</code><dd>will be replaced with the title of the page.
+ <dt><code>$datetime</code><dd>will be replaced with current the date and time.
+ <dt><code>$date</code><dd>will be replaced with the current date.
+ <dt><code>$year</code><dd>will be replaces with the current year.
+ <dt><code>$doxygenversion</code><dd>will be replaced with the version of doxygen
+ <dt><code>$projectname</code><dd>will be replaced with the name of
the project (see \ref cfg_project_name "PROJECT_NAME")
- <dt><code>\$projectnumber</code><dd>will be replaced with the project number
+ <dt><code>$projectnumber</code><dd>will be replaced with the project number
(see \ref cfg_project_number "PROJECT_NUMBER")
- <dt><code>\$projectbrief</code><dd>will be replaced with the project brief
+ <dt><code>$projectbrief</code><dd>will be replaced with the project brief
description (see \ref cfg_project_brief "PROJECT_BRIEF")
- <dt><code>\$projectlogo</code><dd>will be replaced with the project logo
+ <dt><code>$projectlogo</code><dd>will be replaced with the project logo
(see \ref cfg_project_logo "PROJECT_LOGO")
- <dt><code>\$treeview</code><dd>will be replaced with links to
+ <dt><code>$generatedby</code><dd>will be replaced with the output language dependent
+ version of the text "Generated by" or when the
+ \ref cfg_html_timestamp "HTML_TIMESTAMP" is set by the output language
+ dependent version of the text &quot;Generated on `$datetime` for `$projectname` by&quot;.
+ <dt><code>$stylesheet</code><dd>will be replaced with the setting of
+ \ref cfg_html_stylesheet "HTML_STYLESHEET" unless it is empty or the file in which case
+ it is replaced by the default setting `doxygen.css`.
+ <dt><code>$extrastylesheet</code><dd>will be replaced with the setting of
+ \ref cfg_html_extra_stylesheet "HTML_EXTRA_STYLESHEET" including the required
+ HTML tags for each extra stylesheet.
+ <dt><code>$treeview</code><dd>will be replaced with links to
the javascript and style sheets needed for the navigation tree
(or an empty string when \ref cfg_generate_treeview "GENERATE_TREEVIEW"
is disabled).
- <dt><code>\$search</code><dd>will be replaced with a links to
+ <dt><code>$search</code><dd>will be replaced with a links to
the javascript and style sheets needed for the search engine
(or an empty string when \ref cfg_searchengine "SEARCHENGINE"
is disabled).
- <dt><code>\$mathjax</code><dd>will be replaced with a links to
+ <dt><code>$searchbox</code><dd>will be replaced with the HTML code needed for
+ the search box to be shown
+ (or an empty string when \ref cfg_searchengine "SEARCHENGINE"
+ is disabled).
+ <dt><code>$mathjax</code><dd>will be replaced with a links to
the javascript and style sheets needed for the MathJax feature
(or an empty string when \ref cfg_use_mathjax "USE_MATHJAX" is disabled).
- <dt><code>\$relpath^</code><dd>
- If \ref cfg_create_subdirs "CREATE_SUBDIRS" is enabled, the command <code>\$relpath^</code> can be
- used to produce a relative path to the root of the HTML output directory,
- e.g. use <code>\$relpath^doxygen.css</code>, to refer to the standard style sheet.
+ <dt><code>$relpath^</code><dd>
+ If \ref cfg_create_subdirs "CREATE_SUBDIRS" is enabled, the command <code>$relpath^</code> can be
+ used to produce a relative path to the root of the HTML output directory,
+ e.g. use <code>$relpath^doxygen.css</code>, to refer to the standard style sheet.
+ <dt><code>$navpath</code><dd>will be replaced with a path as required by
+ \ref cfg_generate_treeview "GENERATE_TREEVIEW"
</dl>
To cope with differences in the layout of the header and footer that depend on
@@ -2737,38 +2753,165 @@ or
<option type='string' id='LATEX_HEADER' format='file' defval='' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_HEADER tag can be used to specify a personal \f$\mbox{\LaTeX}\f$
+ The \c LATEX_HEADER tag can be used to specify a user-defined \f$\mbox{\LaTeX}\f$
header for the generated \f$\mbox{\LaTeX}\f$ document.
The header should contain everything until the first chapter.
-
If it is left blank doxygen will generate a
- standard header. See section \ref doxygen_usage for information on how to
- let doxygen write the default header to a separate file.
+ standard header.
+
+ It is highly recommended to start with a default header using
+\verbatim
+doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+\endverbatim
+ and then modify the file \c new_header.tex.
+
+ See also section \ref doxygen_usage for information on how to generate
+ the default header that doxygen normally uses.
<br>Note: Only use a user-defined header if you know what you are doing!
- The following commands have a special meaning inside the header:
- <code>\$title</code>, <code>\$datetime</code>, <code>\$date</code>,
- <code>\$doxygenversion</code>, <code>\$projectname</code>,
- <code>\$projectnumber</code>, <code>\$projectbrief</code>,
- <code>\$projectlogo</code>.
- Doxygen will replace <code>\$title</code> with the empty string, for the replacement values of the
- other commands the user is referred to \ref cfg_html_header "HTML_HEADER".
+ @note The header is subject to change so you typically
+ have to regenerate the default header when upgrading to a newer version of
+ doxygen.
+ The following commands have a special meaning inside the header (and footer):
+]]>
+ </docs>
+ <docs doxywizard='0' doxyfile='0'>
+<![CDATA[
+ <dl>
+ <dt><code>$title</code><dd>will be replaced with the project name.
+ <dt><code>$datetime</code><dd>will be replaced with current the date and time.
+ <dt><code>$date</code><dd>will be replaced with the current date.
+ <dt><code>$year</code><dd>will be replaces with the current year.
+ <dt><code>$doxygenversion</code><dd>will be replaced with the version of doxygen
+ <dt><code>$projectname</code><dd>will be replaced with the name of
+ the project (see \ref cfg_project_name "PROJECT_NAME")
+ <dt><code>$projectnumber</code><dd>will be replaced with the project number
+ (see \ref cfg_project_number "PROJECT_NUMBER")
+ <dt><code>$projectbrief</code><dd>will be replaced with the project brief
+ description (see \ref cfg_project_brief "PROJECT_BRIEF")
+ <dt><code>$projectlogo</code><dd>will be replaced with the project logo
+ (see \ref cfg_project_logo "PROJECT_LOGO")
+ <dt><code>$latexdocumentpre</code><dd>will be replaced by an output language dependent setting
+ e.g. embed the entire document in a special environment (for Chinese, Japanese etc.)
+ Commonly used together with `$latexdocumentpost` in the footer.
+ <dt><code>$latexdocumentpost</code><dd>will be replaced by an output language dependent setting
+ e.g. embed the entire document in a special environment (for Chinese, Japanese etc.)
+ Commonly used together with `$latexdocumentpre` in the header.
+ <dt><code>$generatedby</code><dd>will be replaced with the output language dependent
+ version of the text "Generated by" or when the
+ \ref cfg_latex_timestamp "LATEX_TIMESTAMP" is set by the output language
+ dependent version of the text &quot;Generated on `$datetime` for `$projectname` by&quot;.
+ <dt><code>$latexcitereference</code><dd>will be replaced by the output language dependent$
+ version of the word "Bibliography".
+ This setting is typically used in combination with the block name `CITATIONS_PRESENT`.
+ <dt><code>$latexbibstyle</code><dd>will be replaced with the latex bib style to be used as
+ as set by \ref cfg_latex_bib_style "LATEX_BIB_STYLE", in case nothing is set the bib style
+ `plain` is used.
+ This setting is typically used in combination with the block name `CITATIONS_PRESENT`.
+ <dt><code>$latexbibfiles</code><dd>will be replaced by the comma separeted list of `bib. files
+ as set by \ref cfg_cite_bib_files "CITE_BIB_FILES" (when necessary a missing `.bib` is
+ automatically added).
+ This setting is typically used in combination with the block name `CITATIONS_PRESENT`.
+ <dt><code>$papertype</code><dd>will be replaced by the paper type as set in
+ \ref cfg_paper_type "PAPER_TYPE" and the word "paper" is directly appended to it to have
+ a correct \f$\mbox{\LaTeX}\f$ paper type.
+ <dt><code>$languagesupport</code><dd>will be replaced by an output language dependent setting
+ of packages required for translating terms of the specified language.
+ <dt><code>$latexfontenc</code><dd>will be replaced by an output language dependent setting
+ of the fontencoding to be used.
+ This setting is typically used in combination with the block name `LATEX_FONTENC`.
+ <dt><code>$latexfont</code><dd>will be replaced by an output language dependent setting
+ of the fonts to be used.
+ <dt><code>$latexemojidirectory</code><dd>will be replaced by the directory as set in
+ \ref cfg_latex_emoji_directory "LATEX_EMOJI_DIRECTORY" with the backslashes replaced by
+ forward slashes (so usable by \f$\mbox{\LaTeX}\f$). In case the
+ \ref cfg_latex_emoji_directory "LATEX_EMOJI_DIRECTORY" is
+ empty, the current directory will be used.
+ <dt><code>$makeindex</code><dd>will be replaced by the command as set in
+ \ref cfg_latex_makeindex_cmd "LATEX_MAKEINDEX_CMD". Then the command doesn't start with
+ a backslash, a backslash is automatically prepended. In case the setting is empty the
+ command `\makeindex` is used.
+ <dt><code>$extralatexpackages</code><dd>will be replaced by commands for usinging the packages set
+ in \ref cfg_extra_packages "EXTRA_PACKAGES".
+ <dt><code>$extralatexstylesheet</code><dd>will be replaced by commands for usinging the packages set
+ in \ref cfg_latex_extra_stylesheet "LATEX_EXTRA_STYLESHEET" (when the extension is the default
+ extension, `.sty`, this extension is stripped for the package name).
+ <dt><code>$latexspecialformulachars</code><dd>will be replaced by the code for some special
+ unicode characters that are commonly used (i.e. superscript minus, superscript 2 and superscript 3)
+ <dt><code>$formulamacrofile</code><dd>will be replaced by the name of the file as set
+ in \ref cfg_formula_macrofile "FORMULA_MACROFILE".
+ This setting is typically used in combination with the block name `FORMULA_MACROFILE`.
+ </dl>
+
+To cope with differences in the layout of the header and footer that depend on
+ configuration settings, the header and footer can also contain special blocks that
+ will be copied to the output or skipped depending on the configuration.
+ Such blocks have the following form:
+\verbatim
+ %%BEGIN BLOCKNAME
+ Some context copied when condition BLOCKNAME holds
+ %%END BLOCKNAME
+ %%BEGIN !BLOCKNAME
+ Some context copied when condition BLOCKNAME does not hold
+ %%END !BLOCKNAME
+\endverbatim
+The following block names are set based on the used settings in the
+ configuration file:
+ <dl>
+ <dt><code>COMPACT_LATEX</code><dd>Content within this block is copied to the output
+ when the \ref cfg_compact_latex "COMPACT_LATEX" option is enabled.
+ <dt><code>PDF_HYPERLINKS</code><dd>Content within this block is copied to the output
+ when the \ref cfg_pdf_hyperlinks "PDF_HYPERLINKS" option is enabled.
+ <dt><code>USE_PDFLATEX</code><dd>Content within this block is copied to the output
+ when the \ref cfg_use_pdflatex "USE_PDFLATEX" option is enabled.
+ <dt><code>LATEX_BATCHMODE</code><dd>Content within this block is copied to the output
+ when the \ref cfg_latex_batchmode "LATEX_BATCHMODE" option is enabled.
+ <dt><code>LATEX_TIMESTAMP</code><dd>Content within this block is copied to the output
+ when the \ref cfg_latex_timestamp "LATEX_TIMESTAMP" option is enabled.
+ </dl>
+The following block names are set based on the fact whether or not the tag has a
+ value in the used configuration file:
+ <dl>
+ <dt><code>LATEX_FONTENC</code><dd>Content within this block is copied to the output
+ when the doxygen latex translator function returns a value for the font encoding
+ to be used. It is to be used in combination with the above mentioned `$latexfontenc`.
+ <dt><code>FORMULA_MACROFILE</code><dd>Content within this block is copied to the output
+ when the \ref cfg_formula_macrofile "FORMULA_MACROFILE" option is not empty. It is
+ to be used in combination with the above mentioned `$formulamacrofile`.
+ </dl>
+The following block name is set based on whether or not a feature is used in the
+ documentation:
+ <dl>
+ <dt><code>CITATIONS_PRESENT</code><dd>Content within this block is copied to the output
+ when in the documentation citations are present and the relevant .. are present.
+ It is to be used in combination with the above mentioned `$latexcitereference`,
+ `$latexbibstyle` and `$latexbibfiles`.
+ </dl>
+]]>
+ </docs>
+ <docs documentation='0'>
+<![CDATA[
+ For a description of the possible markers and block names see the documentation.
]]>
</docs>
</option>
<option type='string' id='LATEX_FOOTER' format='file' defval='' depends='GENERATE_LATEX'>
<docs>
<![CDATA[
- The \c LATEX_FOOTER tag can be used to specify a personal \f$\mbox{\LaTeX}\f$ footer for
+ The \c LATEX_FOOTER tag can be used to specify a user-defined \f$\mbox{\LaTeX}\f$ footer for
the generated \f$\mbox{\LaTeX}\f$ document. The footer should contain everything after
the last chapter. If it is left blank doxygen will generate a
standard footer.
+
See \ref cfg_latex_header "LATEX_HEADER" for more information on
how to generate a default footer and what special commands can be
used inside the footer.
- <br>Note: Only use a user-defined footer if you know what you are doing!
+ See also section \ref doxygen_usage for information on how to generate
+ the default footer that doxygen normally uses.
+
+ Note: Only use a user-defined footer if you know what you are doing!
]]>
</docs>
</option>
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index e186c37..a9032b1 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -296,73 +296,6 @@ static QCString getConvertLatexMacro()
out.addChar(0);
return out.get();
}
-//------------------------------------------------------------------------
-
-/// Clear a text block \a s from \a begin to \a end markers
-QCString clearBlock(const char *s,const char *begin,const char *end)
-{
- if (s==0 || begin==0 || end==0) return s;
- const char *p, *q;
- int beginLen = qstrlen(begin);
- int endLen = qstrlen(end);
- int resLen = 0;
- for (p=s; (q=strstr(p,begin))!=0; p=q+endLen)
- {
- resLen+=(int)(q-p);
- p=q+beginLen;
- if ((q=strstr(p,end))==0)
- {
- resLen+=beginLen;
- break;
- }
- }
- resLen+=qstrlen(p);
- // resLen is the length of the string without the marked block
-
- QCString result(resLen+1);
- char *r;
- for (r=result.rawData(), p=s; (q=strstr(p,begin))!=0; p=q+endLen)
- {
- int l = (int)(q-p);
- memcpy(r,p,l);
- r+=l;
- p=q+beginLen;
- if ((q=strstr(p,end))==0)
- {
- memcpy(r,begin,beginLen);
- r+=beginLen;
- break;
- }
- }
- qstrcpy(r,p);
- return result;
-}
-//----------------------------------------------------------------------
-
-QCString selectBlock(const QCString& s,const QCString &name,bool enable)
-{
- // TODO: this is an expensive function that is called a lot -> optimize it
- const QCString begin = "<!--BEGIN " + name + "-->";
- const QCString end = "<!--END " + name + "-->";
- const QCString nobegin = "<!--BEGIN !" + name + "-->";
- const QCString noend = "<!--END !" + name + "-->";
-
- QCString result = s;
- if (enable)
- {
- result = substitute(result, begin, "");
- result = substitute(result, end, "");
- result = clearBlock(result, nobegin, noend);
- }
- else
- {
- result = substitute(result, nobegin, "");
- result = substitute(result, noend, "");
- result = clearBlock(result, begin, end);
- }
-
- return result;
-}
static QCString getSearchBox(bool serverSide, QCString relPath, bool highlightSearch)
{
@@ -379,36 +312,6 @@ static QCString getSearchBox(bool serverSide, QCString relPath, bool highlightSe
return QCString(result);
}
-static QCString removeEmptyLines(const QCString &s)
-{
- BufStr out(s.length()+1);
- const char *p=s.data();
- if (p)
- {
- char c;
- while ((c=*p++))
- {
- if (c=='\n')
- {
- const char *e = p;
- while (*e==' ' || *e=='\t') e++;
- if (*e=='\n')
- {
- p=e;
- }
- else out.addChar(c);
- }
- else
- {
- out.addChar(c);
- }
- }
- }
- out.addChar('\0');
- //printf("removeEmptyLines(%s)=%s\n",s.data(),out.data());
- return out.data();
-}
-
static QCString substituteHtmlKeywords(const QCString &str,
const QCString &title,
const QCString &relPath,
@@ -592,14 +495,14 @@ static QCString substituteHtmlKeywords(const QCString &str,
result = substitute(result,"$relpath^",relPath); //<-- must be last
// additional HTML only conditional blocks
- result = selectBlock(result,"DISABLE_INDEX",disableIndex);
- result = selectBlock(result,"GENERATE_TREEVIEW",treeView);
- result = selectBlock(result,"SEARCHENGINE",searchEngine);
- result = selectBlock(result,"TITLEAREA",titleArea);
- result = selectBlock(result,"PROJECT_NAME",hasProjectName);
- result = selectBlock(result,"PROJECT_NUMBER",hasProjectNumber);
- result = selectBlock(result,"PROJECT_BRIEF",hasProjectBrief);
- result = selectBlock(result,"PROJECT_LOGO",hasProjectLogo);
+ result = selectBlock(result,"DISABLE_INDEX",disableIndex,OutputGenerator::Html);
+ result = selectBlock(result,"GENERATE_TREEVIEW",treeView,OutputGenerator::Html);
+ result = selectBlock(result,"SEARCHENGINE",searchEngine,OutputGenerator::Html);
+ result = selectBlock(result,"TITLEAREA",titleArea,OutputGenerator::Html);
+ result = selectBlock(result,"PROJECT_NAME",hasProjectName,OutputGenerator::Html);
+ result = selectBlock(result,"PROJECT_NUMBER",hasProjectNumber,OutputGenerator::Html);
+ result = selectBlock(result,"PROJECT_BRIEF",hasProjectBrief,OutputGenerator::Html);
+ result = selectBlock(result,"PROJECT_LOGO",hasProjectLogo,OutputGenerator::Html);
result = removeEmptyLines(result);
diff --git a/src/index.cpp b/src/index.cpp
index e2e5ea1..c71e8fb 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -4233,10 +4233,7 @@ static void writeIndex(OutputList &ol)
ol.startFile("refman",0,0);
ol.startIndexSection(isTitlePageStart);
- if (!Config_getString(LATEX_HEADER).isEmpty())
- {
- ol.disable(OutputGenerator::Latex);
- }
+ ol.disable(OutputGenerator::Latex);
ol.disable(OutputGenerator::Docbook);
if (projPrefix.isEmpty())
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index ece344f..e73f6b8 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -44,6 +44,9 @@
#include "resourcemgr.h"
#include "portable.h"
+static QCString g_header;
+static QCString g_footer;
+
LatexCodeGenerator::LatexCodeGenerator(FTextStream &t,const QCString &relPath,const QCString &sourceFileName)
: m_relPath(relPath), m_sourceFileName(sourceFileName)
{
@@ -483,359 +486,29 @@ void LatexGenerator::init()
term("Could not create output directory %s\n",dname.data());
}
- writeLatexMakefile();
- writeMakeBat();
-
- createSubDirs(d);
-}
-
-static void writeDefaultHeaderPart1(FTextStream &t)
-{
- // part 1
-
- // Handle batch mode
- if (Config_getBool(LATEX_BATCHMODE))
- t << "\\batchmode\n";
-
- // to overcome problems with too many open files
- t << "\\let\\mypdfximage\\pdfximage"
- "\\def\\pdfximage{\\immediate\\mypdfximage}";
-
- // Set document class depending on configuration
- QCString documentClass;
- if (Config_getBool(COMPACT_LATEX))
- documentClass = "article";
- else
- documentClass = "book";
- t << "\\documentclass[twoside]{" << documentClass << "}\n"
- "\n";
- t << "%% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package\n"
- "\\usepackage{ifthen}\n"
- "\\ifx\\requestedLaTeXdate\\undefined\n"
- "\\usepackage{array}\n"
- "\\else\n"
- "\\usepackage{array}[=2016-10-06]\n"
- "\\fi\n"
- "%%\n";
-
- // Load required packages
- t << "% Packages required by doxygen\n"
- "\\usepackage{fixltx2e}\n" // for \textsubscript
- "\\usepackage{doxygen}\n";
- const StringVector &extraLatexStyles = Config_getList(LATEX_EXTRA_STYLESHEET);
- for (const auto &extraStyle : extraLatexStyles)
- {
- QCString fileName = extraStyle.c_str();
- if (!fileName.isEmpty())
- {
- QFileInfo fi(fileName);
- if (fi.exists())
- {
- if (checkExtension(fi.fileName().data(), LATEX_STYLE_EXTENSION))
- {
- // strip the extension, it will be added by the usepackage in the tex conversion process
- t << "\\usepackage{" << stripExtensionGeneral(fi.fileName().data(), LATEX_STYLE_EXTENSION) << "}\n";
- }
- else
- {
- t << "\\usepackage{" << fi.fileName().utf8() << "}\n";
- }
- }
- }
- }
- t << "\\usepackage{graphicx}\n"
- "\\usepackage[utf8]{inputenc}\n"
- "\\usepackage{makeidx}\n"
- "\\PassOptionsToPackage{warn}{textcomp}\n"
- "\\usepackage{textcomp}\n"
- "\\usepackage[nointegrals]{wasysym}\n"
- "\\usepackage{ifxetex}\n"
- "\n";
-
- // Language support
- QCString languageSupport = theTranslator->latexLanguageSupportCommand();
- if (!languageSupport.isEmpty())
- {
- t << "% NLS support packages\n"
- << languageSupport
- << "\n";
- }
-
- // Define default fonts
- t << "% Font selection\n";
- QCString fontenc = theTranslator->latexFontenc();
- if (!fontenc.isEmpty())
- {
- t << "\\usepackage[" << fontenc << "]{fontenc}\n";
- }
- QCString font = theTranslator->latexFont();
- if (!font.isEmpty())
- {
- t << font;
- }
- t << "\\usepackage{sectsty}\n"
- "\\allsectionsfont{%\n"
- " \\fontseries{bc}\\selectfont%\n"
- " \\color{darkgray}%\n"
- "}\n"
- "\\renewcommand{\\DoxyLabelFont}{%\n"
- " \\fontseries{bc}\\selectfont%\n"
- " \\color{darkgray}%\n"
- "}\n"
- "\\newcommand{\\+}{\\discretionary{\\mbox{\\scriptsize$\\hookleftarrow$}}{}{}}\n"
- "\n";
-
- QCString emojiDir=Config_getString(LATEX_EMOJI_DIRECTORY);
- if (emojiDir.isEmpty()) emojiDir = ".";
- emojiDir = substitute(emojiDir,"\\","/");
- t << "% Arguments of doxygenemoji:\n"
- "% 1) ':<text>:' form of the emoji, already \"LaTeX\"-escaped\n"
- "% 2) file with the name of the emoji without the .png extension\n"
- "% in case image exist use this otherwise use the ':<text>:' form\n";
- t << "\\newcommand{\\doxygenemoji}[2]{%\n"
- " \\IfFileExists{" << emojiDir << "/#2.png}{\\raisebox{-0.1em}{\\includegraphics[height=0.9em]{" << emojiDir << "/#2.png}}}{#1}%\n"
- "}\n";
-
- // Define page & text layout
- QCString paperName=Config_getEnum(PAPER_TYPE);
- // "a4wide" package is obsolete (see bug 563698)
- t << "% Page & text layout\n"
- "\\usepackage{geometry}\n"
- "\\geometry{%\n"
- " " << paperName << "paper,%\n"
- " top=2.5cm,%\n"
- " bottom=2.5cm,%\n"
- " left=2.5cm,%\n"
- " right=2.5cm%\n"
- "}\n";
- // \sloppy is obsolete (see bug 563698)
- // Allow a bit of overflow to go unnoticed by other means
- t << "\\tolerance=750\n"
- "\\hfuzz=15pt\n"
- "\\hbadness=750\n"
- "\\setlength{\\emergencystretch}{15pt}\n"
- "\\setlength{\\parindent}{0cm}\n"
- "\\newcommand{\\doxynormalparskip}{\\setlength{\\parskip}{3ex plus 2ex minus 2ex}}\n"
- "\\newcommand{\\doxytocparskip}{\\setlength{\\parskip}{1ex plus 0ex minus 0ex}}\n"
- "\\doxynormalparskip\n";
- // Redefine paragraph/subparagraph environments, using sectsty fonts
- t << "\\makeatletter\n"
- "\\renewcommand{\\paragraph}{%\n"
- " \\@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{%\n"
- " \\normalfont\\normalsize\\bfseries\\SS@parafont%\n"
- " }%\n"
- "}\n"
- "\\renewcommand{\\subparagraph}{%\n"
- " \\@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{%\n"
- " \\normalfont\\normalsize\\bfseries\\SS@subparafont%\n"
- " }%\n"
- "}\n"
- "\\makeatother\n"
- "\n";
- //
- t << "\\makeatletter\n"
- "\\newcommand\\hrulefilll{\\leavevmode\\leaders\\hrule\\hskip 0pt plus 1filll\\kern\\z@}\n"
- "\\makeatother\n"
- "\n";
-
- // Headers & footers
- QGString genString;
- QCString generatedBy;
- bool timeStamp = Config_getBool(LATEX_TIMESTAMP);
- FTextStream tg(&genString);
- if (timeStamp)
+ if (!Config_getString(LATEX_HEADER).isEmpty())
{
- generatedBy = theTranslator->trGeneratedAt(dateToString(TRUE), Config_getString(PROJECT_NAME));
+ g_header=fileToString(Config_getString(LATEX_HEADER));
+ //printf("g_header='%s'\n",g_header.data());
}
else
{
- generatedBy = theTranslator->trGeneratedBy();
+ g_header = ResourceMgr::instance().getAsString("header.tex");
}
- filterLatexString(tg, generatedBy,
- false, // insideTabbing
- false, // insidePre
- false, // insideItem
- false, // insideTable
- false // keepSpaces
- );
- t << "% Headers & footers\n"
- "\\usepackage{fancyhdr}\n"
- "\\pagestyle{fancyplain}\n"
- "\\renewcommand{\\footrulewidth}{0.4pt}\n"
- "%\n"
- "\\fancypagestyle{fancyplain}{\n"
- "\\fancyhf{}\n"
- "\\fancyhead[LE, RO]{\\bfseries\\thepage}\n"
- "\\fancyhead[LO]{\\bfseries\\rightmark}\n"
- "\\fancyhead[RE]{\\bfseries\\leftmark}\n"
- "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n"
- "}\n"
- "%\n"
- "\\fancypagestyle{plain}{\n"
- "\\fancyhf{}\n"
- "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n"
- "\\renewcommand{\\headrulewidth}{0pt}}\n"
- "%\n"
- "\\pagestyle{fancyplain}\n"
- "%\n";
-
- if (!Config_getBool(COMPACT_LATEX))
- {
- t << "\\renewcommand{\\chaptermark}[1]{%\n"
- " \\markboth{#1}{}%\n"
- "}\n";
- }
- t << "\\renewcommand{\\sectionmark}[1]{%\n"
- " \\markright{\\thesection\\ #1}%\n"
- "}\n"
- "\n";
-
- // ToC, LoF, LoT, bibliography, and index
- t << "% Indices & bibliography\n"
- "\\usepackage{natbib}\n"
- "\\usepackage[titles]{tocloft}\n"
- "\\setcounter{tocdepth}{3}\n"
- "\\setcounter{secnumdepth}{5}\n";
-
- QCString latex_mkidx_command = Config_getString(LATEX_MAKEINDEX_CMD);
- if (!latex_mkidx_command.isEmpty())
+ if (!Config_getString(LATEX_FOOTER).isEmpty())
{
- if (latex_mkidx_command[0] == '\\')
- t << latex_mkidx_command << "\n";
- else
- t << '\\' << latex_mkidx_command << "\n";
+ g_footer=fileToString(Config_getString(LATEX_FOOTER));
+ //printf("g_footer='%s'\n",g_footer.data());
}
else
{
- t << "\\makeindex\n";
+ g_footer = ResourceMgr::instance().getAsString("footer.tex");
}
- t << "\n";
- writeExtraLatexPackages(t);
- writeLatexSpecialFormulaChars(t);
- QCString macroFile = Config_getString(FORMULA_MACROFILE);
- if (!macroFile.isEmpty())
- {
- QFileInfo fi(macroFile);
- macroFile=fi.absFilePath().utf8();
- QCString stripMacroFile = fi.fileName().data();
- copyFile(macroFile,Config_getString(LATEX_OUTPUT) + "/" + stripMacroFile);
- t << "\\input{" << stripMacroFile << "}" << endl;
- }
+ writeLatexMakefile();
+ writeMakeBat();
- // Hyperlinks
- bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
- if (pdfHyperlinks)
- {
- t << "% Hyperlinks (required, but should be loaded last)\n"
- "\\ifpdf\n"
- " \\usepackage[pdftex,pagebackref=true]{hyperref}\n"
- "\\else\n"
- " \\ifxetex\n"
- " \\usepackage[pagebackref=true]{hyperref}\n"
- " \\else\n"
- " \\usepackage[ps2pdf,pagebackref=true]{hyperref}\n"
- " \\fi\n"
- "\\fi\n"
- "\n"
- "\\hypersetup{%\n"
- " colorlinks=true,%\n"
- " linkcolor=blue,%\n"
- " citecolor=blue,%\n"
- " unicode%\n"
- "}\n"
- "\n";
- }
-
- // Custom commands used by the header
- t << "% Custom commands\n"
- "\\newcommand{\\clearemptydoublepage}{%\n"
- " \\newpage{\\pagestyle{empty}\\cleardoublepage}%\n"
- "}\n"
- "\n";
-
- // caption style definition
- t << "\\usepackage{caption}\n"
- << "\\captionsetup{labelsep=space,justification=centering,font={bf},singlelinecheck=off,skip=4pt,position=top}\n\n";
-
-
- // in page table of contents
- t << "\\usepackage{etoc}\n"
- "\\etocsettocstyle{\\doxytocparskip}{\\doxynormalparskip}\n";
-
- // prevent numbers overlap the titles in toc
- t << "\\renewcommand{\\numberline}[1]{#1~}\n";
-
- // End of preamble, now comes the document contents
- t << "%===== C O N T E N T S =====\n"
- "\n"
- "\\begin{document}\n"
- "\\raggedbottom\n";
- QCString documentPre = theTranslator->latexDocumentPre();
- if (!documentPre.isEmpty())
- {
- t << documentPre;
- }
- t << "\n";
-
- // Front matter
- t << "% Titlepage & ToC\n";
- bool usePDFLatex = Config_getBool(USE_PDFLATEX);
- if (pdfHyperlinks && usePDFLatex)
- {
- // To avoid duplicate page anchors due to reuse of same numbers for
- // the index (be it as roman numbers)
- t << "\\hypersetup{pageanchor=false,\n"
- // << " bookmarks=true,\n" // commented out to prevent warning
- << " bookmarksnumbered=true,\n"
- << " pdfencoding=unicode\n"
- << " }\n";
- }
- t << "\\pagenumbering{alph}\n"
- "\\begin{titlepage}\n"
- "\\vspace*{7cm}\n"
- "\\begin{center}%\n"
- "{\\Large ";
-}
-
-static void writeDefaultHeaderPart2(FTextStream &t)
-{
- // part 2
- // Finalize project name
- t << "}\\\\\n"
- "\\vspace*{1cm}\n"
- "{\\large ";
-}
-
-static void writeDefaultHeaderPart3(FTextStream &t)
-{
- // part 3
- // Finalize project number
- t << " Doxygen " << getDoxygenVersion() << "}\\\\\n";
- if (Config_getBool(LATEX_TIMESTAMP))
- t << "\\vspace*{0.5cm}\n"
- "{\\small " << dateToString(TRUE) << "}\\\\\n";
- t << "\\end{center}\n"
- "\\end{titlepage}\n";
- bool compactLatex = Config_getBool(COMPACT_LATEX);
- if (!compactLatex)
- t << "\\clearemptydoublepage\n";
- t << "\\pagenumbering{roman}\n";
-
- // ToC
- t << "\\tableofcontents\n";
- if (!compactLatex)
- t << "\\clearemptydoublepage\n";
- t << "\\pagenumbering{arabic}\n";
- bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
- bool usePDFLatex = Config_getBool(USE_PDFLATEX);
- if (pdfHyperlinks && usePDFLatex)
- {
- // re-enable anchors again
- t << "\\hypersetup{pageanchor=true}\n";
- }
- t << "\n"
- "%--- Begin generated contents ---\n";
+ createSubDirs(d);
}
static void writeDefaultStyleSheet(FTextStream &t)
@@ -843,56 +516,18 @@ static void writeDefaultStyleSheet(FTextStream &t)
t << ResourceMgr::instance().getAsString("doxygen.sty");
}
-static void writeDefaultFooter(FTextStream &t)
-{
- t << "%--- End generated contents ---\n"
- "\n";
-
- // Bibliography
- CitationManager::instance().writeLatexBibliography(t);
-
- // Index
- t << "% Index\n";
- QCString unit;
- if (Config_getBool(COMPACT_LATEX))
- {
- unit = "section";
- }
- else
- {
- unit = "chapter";
- t << "\\backmatter\n";
- }
- t << "\\newpage\n"
- "\\phantomsection\n"
- "\\clearemptydoublepage\n"
- "\\addcontentsline{toc}{" << unit << "}{\\indexname}\n"
- "\\printindex\n"
- "\n";
- QCString documentPost = theTranslator->latexDocumentPost();
- if (!documentPost.isEmpty())
- {
- t << documentPost;
- }
- t << "\\end{document}\n";
-}
-
void LatexGenerator::writeHeaderFile(QFile &f)
{
FTextStream t(&f);
t << "% Latex header for doxygen " << getDoxygenVersion() << endl;
- writeDefaultHeaderPart1(t);
- t << "Your title here";
- writeDefaultHeaderPart2(t);
- t << "Generated by";
- writeDefaultHeaderPart3(t);
+ t << ResourceMgr::instance().getAsString("header.tex");
}
void LatexGenerator::writeFooterFile(QFile &f)
{
FTextStream t(&f);
t << "% Latex footer for doxygen " << getDoxygenVersion() << endl;
- writeDefaultFooter(t);
+ t << ResourceMgr::instance().getAsString("footer.tex");
}
void LatexGenerator::writeStyleSheetFile(QFile &f)
@@ -932,33 +567,164 @@ void LatexGenerator::startProjectNumber()
t << "\\\\[1ex]\\large ";
}
-void LatexGenerator::startIndexSection(IndexSections is)
+static QCString extraLatexStyleSheet()
{
- bool compactLatex = Config_getBool(COMPACT_LATEX);
- QCString latexHeader = Config_getString(LATEX_HEADER);
- switch (is)
+ QCString result;
+ const StringVector &extraLatexStyles = Config_getList(LATEX_EXTRA_STYLESHEET);
+ for (const auto &extraStyle : extraLatexStyles)
{
- case isTitlePageStart:
+ QCString fileName = extraStyle.c_str();
+ if (!fileName.isEmpty())
+ {
+ QFileInfo fi(fileName);
+ if (fi.exists())
{
- if (latexHeader.isEmpty())
+ result += "\\usepackage{";
+ if (checkExtension(fi.fileName().data(), LATEX_STYLE_EXTENSION))
{
- writeDefaultHeaderPart1(t);
+ // strip the extension, it will be added by the usepackage in the tex conversion process
+ result += stripExtensionGeneral(fi.fileName().data(), LATEX_STYLE_EXTENSION);
}
else
{
- QCString header = fileToString(latexHeader);
- t << substituteKeywords(header,"",
- convertToLaTeX(Config_getString(PROJECT_NAME)),
- convertToLaTeX(Config_getString(PROJECT_NUMBER)),
- convertToLaTeX(Config_getString(PROJECT_BRIEF)));
+ result += fi.fileName().utf8();
}
+ result += "}\n";
}
+ }
+ }
+ return result;
+}
+
+static QCString makeIndex()
+{
+ QCString result;
+ QCString latex_mkidx_command = Config_getString(LATEX_MAKEINDEX_CMD);
+ if (!latex_mkidx_command.isEmpty())
+ {
+ if (latex_mkidx_command[0] == '\\')
+ result += latex_mkidx_command;
+ else
+ result += '\\'+latex_mkidx_command;
+ }
+ else
+ {
+ result += "\\makeindex";
+ }
+ return result;
+}
+
+static QCString substituteLatexKeywords(const QCString &str,
+ const QCString &title)
+{
+ bool compactLatex = Config_getBool(COMPACT_LATEX);
+ bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
+ bool usePdfLatex = Config_getBool(USE_PDFLATEX);
+ bool latexBatchmode = Config_getBool(LATEX_BATCHMODE);
+ QCString paperType = Config_getString(PAPER_TYPE);
+
+ QCString style = Config_getString(LATEX_BIB_STYLE);
+ if (style.isEmpty())
+ {
+ style="plain";
+ }
+
+ QGString genString;
+ FTextStream tg(&genString);
+ QCString generatedBy;
+ bool timeStamp = Config_getBool(LATEX_TIMESTAMP);
+ if (timeStamp)
+ {
+ generatedBy = theTranslator->trGeneratedAt(dateToString(TRUE), Config_getString(PROJECT_NAME));
+ }
+ else
+ {
+ generatedBy = theTranslator->trGeneratedBy();
+ }
+ filterLatexString(tg, generatedBy,
+ false, // insideTabbing
+ false, // insidePre
+ false, // insideItem
+ false, // insideTable
+ false // keepSpaces
+ );
+ generatedBy = genString;
+
+ QCString latexFontenc = theTranslator->latexFontenc();
+
+ QCString latexEmojiDirectory = Config_getString(LATEX_EMOJI_DIRECTORY);
+ if (latexEmojiDirectory.isEmpty()) latexEmojiDirectory = ".";
+ latexEmojiDirectory = substitute(latexEmojiDirectory,"\\","/");
+
+ QGString genExtraLatexPackages;
+ FTextStream tg1(&genExtraLatexPackages);
+ writeExtraLatexPackages(tg1);
+ QCString extraLatexPackages;
+ extraLatexPackages = genExtraLatexPackages;
+
+ QGString genLatexSpecialFormulaChars;
+ FTextStream tg2(&genLatexSpecialFormulaChars);
+ writeLatexSpecialFormulaChars(tg2);
+ QCString latexSpecialFormulaChars;
+ latexSpecialFormulaChars = genLatexSpecialFormulaChars;
+
+ QCString formulaMacrofile = Config_getString(FORMULA_MACROFILE);
+ if (!formulaMacrofile.isEmpty())
+ {
+ QFileInfo fi(formulaMacrofile);
+ formulaMacrofile=fi.absFilePath().utf8();
+ QCString stripMacroFile = fi.fileName().data();
+ copyFile(formulaMacrofile,Config_getString(LATEX_OUTPUT) + "/" + stripMacroFile);
+ }
+
+ // first substitute generic keywords
+ QCString result = substituteKeywords(str,title,
+ convertToLaTeX(Config_getString(PROJECT_NAME)),
+ convertToLaTeX(Config_getString(PROJECT_NUMBER)),
+ convertToLaTeX(Config_getString(PROJECT_BRIEF)));
+
+ // additional LaTeX only keywords
+ result = substitute(result,"$latexdocumentpre",theTranslator->latexDocumentPre());
+ result = substitute(result,"$latexdocumentpost",theTranslator->latexDocumentPost());
+ result = substitute(result,"$generatedby",generatedBy);
+ result = substitute(result,"$latexbibstyle",style);
+ result = substitute(result,"$latexcitereference",theTranslator->trCiteReferences());
+ result = substitute(result,"$latexbibfiles",CitationManager::instance().latexBibFiles());
+ result = substitute(result,"$papertype",paperType+"paper");
+ result = substitute(result,"$extralatexstylesheet",extraLatexStyleSheet());
+ result = substitute(result,"$languagesupport",theTranslator->latexLanguageSupportCommand());
+ result = substitute(result,"$latexfontenc",latexFontenc);
+ result = substitute(result,"$latexfont",theTranslator->latexFont());
+ result = substitute(result,"$latexemojidirectory",latexEmojiDirectory);
+ result = substitute(result,"$makeindex",makeIndex());
+ result = substitute(result,"$extralatexpackages",extraLatexPackages);
+ result = substitute(result,"$latexspecialformulachars",latexSpecialFormulaChars);
+ result = substitute(result,"$formulamacrofile",formulaMacrofile);
+
+ // additional LaTeX only conditional blocks
+ result = selectBlock(result,"CITATIONS_PRESENT", !CitationManager::instance().isEmpty(),OutputGenerator::Latex);
+ result = selectBlock(result,"COMPACT_LATEX",compactLatex,OutputGenerator::Latex);
+ result = selectBlock(result,"PDF_HYPERLINKS",pdfHyperlinks,OutputGenerator::Latex);
+ result = selectBlock(result,"USE_PDFLATEX",usePdfLatex,OutputGenerator::Latex);
+ result = selectBlock(result,"LATEX_TIMESTAMP",timeStamp,OutputGenerator::Latex);
+ result = selectBlock(result,"LATEX_BATCHMODE",latexBatchmode,OutputGenerator::Latex);
+ result = selectBlock(result,"LATEX_FONTENC",!latexFontenc.isEmpty(),OutputGenerator::Latex);
+ result = selectBlock(result,"FORMULA_MACROFILE",!formulaMacrofile.isEmpty(),OutputGenerator::Latex);
+
+ result = removeEmptyLines(result);
+
+ return result;
+}
+
+void LatexGenerator::startIndexSection(IndexSections is)
+{
+ bool compactLatex = Config_getBool(COMPACT_LATEX);
+ switch (is)
+ {
+ case isTitlePageStart:
+ t << substituteLatexKeywords(g_header,convertToLaTeX(Config_getString(PROJECT_NAME)));
break;
case isTitlePageAuthor:
- if (latexHeader.isEmpty())
- {
- writeDefaultHeaderPart2(t);
- }
break;
case isMainPage:
if (compactLatex) t << "\\doxysection"; else t << "\\chapter";
@@ -978,7 +744,7 @@ void LatexGenerator::startIndexSection(IndexSections is)
break;
case isNamespaceIndex:
if (compactLatex) t << "\\doxysection"; else t << "\\chapter";
- t << "{"; //Namespace Index}\"
+ t << "{"; //Namespace Index}\n"
break;
case isClassHierarchyIndex:
if (compactLatex) t << "\\doxysection"; else t << "\\chapter";
@@ -1094,19 +860,12 @@ void LatexGenerator::startIndexSection(IndexSections is)
void LatexGenerator::endIndexSection(IndexSections is)
{
- //bool compactLatex = Config_getBool(COMPACT_LATEX);
bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
- QCString latexHeader = Config_getString(LATEX_HEADER);
- QCString latexFooter = Config_getString(LATEX_FOOTER);
switch (is)
{
case isTitlePageStart:
break;
case isTitlePageAuthor:
- if (latexHeader.isEmpty())
- {
- writeDefaultHeaderPart3(t);
- }
break;
case isMainPage:
{
@@ -1268,18 +1027,7 @@ void LatexGenerator::endIndexSection(IndexSections is)
case isPageDocumentation2:
break;
case isEndIndex:
- if (latexFooter.isEmpty())
- {
- writeDefaultFooter(t);
- }
- else
- {
- QCString footer = fileToString(latexFooter);
- t << substituteKeywords(footer,"",
- convertToLaTeX(Config_getString(PROJECT_NAME)),
- convertToLaTeX(Config_getString(PROJECT_NUMBER)),
- convertToLaTeX(Config_getString(PROJECT_BRIEF)));
- }
+ t << substituteLatexKeywords(g_footer,convertToLaTeX(Config_getString(PROJECT_NAME)));
break;
}
}
@@ -2320,5 +2068,3 @@ void LatexGenerator::writeLabel(const char *l,bool isLast)
void LatexGenerator::endLabels()
{
}
-
-
diff --git a/src/util.cpp b/src/util.cpp
index 7fcd5ed..3feb8db 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -7334,3 +7334,117 @@ FortranFormat convertFileNameFortranParserCode(QCString fn)
return FortranFormat_Unknown;
}
+//------------------------------------------------------------------------
+
+/// Clear a text block \a s from \a begin to \a end markers
+QCString clearBlock(const char *s,const char *begin,const char *end)
+{
+ if (s==0 || begin==0 || end==0) return s;
+ const char *p, *q;
+ int beginLen = qstrlen(begin);
+ int endLen = qstrlen(end);
+ int resLen = 0;
+ for (p=s; (q=strstr(p,begin))!=0; p=q+endLen)
+ {
+ resLen+=(int)(q-p);
+ p=q+beginLen;
+ if ((q=strstr(p,end))==0)
+ {
+ resLen+=beginLen;
+ break;
+ }
+ }
+ resLen+=qstrlen(p);
+ // resLen is the length of the string without the marked block
+
+ QCString result(resLen+1);
+ char *r;
+ for (r=result.rawData(), p=s; (q=strstr(p,begin))!=0; p=q+endLen)
+ {
+ int l = (int)(q-p);
+ memcpy(r,p,l);
+ r+=l;
+ p=q+beginLen;
+ if ((q=strstr(p,end))==0)
+ {
+ memcpy(r,begin,beginLen);
+ r+=beginLen;
+ break;
+ }
+ }
+ qstrcpy(r,p);
+ return result;
+}
+//----------------------------------------------------------------------
+
+QCString selectBlock(const QCString& s,const QCString &name,bool enable, OutputGenerator::OutputType o)
+{
+ // TODO: this is an expensive function that is called a lot -> optimize it
+ QCString begin;
+ QCString end;
+ QCString nobegin;
+ QCString noend;
+ switch (o)
+ {
+ case OutputGenerator::Html:
+ begin = "<!--BEGIN " + name + "-->";
+ end = "<!--END " + name + "-->";
+ nobegin = "<!--BEGIN !" + name + "-->";
+ noend = "<!--END !" + name + "-->";
+ break;
+ case OutputGenerator::Latex:
+ begin = "%%BEGIN " + name;
+ end = "%%END " + name;
+ nobegin = "%%BEGIN !" + name;
+ noend = "%%END !" + name;
+ break;
+ default:
+ break;
+ }
+
+ QCString result = s;
+ if (enable)
+ {
+ result = substitute(result, begin, "");
+ result = substitute(result, end, "");
+ result = clearBlock(result, nobegin, noend);
+ }
+ else
+ {
+ result = substitute(result, nobegin, "");
+ result = substitute(result, noend, "");
+ result = clearBlock(result, begin, end);
+ }
+
+ return result;
+}
+
+QCString removeEmptyLines(const QCString &s)
+{
+ BufStr out(s.length()+1);
+ const char *p=s.data();
+ if (p)
+ {
+ char c;
+ while ((c=*p++))
+ {
+ if (c=='\n')
+ {
+ const char *e = p;
+ while (*e==' ' || *e=='\t') e++;
+ if (*e=='\n')
+ {
+ p=e;
+ }
+ else out.addChar(c);
+ }
+ else
+ {
+ out.addChar(c);
+ }
+ }
+ }
+ out.addChar('\0');
+ //printf("removeEmptyLines(%s)=%s\n",s.data(),out.data());
+ return out.data();
+}
diff --git a/src/util.h b/src/util.h
index b19e1c5..6d50d88 100644
--- a/src/util.h
+++ b/src/util.h
@@ -35,6 +35,7 @@
#include "arguments.h"
#include "containers.h"
#include "namespacedef.h"
+#include "outputgen.h"
//--------------------------------------------------------------------
@@ -168,8 +169,8 @@ QCString substituteClassNames(const QCString &s);
QCString clearBlock(const char *s,const char *begin,const char *end);
-
-QCString selectBlock(const QCString& s,const QCString &name,bool which);
+QCString selectBlock(const QCString& s,const QCString &name,bool enable, OutputGenerator::OutputType o);
+QCString removeEmptyLines(const QCString &s);
QCString resolveDefines(const char *n);
diff --git a/templates/latex/footer.tex b/templates/latex/footer.tex
new file mode 100755
index 0000000..0227221
--- /dev/null
+++ b/templates/latex/footer.tex
@@ -0,0 +1,50 @@
+%--- End generated contents ---
+
+%%BEGIN CITATIONS_PRESENT
+ % Bibliography
+ \newpage
+ \phantomsection
+
+%%BEGIN !PDF_HYPERLINKS
+ \clearemptydoublepage
+%%BEGIN COMPACT_LATEX
+ \addcontentsline{toc}{section}{$latexcitereference}
+%%END COMPACT_LATEX
+%%BEGIN !COMPACT_LATEX
+ \addcontentsline{toc}{chapter}{$latexcitereference}
+%%END !COMPACT_LATEX
+ \printindex
+%%END !PDF_HYPERLINKS
+
+ \bibliographystyle{$latexbibstyle}
+ \bibliography{$latexbibfiles}
+%%BEGIN PDF_HYPERLINKS
+%%BEGIN COMPACT_LATEX
+ \addcontentsline{toc}{section}{$latexcitereference}
+%%END COMPACT_LATEX
+%%BEGIN !COMPACT_LATEX
+ \addcontentsline{toc}{chapter}{$latexcitereference}
+%%END !COMPACT_LATEX
+%%END PDF_HYPERLINKS
+
+%%END CITATIONS_PRESENT
+
+% Index
+%%BEGIN !COMPACT_LATEX
+ \backmatter
+%%END !COMPACT_LATEX
+ \newpage
+ \phantomsection
+ \clearemptydoublepage
+%%BEGIN COMPACT_LATEX
+ \addcontentsline{toc}{section}{\indexname}
+%%END COMPACT_LATEX
+%%BEGIN !COMPACT_LATEX
+ \addcontentsline{toc}{chapter}{\indexname}
+%%END !COMPACT_LATEX
+ \printindex
+
+% Required for some languages (in combination with latexdocumentpre from the header)
+$latexdocumentpost
+\end{document}
+
diff --git a/templates/latex/header.tex b/templates/latex/header.tex
new file mode 100644
index 0000000..a9446d7
--- /dev/null
+++ b/templates/latex/header.tex
@@ -0,0 +1,249 @@
+ % Handle batch mode
+%%BEGIN LATEX_BATCHMODE
+ \batchmode
+%%END LATEX_BATCHMODE
+
+ % to overcome problems with too many open files
+ \let\mypdfximage\pdfximage\def\pdfximage{\immediate\mypdfximage}
+
+ % Set document class depending on configuration
+%%BEGIN COMPACT_LATEX
+ \documentclass[twoside]{article}
+%%END COMPACT_LATEX
+%%BEGIN !COMPACT_LATEX
+ \documentclass[twoside]{book}
+%%END !COMPACT_LATEX
+
+ %% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package
+ \usepackage{ifthen}
+ \ifx\requestedLaTeXdate\undefined
+ \usepackage{array}
+ \else
+ \usepackage{array}[=2016-10-06]
+ \fi
+ %%
+
+ % Packages required by doxygen
+ \usepackage{fixltx2e} % for \textsubscript
+ \usepackage{doxygen}
+
+ $extralatexstylesheet
+
+ \usepackage{graphicx}
+ \usepackage[utf8]{inputenc}
+ \usepackage{makeidx}
+ \PassOptionsToPackage{warn}{textcomp}
+ \usepackage{textcomp}
+ \usepackage[nointegrals]{wasysym}
+ \usepackage{ifxetex}
+
+ % NLS support packages
+ $languagesupport
+
+ % Define default fonts
+ % Font selection
+%%BEGIN LATEX_FONTENC
+ \usepackage[$latexfontenc]{fontenc}
+%%END LATEX_FONTENC
+
+ % set main and monospaced font
+ $latexfont
+
+ \usepackage{sectsty}
+ \allsectionsfont{%
+ \fontseries{bc}\selectfont%
+ \color{darkgray}%
+ }
+ \renewcommand{\DoxyLabelFont}{%
+ \fontseries{bc}\selectfont%
+ \color{darkgray}%
+ }
+ \newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}}
+
+ % Arguments of doxygenemoji:
+ % 1) ':<text>:' form of the emoji, already LaTeX-escaped
+ % 2) file with the name of the emoji without the .png extension
+ % in case image exist use this otherwise use the ':<text>:' form
+ \newcommand{\doxygenemoji}[2]{%
+ \IfFileExists{$latexemojidirectory/#2.png}{\raisebox{-0.1em}{\includegraphics[height=0.9em]{$latexemojidirectory/#2.png}}}{#1}%
+ }
+
+ % Page & text layout
+ \usepackage{geometry}
+ \geometry{%
+ $papertype,%
+ top=2.5cm,%
+ bottom=2.5cm,%
+ left=2.5cm,%
+ right=2.5cm%
+ }
+
+ % Allow a bit of overflow to go unnoticed by other means
+ \tolerance=750
+ \hfuzz=15pt
+ \hbadness=750
+ \setlength{\emergencystretch}{15pt}
+ \setlength{\parindent}{0cm}
+ \newcommand{\doxynormalparskip}{\setlength{\parskip}{3ex plus 2ex minus 2ex}}
+ \newcommand{\doxytocparskip}{\setlength{\parskip}{1ex plus 0ex minus 0ex}}
+ \doxynormalparskip
+ % Redefine paragraph/subparagraph environments, using sectsty fonts
+ \makeatletter
+ \renewcommand{\paragraph}{%
+ \@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{%
+ \normalfont\normalsize\bfseries\SS@parafont%
+ }%
+ }
+ \renewcommand{\subparagraph}{%
+ \@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{%
+ \normalfont\normalsize\bfseries\SS@subparafont%
+ }%
+ }
+ \makeatother
+
+ \makeatletter
+ \newcommand\hrulefilll{\leavevmode\leaders\hrule\hskip 0pt plus 1filll\kern\z@}
+ \makeatother
+
+ % Headers & footers
+ \usepackage{fancyhdr}
+ \pagestyle{fancyplain}
+ \renewcommand{\footrulewidth}{0.4pt}
+
+ \fancypagestyle{fancyplain}{
+ \fancyhf{}
+ \fancyhead[LE, RO]{\bfseries\thepage}
+ \fancyhead[LO]{\bfseries\rightmark}
+ \fancyhead[RE]{\bfseries\leftmark}
+ \fancyfoot[LO, RE]{\bfseries\scriptsize $generatedby Doxygen }
+ }
+
+ \fancypagestyle{plain}{
+ \fancyhf{}
+ \fancyfoot[LO, RE]{\bfseries\scriptsize $generatedby Doxygen }
+ \renewcommand{\headrulewidth}{0pt}
+ }
+
+ \pagestyle{fancyplain}
+
+
+%%BEGIN !COMPACT_LATEX
+ \renewcommand{\chaptermark}[1]{%
+ \markboth{#1}{}%
+ }
+%%END !COMPACT_LATEX
+ \renewcommand{\sectionmark}[1]{%
+ \markright{\thesection\ #1}%
+ }
+
+ % ToC, LoF, LoT, bibliography, and index
+ % Indices & bibliography
+ \usepackage{natbib}
+ \usepackage[titles]{tocloft}
+ \setcounter{tocdepth}{3}
+ \setcounter{secnumdepth}{5}
+
+ % creating indexes
+ $makeindex
+
+ $extralatexpackages
+
+ $latexspecialformulachars
+
+%%BEGIN FORMULA_MACROFILE
+ \input{$formulamacrofile}
+%%END FORMULA_MACROFILE
+
+ % Hyperlinks
+%%BEGIN PDF_HYPERLINKS
+ % Hyperlinks (required, but should be loaded last)
+ \ifpdf
+ \usepackage[pdftex,pagebackref=true]{hyperref}
+ \else
+ \ifxetex
+ \usepackage[pagebackref=true]{hyperref}
+ \else
+ \usepackage[ps2pdf,pagebackref=true]{hyperref}
+ \fi
+ \fi
+
+ \hypersetup{%
+ colorlinks=true,%
+ linkcolor=blue,%
+ citecolor=blue,%
+ unicode%
+ }
+
+%%END PDF_HYPERLINKS
+
+ % Custom commands used by the header
+ % Custom commands
+ \newcommand{\clearemptydoublepage}{%
+ \newpage{\pagestyle{empty}\cleardoublepage}%
+ }
+
+ % caption style definition
+ \usepackage{caption}
+ \captionsetup{labelsep=space,justification=centering,font={bf},singlelinecheck=off,skip=4pt,position=top}
+
+
+ % in page table of contents
+ \usepackage{etoc}
+ \etocsettocstyle{\doxytocparskip}{\doxynormalparskip}
+
+ % prevent numbers overlap the titles in toc
+ \renewcommand{\numberline}[1]{#1~}
+
+% End of preamble, now comes the document contents
+%===== C O N T E N T S =====
+
+\begin{document}
+ \raggedbottom
+
+ $latexdocumentpre
+
+ % Titlepage & ToC
+%%BEGIN PDF_HYPERLINKS
+%%BEGIN USE_PDFLATEX
+ % To avoid duplicate page anchors due to reuse of same numbers for
+ % the index (be it as roman numbers)
+ \hypersetup{pageanchor=false,
+ bookmarksnumbered=true,
+ pdfencoding=unicode
+ }
+%%END USE_PDFLATEX
+%%END PDF_HYPERLINKS
+ \pagenumbering{alph}
+ \begin{titlepage}
+ \vspace*{7cm}
+ \begin{center}%
+ {\Large $title}\\
+ \vspace*{1cm}
+ {\large $generatedby Doxygen $doxygenversion}\\
+%%BEGIN LATEX_TIMESTAMP
+ \vspace*{0.5cm}
+ {\small $datetime}
+%%END LATEX_TIMESTAMP
+ \end{center}
+ \end{titlepage}
+
+%%BEGIN !COMPACT_LATEX
+ \clearemptydoublepage
+%%END !COMPACT_LATEX
+ \pagenumbering{roman}
+
+ \tableofcontents
+%%BEGIN !COMPACT_LATEX
+ \clearemptydoublepage
+%%END !COMPACT_LATEX
+ \pagenumbering{arabic}
+
+%%BEGIN PDF_HYPERLINKS
+%%BEGIN USE_PDFLATEX
+ % re-enable anchors again
+ \hypersetup{pageanchor=true}
+%%END USE_PDFLATEX
+%%END PDF_HYPERLINKS
+
+%--- Begin generated contents ---
+