/******************************************************************************
*
- *
- *
- *
- * Copyright (C) 1997-2015 by Dimitri van Heesch.
+ * Copyright (C) 1997-2022 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
*/
#include <algorithm>
+#include <array>
#include "htmlattrib.h"
#include "latexdocvisitor.h"
#include "language.h"
#include "doxygen.h"
#include "outputgen.h"
+#include "outputlist.h"
#include "dot.h"
#include "util.h"
#include "message.h"
#include "plantuml.h"
#include "fileinfo.h"
#include "regex.h"
+#include "portable.h"
-const int maxLevels=5;
-static const char *secLabels[maxLevels] =
- { "doxysection","doxysubsection","doxysubsubsection","doxyparagraph","doxysubparagraph" };
+static const int g_maxLevels = 7;
+static const std::array<const char *,g_maxLevels> g_secLabels =
+{ "doxysection",
+ "doxysubsection",
+ "doxysubsubsection",
+ "doxysubsubsubsection",
+ "doxysubsubsubsubsection",
+ "doxysubsubsubsubsubsection",
+ "doxysubsubsubsubsubsubsection"
+};
-static const char *getSectionName(int level)
+static const char *g_paragraphLabel = "doxyparagraph";
+static const char *g_subparagraphLabel = "doxysubparagraph";
+
+const char *LatexDocVisitor::getSectionName(int level) const
{
bool compactLatex = Config_getBool(COMPACT_LATEX);
int l = level;
if (compactLatex) l++;
- if (Doxygen::insideMainPage) l--;
- return secLabels[std::min(maxLevels-1,l)];
+
+ if (l <= 3)
+ {
+ // Sections get special treatment because they inherit the parent's level
+ l += m_hierarchyLevel; /* May be -1 if generating main page */
+ if (l >= g_maxLevels)
+ {
+ l = g_maxLevels - 1;
+ }
+ else if (l < 0)
+ {
+ /* Should not happen; level is always >= 1 and hierarchyLevel >= -1 */
+ l = 0;
+ }
+ return g_secLabels[l];
+ }
+ else if (l == 4)
+ {
+ return g_paragraphLabel;
+ }
+ else
+ {
+ return g_subparagraphLabel;
+ }
}
static void insertDimension(TextStream &t, QCString dimension, const char *orientationString)
}
-LatexDocVisitor::LatexDocVisitor(TextStream &t,LatexCodeGenerator &ci,
- const QCString &langExt,bool insideTabbing)
- : m_t(t), m_ci(ci), m_insidePre(FALSE),
+LatexDocVisitor::LatexDocVisitor(TextStream &t,OutputCodeList &ci,LatexCodeGenerator &lcg,
+ const QCString &langExt, int hierarchyLevel)
+ : m_t(t), m_ci(ci), m_lcg(lcg), m_insidePre(FALSE),
m_insideItem(FALSE), m_hide(FALSE),
- m_insideTabbing(insideTabbing), m_langExt(langExt)
+ m_langExt(langExt), m_hierarchyLevel(hierarchyLevel)
{
}
{
if (m_hide) return;
bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
- const char *res = HtmlEntityMapper::instance()->latex(s.symbol());
+ const char *res = HtmlEntityMapper::instance().latex(s.symbol());
if (res)
{
if (((s.symbol() == HtmlEntityMapper::Sym_lt) || (s.symbol() == HtmlEntityMapper::Sym_Less))&& (!m_insidePre))
}
else
{
- err("LaTeX: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s.symbol(),TRUE));
+ err("LaTeX: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance().html(s.symbol(),TRUE));
}
}
void LatexDocVisitor::operator()(const DocEmoji &s)
{
if (m_hide) return;
- QCString emojiName = EmojiEntityMapper::instance()->name(s.index());
+ QCString emojiName = EmojiEntityMapper::instance().name(s.index());
if (!emojiName.isEmpty())
{
QCString imageName=emojiName.mid(1,emojiName.length()-2); // strip : at start and end
break;
case DocStyleChange::Div: /* HTML only */ break;
case DocStyleChange::Span: /* HTML only */ break;
- case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */
- if (s.enable()) m_t << "{\\bfseries{"; else m_t << "}}\\newline";
- break;
}
}
dotindex++,
".dot"
);
- std::ofstream file(fileName.str(),std::ofstream::out | std::ofstream::binary);
+ std::ofstream file = Portable::openOutputStream(fileName);
if (!file.is_open())
{
err("Could not open file %s for writing\n",qPrint(fileName));
qPrint(Config_getString(LATEX_OUTPUT)+"/inline_mscgraph_"),
mscindex++
);
- std::string fileName = baseName.str()+".msc";
- std::ofstream file(fileName,std::ofstream::out | std::ofstream::binary);
+ QCString fileName = baseName+".msc";
+ std::ofstream file = Portable::openOutputStream(fileName);
if (!file.is_open())
{
- err("Could not open file %s for writing\n",fileName.c_str());
+ err("Could not open file %s for writing\n",qPrint(fileName));
}
else
{
writeMscFile(baseName, s);
- if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName);
+ if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
}
}
break;
{
m_ci.startCodeFragment("DoxyCodeInclude");
FileInfo cfi( inc.file().str() );
- FileDef *fd = createFileDef( cfi.dirPath(), cfi.fileName() );
+ auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
getCodeParser(inc.extension()).parseCode(m_ci,inc.context(),
inc.text(),
langExt,
inc.isExample(),
inc.exampleFile(),
- fd, // fileDef,
+ fd.get(), // fileDef,
-1, // start line
-1, // end line
FALSE, // inline fragment
0, // memberDef
TRUE // show line numbers
);
- delete fd;
m_ci.endCodeFragment("DoxyCodeInclude");
}
break;
m_t << "\\end{DoxyVerbInclude}\n";
break;
case DocInclude::Snippet:
+ case DocInclude::SnippetTrimLeft:
{
m_ci.startCodeFragment("DoxyCodeInclude");
getCodeParser(inc.extension()).parseCode(m_ci,
inc.context(),
- extractBlock(inc.text(),inc.blockId()),
+ extractBlock(inc.text(),inc.blockId(),inc.type()==DocInclude::SnippetTrimLeft),
langExt,
inc.isExample(),
inc.exampleFile()
case DocInclude::SnipWithLines:
{
FileInfo cfi( inc.file().str() );
- FileDef *fd = createFileDef( cfi.dirPath(), cfi.fileName() );
+ auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
m_ci.startCodeFragment("DoxyCodeInclude");
getCodeParser(inc.extension()).parseCode(m_ci,
inc.context(),
langExt,
inc.isExample(),
inc.exampleFile(),
- fd,
+ fd.get(),
lineBlock(inc.text(),inc.blockId()),
-1, // endLine
FALSE, // inlineFragment
0, // memberDef
TRUE // show line number
);
- delete fd;
m_ci.endCodeFragment("DoxyCodeInclude");
}
break;
m_hide = popHidden();
if (!m_hide)
{
- FileDef *fd = 0;
+ std::unique_ptr<FileDef> fd;
if (!op.includeFileName().isEmpty())
{
FileInfo cfi( op.includeFileName().str() );
getCodeParser(locLangExt).parseCode(m_ci,op.context(),op.text(),langExt,
op.isExample(),op.exampleFile(),
- fd, // fileDef
+ fd.get(), // fileDef
op.line(), // startLine
-1, // endLine
FALSE, // inline fragment
0, // memberDef
op.showLineNo() // show line numbers
);
- if (fd) delete fd;
}
pushHidden(m_hide);
m_hide=TRUE;
void LatexDocVisitor::operator()(const DocSection &s)
{
if (m_hide) return;
- if (Config_getBool(PDF_HYPERLINKS))
+ bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
+ if (pdfHyperlinks)
{
m_t << "\\hypertarget{" << stripPath(s.file()) << "_" << s.anchor() << "}{}";
}
m_t << "\\" << getSectionName(s.level()) << "{";
+ if (pdfHyperlinks)
+ {
+ m_t << "\\texorpdfstring{";
+ }
filter(convertCharEntitiesToUTF8(s.title()));
+ if (pdfHyperlinks)
+ {
+ m_t << "}{" << latexEscapePDFString(convertCharEntitiesToUTF8(s.title())) << "}";
+ }
m_t << "}\\label{" << stripPath(s.file()) << "_" << s.anchor() << "}\n";
visitChildren(s);
}
m_t << "}}";
}
+void LatexDocVisitor::operator()(const DocHtmlSummary &d)
+{
+ if (m_hide) return;
+ m_t << "{\\bfseries{";
+ visitChildren(d);
+ m_t << "}}";
+}
+
void LatexDocVisitor::operator()(const DocHtmlDetails &d)
{
if (m_hide) return;
m_t << "\n\n";
+ auto summary = d.summary();
+ if (summary)
+ {
+ std::visit(*this,*summary);
+ m_t << "\\begin{adjustwidth}{1em}{0em}\n";
+ }
visitChildren(d);
- m_t << "\n\n";
+ if (summary)
+ {
+ m_t << "\\end{adjustwidth}\n";
+ }
+ else
+ {
+ m_t << "\n\n";
+ }
}
void LatexDocVisitor::operator()(const DocHtmlHeader &header)
}
else
{
- if (!ref.file().isEmpty()) startLink(ref.ref(),ref.file(),ref.anchor(),ref.refToTable());
+ if (!ref.file().isEmpty()) startLink(ref.ref(),ref.file(),ref.anchor(),ref.refToTable(),ref.refToSection());
}
if (!ref.hasLinkText())
{
}
else
{
- if (!ref.file().isEmpty()) endLink(ref.ref(),ref.file(),ref.anchor(),ref.refToTable());
+ if (!ref.file().isEmpty()) endLink(ref.ref(),ref.file(),ref.anchor(),ref.refToTable(),ref.refToSection(),ref.sectionType());
}
}
if (m_hide) return;
bool hasInOutSpecs = s.hasInOutSpecifier();
bool hasTypeSpecs = s.hasTypeSpecifier();
- m_ci.incUsedTableLevel();
+ m_lcg.incUsedTableLevel();
switch(s.type())
{
case DocParamSect::Param:
}
m_t << "}\n";
visitChildren(s);
- m_ci.decUsedTableLevel();
+ m_lcg.decUsedTableLevel();
switch(s.type())
{
case DocParamSect::Param:
void LatexDocVisitor::filter(const QCString &str, const bool retainNewLine)
{
+ //printf("LatexDocVisitor::filter(%s) m_insideTabbing=%d\n",qPrint(str),m_ci.insideTabbing());
filterLatexString(m_t,str,
- m_insideTabbing,
+ m_lcg.insideTabbing(),
m_insidePre,
m_insideItem,
- m_ci.usedTableLevel()>0, // insideTable
+ m_lcg.usedTableLevel()>0, // insideTable
false, // keepSpaces
retainNewLine
);
}
-void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor,bool refToTable)
+void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor,bool refToTable,bool refToSection)
{
bool pdfHyperLinks = Config_getBool(PDF_HYPERLINKS);
if (ref.isEmpty() && pdfHyperLinks) // internal PDF link
{
m_t << "\\doxytablelink{";
}
+ else if (refToSection)
+ {
+ m_t << "\\doxysectlink{";
+ }
else
{
- m_t << "\\mbox{\\hyperlink{";
+ m_t << "\\doxylink{";
}
if (!file.isEmpty()) m_t << stripPath(file);
if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
if (!anchor.isEmpty()) m_t << anchor;
m_t << "}{";
}
+ else if (ref.isEmpty() && refToSection)
+ {
+ m_t << "\\doxysectref{";
+ }
else if (ref.isEmpty() && refToTable)
{
m_t << "\\doxytableref{";
}
}
-void LatexDocVisitor::endLink(const QCString &ref,const QCString &file,const QCString &anchor,bool refToTable)
+void LatexDocVisitor::endLink(const QCString &ref,const QCString &file,const QCString &anchor,bool /*refToTable*/,bool refToSection, SectionType sectionType)
{
m_t << "}";
bool pdfHyperLinks = Config_getBool(PDF_HYPERLINKS);
m_t << "}{" << file;
if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
m_t << anchor << "}";
+ if (refToSection)
+ {
+ m_t << "{" << static_cast<int>(sectionType) << "}";
+ }
}
if (ref.isEmpty() && pdfHyperLinks) // internal PDF link
{
- if (!refToTable)
+ if (refToSection)
{
- m_t << "}";
+ m_t << "{" << static_cast<int>(sectionType) << "}";
}
}
}