summaryrefslogtreecommitdiff
path: root/src/htmldocvisitor.cpp
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2022-12-27 12:33:07 +0900
committerJinWang An <jinwang.an@samsung.com>2022-12-27 12:33:07 +0900
commit9cf4982ab5fc6d964e1a024ff91a72d1fee5dc00 (patch)
treea19f0c024ea91acd7177f41fb5f066023f49027b /src/htmldocvisitor.cpp
parent15e5c5601a13a41757e2a5e1a9105d1714d40215 (diff)
downloaddoxygen-upstream/1.9.4.tar.gz
doxygen-upstream/1.9.4.tar.bz2
doxygen-upstream/1.9.4.zip
Imported Upstream version 1.9.4upstream/1.9.4
Diffstat (limited to 'src/htmldocvisitor.cpp')
-rw-r--r--src/htmldocvisitor.cpp1608
1 files changed, 710 insertions, 898 deletions
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index d3f5c95..04598c2 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -102,66 +102,54 @@ static QCString convertIndexWordToAnchor(const QCString &word)
return result;
}
-static bool mustBeOutsideParagraph(const DocNode *n)
-{
- switch (n->kind())
- {
- /* <ul> */
- case DocNode::Kind_HtmlList:
- case DocNode::Kind_SimpleList:
- case DocNode::Kind_AutoList:
- /* <dl> */
- case DocNode::Kind_SimpleSect:
- case DocNode::Kind_ParamSect:
- case DocNode::Kind_HtmlDescList:
- case DocNode::Kind_XRefItem:
- /* <table> */
- case DocNode::Kind_HtmlTable:
- /* <h?> */
- case DocNode::Kind_Section:
- case DocNode::Kind_HtmlHeader:
- /* \internal */
- case DocNode::Kind_Internal:
- /* <div> */
- case DocNode::Kind_Include:
- case DocNode::Kind_SecRefList:
- /* <hr> */
- case DocNode::Kind_HorRuler:
- /* CopyDoc gets paragraph markers from the wrapping DocPara node,
- * but needs to insert them for all documentation being copied to
- * preserve formatting.
- */
- case DocNode::Kind_Copy:
- /* <blockquote> */
- case DocNode::Kind_HtmlBlockQuote:
- /* \parblock */
- case DocNode::Kind_ParBlock:
- case DocNode::Kind_IncOperator:
- return TRUE;
- case DocNode::Kind_Verbatim:
- {
- DocVerbatim *dv = (DocVerbatim*)n;
- DocVerbatim::Type t = dv->type();
- if (t == DocVerbatim::JavaDocCode || t == DocVerbatim::JavaDocLiteral) return FALSE;
- return t!=DocVerbatim::HtmlOnly || dv->isBlock();
- }
- case DocNode::Kind_StyleChange:
- return ((DocStyleChange*)n)->style()==DocStyleChange::Preformatted ||
- ((DocStyleChange*)n)->style()==DocStyleChange::Div ||
- ((DocStyleChange*)n)->style()==DocStyleChange::Center;
- case DocNode::Kind_Formula:
- return !((DocFormula*)n)->isInline();
- case DocNode::Kind_Image:
- return !((DocImage*)n)->isInlineImage();
- default:
- break;
+
+
+static bool mustBeOutsideParagraph(const DocNodeVariant &n)
+{
+ //printf("mustBeOutsideParagraph(%s)=",docNodeName(n));
+ if (holds_one_of_alternatives< /* <ul> */ DocHtmlList, DocSimpleList, DocAutoList,
+ /* <dl> */ DocSimpleSect, DocParamSect, DocHtmlDescList, DocXRefItem,
+ /* <table> */ DocHtmlTable,
+ /* <h?> */ DocSection, DocHtmlHeader,
+ /* \internal */ DocInternal,
+ /* <div> */ DocInclude, DocSecRefList,
+ /* <hr> */ DocHorRuler,
+ /* <blockquote> */ DocHtmlBlockQuote,
+ /* \parblock */ DocParBlock,
+ DocIncOperator >(n))
+ {
+ return TRUE;
+ }
+ const DocVerbatim *dv = std::get_if<DocVerbatim>(&n);
+ if (dv)
+ {
+ DocVerbatim::Type t = dv->type();
+ if (t == DocVerbatim::JavaDocCode || t == DocVerbatim::JavaDocLiteral) return FALSE;
+ return t!=DocVerbatim::HtmlOnly || dv->isBlock();
+ }
+ const DocStyleChange *sc = std::get_if<DocStyleChange>(&n);
+ if (sc)
+ {
+ return sc->style()==DocStyleChange::Preformatted ||
+ sc->style()==DocStyleChange::Div ||
+ sc->style()==DocStyleChange::Center;
+ }
+ const DocFormula *df = std::get_if<DocFormula>(&n);
+ if (df)
+ {
+ return !df->isInline();
+ }
+ const DocImage *di = std::get_if<DocImage>(&n);
+ if (di)
+ {
+ return !di->isInlineImage();
}
return FALSE;
}
-static bool isDocVerbatimVisible(const DocVerbatim *s)
+static bool isDocVerbatimVisible(const DocVerbatim &s)
{
- switch(s->type())
+ switch (s.type())
{
case DocVerbatim::ManOnly:
case DocVerbatim::LatexOnly:
@@ -174,9 +162,9 @@ static bool isDocVerbatimVisible(const DocVerbatim *s)
}
}
-static bool isDocIncludeVisible(const DocInclude *s)
+static bool isDocIncludeVisible(const DocInclude &s)
{
- switch (s->type())
+ switch (s.type())
{
case DocInclude::DontInclude:
case DocInclude::LatexInclude:
@@ -190,9 +178,9 @@ static bool isDocIncludeVisible(const DocInclude *s)
}
}
-static bool isDocIncOperatorVisible(const DocIncOperator *s)
+static bool isDocIncOperatorVisible(const DocIncOperator &s)
{
- switch (s->type())
+ switch (s.type())
{
case DocIncOperator::Skip:
return FALSE;
@@ -201,27 +189,34 @@ static bool isDocIncOperatorVisible(const DocIncOperator *s)
}
}
-static bool isInvisibleNode(const DocNode *node)
+static bool isInvisibleNode(const DocNodeVariant &node)
{
- return (node->kind()==DocNode::Kind_WhiteSpace)
- || // skip over image nodes that are not for HTML output
- (node->kind()==DocNode::Kind_Image && ((DocImage*)node)->type()!=DocImage::Html)
- || // skip over verbatim nodes that are not visible in the HTML output
- (node->kind()==DocNode::Kind_Verbatim && !isDocVerbatimVisible((DocVerbatim*)node))
- || // skip over include nodes that are not visible in the HTML output
- (node->kind()==DocNode::Kind_Include && !isDocIncludeVisible((DocInclude*)node))
- || // skip over include operator nodes that are not visible in the HTML output
- (node->kind()==DocNode::Kind_IncOperator && !isDocIncOperatorVisible((DocIncOperator*)node))
- ;
+ //printf("isInvisibleNode(%s)\n",docNodeName(node));
+ // skip over white space
+ const DocWhiteSpace *ws = std::get_if<DocWhiteSpace>(&node);
+ if (ws) return true;
+ // skip over image nodes that are not for HTML output
+ const DocImage *di = std::get_if<DocImage>(&node);
+ if (di) return di->type()!=DocImage::Html;
+ // skip over verbatim nodes that are not visible in the HTML output
+ const DocVerbatim *dv = std::get_if<DocVerbatim>(&node);
+ if (dv) return !isDocVerbatimVisible(*dv);
+ // skip over include nodes that are not visible in the HTML output
+ const DocInclude *dinc = std::get_if<DocInclude>(&node);
+ if (dinc) return !isDocIncludeVisible(*dinc);
+ const DocIncOperator *dio = std::get_if<DocIncOperator>(&node);
+ // skip over include operator nodes that are not visible in the HTML output
+ if (dio) return !isDocIncOperatorVisible(*dio);
+ return false;
}
static void mergeHtmlAttributes(const HtmlAttribList &attribs, HtmlAttribList &mergeInto)
{
for (const auto &att : attribs)
{
- auto it = std::find_if(mergeInto.begin(),mergeInto.end(),
+ auto it = std::find_if(std::begin(mergeInto),std::end(mergeInto),
[&att](const auto &opt) { return opt.name==att.name; });
- if (it!=mergeInto.end()) // attribute name already in mergeInto
+ if (it!=std::end(mergeInto)) // attribute name already in mergeInto
{
it->value = it->value + " " + att.value;
}
@@ -277,37 +272,50 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl
HtmlDocVisitor::HtmlDocVisitor(TextStream &t,CodeOutputInterface &ci,
const Definition *ctx)
- : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_ctx(ctx)
+ : m_t(t), m_ci(ci), m_ctx(ctx)
{
if (ctx) m_langExt=ctx->getDefFileExtension();
}
+template<class T>
+void HtmlDocVisitor::visitCaption(TextStream &t,const T &n)
+{
+ if (n.hasCaption())
+ {
+ t << "<div class=\"caption\">\n";
+ for (const auto &child : n.children())
+ {
+ std::visit(*this, child);
+ }
+ t << "</div>\n";
+ }
+}
+
//--------------------------------------
// visitor functions for leaf nodes
//--------------------------------------
-void HtmlDocVisitor::visit(DocWord *w)
+void HtmlDocVisitor::operator()(const DocWord &w)
{
- //printf("word: %s\n",qPrint(w->word()));
if (m_hide) return;
- filter(w->word());
+ filter(w.word());
}
-void HtmlDocVisitor::visit(DocLinkedWord *w)
+void HtmlDocVisitor::operator()(const DocLinkedWord &w)
{
if (m_hide) return;
- //printf("linked word: %s\n",qPrint(w->word()));
- startLink(w->ref(),w->file(),w->relPath(),w->anchor(),w->tooltip());
- filter(w->word());
+ //printf("linked word: %s\n",qPrint(w.word()));
+ startLink(w.ref(),w.file(),w.relPath(),w.anchor(),w.tooltip());
+ filter(w.word());
endLink();
}
-void HtmlDocVisitor::visit(DocWhiteSpace *w)
+void HtmlDocVisitor::operator()(const DocWhiteSpace &w)
{
if (m_hide) return;
if (m_insidePre)
{
- m_t << w->chars();
+ m_t << w.chars();
}
else
{
@@ -315,39 +323,40 @@ void HtmlDocVisitor::visit(DocWhiteSpace *w)
}
}
-void HtmlDocVisitor::visit(DocSymbol *s)
+void HtmlDocVisitor::operator()(const DocSymbol &s)
{
if (m_hide) return;
if (m_insideTitle &&
- (s->symbol()==DocSymbol::Sym_Quot || s->symbol()==DocSymbol::Sym_quot)) // escape "'s inside title="..."
+ (s.symbol()==HtmlEntityMapper::Sym_Quot || s.symbol()==HtmlEntityMapper::Sym_quot)) // escape "'s inside title="..."
{
m_t << "&quot;";
}
else
{
- const char *res = HtmlEntityMapper::instance()->html(s->symbol());
+ const char *res = HtmlEntityMapper::instance()->html(s.symbol());
if (res)
{
m_t << res;
}
else
{
- err("HTML: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
+ err("HTML: non supported HTML-entity found: %s\n",
+ HtmlEntityMapper::instance()->html(s.symbol(),TRUE));
}
}
}
-void HtmlDocVisitor::visit(DocEmoji *s)
+void HtmlDocVisitor::operator()(const DocEmoji &s)
{
if (m_hide) return;
- const char *res = EmojiEntityMapper::instance()->unicode(s->index());
+ const char *res = EmojiEntityMapper::instance()->unicode(s.index());
if (res)
{
- m_t << "<span class=\"emoji\">"<<res<<"</span>";
+ m_t << "<span class=\"emoji\">" << res << "</span>";
}
else
{
- m_t << s->name();
+ m_t << s.name();
}
}
@@ -379,12 +388,12 @@ void HtmlDocVisitor::writeObfuscatedMailAddress(const QCString &url)
}
}
-void HtmlDocVisitor::visit(DocURL *u)
+void HtmlDocVisitor::operator()(const DocURL &u)
{
if (m_hide) return;
- if (u->isEmail()) // mail address
+ if (u.isEmail()) // mail address
{
- QCString url = u->url();
+ QCString url = u.url();
// obfuscate the mail address link
writeObfuscatedMailAddress(url);
if (!Config_getBool(OBFUSCATE_EMAILS))
@@ -411,66 +420,66 @@ void HtmlDocVisitor::visit(DocURL *u)
else // web address
{
m_t << "<a href=\"";
- m_t << u->url() << "\">";
- filter(u->url());
+ m_t << u.url() << "\">";
+ filter(u.url());
m_t << "</a>";
}
}
-void HtmlDocVisitor::visit(DocLineBreak *br)
+void HtmlDocVisitor::operator()(const DocLineBreak &br)
{
if (m_hide) return;
- m_t << "<br "<< htmlAttribsToString(br->attribs()) << " />\n";
+ m_t << "<br "<< htmlAttribsToString(br.attribs()) << " />\n";
}
-void HtmlDocVisitor::visit(DocHorRuler *hr)
+void HtmlDocVisitor::operator()(const DocHorRuler &hr)
{
if (m_hide) return;
forceEndParagraph(hr);
- m_t << "<hr "<< htmlAttribsToString(hr->attribs()) << " />\n";
+ m_t << "<hr "<< htmlAttribsToString(hr.attribs()) << " />\n";
forceStartParagraph(hr);
}
-void HtmlDocVisitor::visit(DocStyleChange *s)
+void HtmlDocVisitor::operator()(const DocStyleChange &s)
{
if (m_hide) return;
- switch (s->style())
+ switch (s.style())
{
case DocStyleChange::Bold:
- if (s->enable()) m_t << "<b" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</b>";
+ if (s.enable()) m_t << "<b" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</b>";
break;
case DocStyleChange::S:
- if (s->enable()) m_t << "<s" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</s>";
+ if (s.enable()) m_t << "<s" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</s>";
break;
case DocStyleChange::Strike:
- if (s->enable()) m_t << "<strike" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</strike>";
+ if (s.enable()) m_t << "<strike" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</strike>";
break;
case DocStyleChange::Del:
- if (s->enable()) m_t << "<del" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</del>";
+ if (s.enable()) m_t << "<del" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</del>";
break;
case DocStyleChange::Underline:
- if (s->enable()) m_t << "<u" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</u>";
+ if (s.enable()) m_t << "<u" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</u>";
break;
case DocStyleChange::Ins:
- if (s->enable()) m_t << "<ins" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</ins>";
+ if (s.enable()) m_t << "<ins" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</ins>";
break;
case DocStyleChange::Italic:
- if (s->enable()) m_t << "<em" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</em>";
+ if (s.enable()) m_t << "<em" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</em>";
break;
case DocStyleChange::Code:
- if (s->enable()) m_t << "<code" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</code>";
+ if (s.enable()) m_t << "<code" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</code>";
break;
case DocStyleChange::Subscript:
- if (s->enable()) m_t << "<sub" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</sub>";
+ if (s.enable()) m_t << "<sub" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</sub>";
break;
case DocStyleChange::Superscript:
- if (s->enable()) m_t << "<sup" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</sup>";
+ if (s.enable()) m_t << "<sup" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</sup>";
break;
case DocStyleChange::Center:
- if (s->enable())
+ if (s.enable())
{
forceEndParagraph(s);
- m_t << "<center" << htmlAttribsToString(s->attribs()) << ">";
+ m_t << "<center" << htmlAttribsToString(s.attribs()) << ">";
}
else
{
@@ -479,16 +488,16 @@ void HtmlDocVisitor::visit(DocStyleChange *s)
}
break;
case DocStyleChange::Small:
- if (s->enable()) m_t << "<small" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</small>";
+ if (s.enable()) m_t << "<small" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</small>";
break;
case DocStyleChange::Cite:
- if (s->enable()) m_t << "<cite" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</cite>";
+ if (s.enable()) m_t << "<cite" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</cite>";
break;
case DocStyleChange::Preformatted:
- if (s->enable())
+ if (s.enable())
{
forceEndParagraph(s);
- m_t << "<pre" << htmlAttribsToString(s->attribs()) << ">";
+ m_t << "<pre" << htmlAttribsToString(s.attribs()) << ">";
m_insidePre=TRUE;
}
else
@@ -499,10 +508,10 @@ void HtmlDocVisitor::visit(DocStyleChange *s)
}
break;
case DocStyleChange::Div:
- if (s->enable())
+ if (s.enable())
{
forceEndParagraph(s);
- m_t << "<div" << htmlAttribsToString(s->attribs()) << ">";
+ m_t << "<div" << htmlAttribsToString(s.attribs()) << ">";
}
else
{
@@ -511,61 +520,39 @@ void HtmlDocVisitor::visit(DocStyleChange *s)
}
break;
case DocStyleChange::Span:
- if (s->enable()) m_t << "<span" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</span>";
+ if (s.enable()) m_t << "<span" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</span>";
break;
case DocStyleChange::Details:
- if (s->enable()) m_t << "<details" << htmlAttribsToString(s->attribs()) << ">\n"; else m_t << "</details>\n";
+ if (s.enable()) m_t << "<details" << htmlAttribsToString(s.attribs()) << ">\n"; else m_t << "</details>\n";
break;
case DocStyleChange::Summary:
- if (s->enable()) m_t << "<summary" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</summary>";
+ if (s.enable()) m_t << "<summary" << htmlAttribsToString(s.attribs()) << ">"; else m_t << "</summary>";
break;
}
}
+///--------------------------------------------------------------------------------------
-static void visitPreCaption(TextStream &t, DocVerbatim *s)
-{
- if (s->hasCaption())
- {
- t << "<div class=\"caption\">\n";
- }
-}
-
-
-static void visitPostCaption(TextStream &t, DocVerbatim *s)
-{
- if (s->hasCaption())
- {
- t << "</div>\n";
- }
-}
-
-
-static void visitCaption(HtmlDocVisitor *parent, DocNodeList &children)
-{
- for (const auto &n : children) n->accept(parent);
-}
-
-void HtmlDocVisitor::visit(DocVerbatim *s)
+void HtmlDocVisitor::operator()(const DocVerbatim &s)
{
if (m_hide) return;
QCString lang = m_langExt;
- if (!s->language().isEmpty()) // explicit language setting
+ if (!s.language().isEmpty()) // explicit language setting
{
- lang = s->language();
+ lang = s.language();
}
SrcLangExt langExt = getLanguageFromCodeLang(lang);
- switch(s->type())
+ switch(s.type())
{
case DocVerbatim::Code:
forceEndParagraph(s);
m_ci.startCodeFragment("DoxyCode");
getCodeParser(lang).parseCode(m_ci,
- s->context(),
- s->text(),
+ s.context(),
+ s.text(),
langExt,
- s->isExample(),
- s->exampleFile(),
+ s.isExample(),
+ s.exampleFile(),
0, // fileDef
-1, // startLine
-1, // endLine
@@ -580,23 +567,23 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
case DocVerbatim::Verbatim:
forceEndParagraph(s);
m_t << "<pre class=\"fragment\">";
- filter(s->text());
+ filter(s.text());
m_t << "</pre>";
forceStartParagraph(s);
break;
case DocVerbatim::JavaDocLiteral:
- filter(s->text(), true);
+ filter(s.text(), true);
break;
case DocVerbatim::JavaDocCode:
m_t << "<code class=\"JavaDocCode\">";
- filter(s->text(), true);
+ filter(s.text(), true);
m_t << "</code>";
break;
case DocVerbatim::HtmlOnly:
{
- if (s->isBlock()) forceEndParagraph(s);
- m_t << s->text();
- if (s->isBlock()) forceStartParagraph(s);
+ if (s.isBlock()) forceEndParagraph(s);
+ m_t << s.text();
+ if (s.isBlock()) forceStartParagraph(s);
}
break;
case DocVerbatim::ManOnly:
@@ -625,15 +612,13 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
}
else
{
- QCString stext = s->text();
+ QCString stext = s.text();
file.write( stext.data(), stext.length() );
file.close();
m_t << "<div class=\"dotgraph\">\n";
- writeDotFile(fileName,s->relPath(),s->context(),s->srcFile(),s->srcLine());
- visitPreCaption(m_t, s);
- visitCaption(this, s->children());
- visitPostCaption(m_t, s);
+ writeDotFile(fileName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
+ visitCaption(m_t, s);
m_t << "</div>\n";
if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
@@ -660,17 +645,15 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
else
{
QCString text = "msc {";
- text+=s->text();
+ text+=s.text();
text+="}";
file.write( text.data(), text.length() );
file.close();
m_t << "<div class=\"mscgraph\">\n";
- writeMscFile(baseName+".msc",s->relPath(),s->context(),s->srcFile(),s->srcLine());
- visitPreCaption(m_t, s);
- visitCaption(this, s->children());
- visitPostCaption(m_t, s);
+ writeMscFile(baseName+".msc",s.relPath(),s.context(),s.srcFile(),s.srcLine());
+ visitCaption(m_t, s);
m_t << "</div>\n";
if (Config_getBool(DOT_CLEANUP)) Dir().remove(baseName.str()+".msc");
@@ -681,7 +664,7 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
case DocVerbatim::PlantUML:
{
forceEndParagraph(s);
- static QCString htmlOutput = Config_getString(HTML_OUTPUT);
+ QCString htmlOutput = Config_getString(HTML_OUTPUT);
QCString imgExt = getDotImageExtension();
PlantumlManager::OutputFormat format = PlantumlManager::PUML_BITMAP; // default : PUML_BITMAP
if (imgExt=="svg")
@@ -689,13 +672,11 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
format = PlantumlManager::PUML_SVG;
}
QCString baseName = PlantumlManager::instance().writePlantUMLSource(
- htmlOutput,s->exampleFile(),
- s->text(),format,s->engine(),s->srcFile(),s->srcLine());
+ htmlOutput,s.exampleFile(),
+ s.text(),format,s.engine(),s.srcFile(),s.srcLine());
m_t << "<div class=\"plantumlgraph\">\n";
- writePlantUMLFile(baseName,s->relPath(),s->context(),s->srcFile(),s->srcLine());
- visitPreCaption(m_t, s);
- visitCaption(this, s->children());
- visitPostCaption(m_t, s);
+ writePlantUMLFile(baseName,s.relPath(),s.context(),s.srcFile(),s.srcLine());
+ visitCaption(m_t, s);
m_t << "</div>\n";
forceStartParagraph(s);
}
@@ -703,27 +684,27 @@ void HtmlDocVisitor::visit(DocVerbatim *s)
}
}
-void HtmlDocVisitor::visit(DocAnchor *anc)
+void HtmlDocVisitor::operator()(const DocAnchor &anc)
{
if (m_hide) return;
- m_t << "<a class=\"anchor\" id=\"" << anc->anchor() << "\"" << htmlAttribsToString(anc->attribs()) << "></a>";
+ m_t << "<a class=\"anchor\" id=\"" << anc.anchor() << "\"" << htmlAttribsToString(anc.attribs()) << "></a>";
}
-void HtmlDocVisitor::visit(DocInclude *inc)
+void HtmlDocVisitor::operator()(const DocInclude &inc)
{
if (m_hide) return;
- SrcLangExt langExt = getLanguageFromFileName(inc->extension());
- switch(inc->type())
+ SrcLangExt langExt = getLanguageFromFileName(inc.extension());
+ switch(inc.type())
{
case DocInclude::Include:
forceEndParagraph(inc);
m_ci.startCodeFragment("DoxyCode");
- getCodeParser(inc->extension()).parseCode(m_ci,
- inc->context(),
- inc->text(),
+ getCodeParser(inc.extension()).parseCode(m_ci,
+ inc.context(),
+ inc.text(),
langExt,
- inc->isExample(),
- inc->exampleFile(),
+ inc.isExample(),
+ inc.exampleFile(),
0, // fileDef
-1, // startLine
-1, // endLine
@@ -739,14 +720,14 @@ void HtmlDocVisitor::visit(DocInclude *inc)
{
forceEndParagraph(inc);
m_ci.startCodeFragment("DoxyCode");
- FileInfo cfi( inc->file().str() );
+ FileInfo cfi( inc.file().str() );
FileDef *fd = createFileDef( cfi.dirPath(), cfi.fileName() );
- getCodeParser(inc->extension()).parseCode(m_ci,
- inc->context(),
- inc->text(),
+ getCodeParser(inc.extension()).parseCode(m_ci,
+ inc.context(),
+ inc.text(),
langExt,
- inc->isExample(),
- inc->exampleFile(),
+ inc.isExample(),
+ inc.exampleFile(),
fd, // fileDef,
-1, // start line
-1, // end line
@@ -770,15 +751,15 @@ void HtmlDocVisitor::visit(DocInclude *inc)
break;
case DocInclude::HtmlInclude:
{
- if (inc->isBlock()) forceEndParagraph(inc);
- m_t << inc->text();
- if (inc->isBlock()) forceStartParagraph(inc);
+ if (inc.isBlock()) forceEndParagraph(inc);
+ m_t << inc.text();
+ if (inc.isBlock()) forceStartParagraph(inc);
}
break;
case DocInclude::VerbInclude:
forceEndParagraph(inc);
m_t << "<pre class=\"fragment\">";
- filter(inc->text());
+ filter(inc.text());
m_t << "</pre>";
forceStartParagraph(inc);
break;
@@ -786,12 +767,12 @@ void HtmlDocVisitor::visit(DocInclude *inc)
{
forceEndParagraph(inc);
m_ci.startCodeFragment("DoxyCode");
- getCodeParser(inc->extension()).parseCode(m_ci,
- inc->context(),
- extractBlock(inc->text(),inc->blockId()),
+ getCodeParser(inc.extension()).parseCode(m_ci,
+ inc.context(),
+ extractBlock(inc.text(),inc.blockId()),
langExt,
- inc->isExample(),
- inc->exampleFile(),
+ inc.isExample(),
+ inc.exampleFile(),
0,
-1, // startLine
-1, // endLine
@@ -808,16 +789,16 @@ void HtmlDocVisitor::visit(DocInclude *inc)
{
forceEndParagraph(inc);
m_ci.startCodeFragment("DoxyCode");
- FileInfo cfi( inc->file().str() );
+ FileInfo cfi( inc.file().str() );
FileDef *fd = createFileDef( cfi.dirPath(), cfi.fileName() );
- getCodeParser(inc->extension()).parseCode(m_ci,
- inc->context(),
- extractBlock(inc->text(),inc->blockId()),
+ getCodeParser(inc.extension()).parseCode(m_ci,
+ inc.context(),
+ extractBlock(inc.text(),inc.blockId()),
langExt,
- inc->isExample(),
- inc->exampleFile(),
+ inc.isExample(),
+ inc.exampleFile(),
fd,
- lineBlock(inc->text(),inc->blockId()),
+ lineBlock(inc.text(),inc.blockId()),
-1, // endLine
FALSE, // inlineFragment
0, // memberDef
@@ -837,44 +818,44 @@ void HtmlDocVisitor::visit(DocInclude *inc)
}
}
-void HtmlDocVisitor::visit(DocIncOperator *op)
+void HtmlDocVisitor::operator()(const DocIncOperator &op)
{
//printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
- // op->type(),op->isFirst(),op->isLast(),qPrint(op->text()));
- if (op->isFirst())
+ // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
+ if (op.isFirst())
{
forceEndParagraph(op);
if (!m_hide) m_ci.startCodeFragment("DoxyCode");
pushHidden(m_hide);
m_hide=TRUE;
}
- QCString locLangExt = getFileNameExtension(op->includeFileName());
+ QCString locLangExt = getFileNameExtension(op.includeFileName());
if (locLangExt.isEmpty()) locLangExt = m_langExt;
SrcLangExt langExt = getLanguageFromFileName(locLangExt);
- if (op->type()!=DocIncOperator::Skip)
+ if (op.type()!=DocIncOperator::Skip)
{
m_hide = popHidden();
if (!m_hide)
{
FileDef *fd = 0;
- if (!op->includeFileName().isEmpty())
+ if (!op.includeFileName().isEmpty())
{
- FileInfo cfi( op->includeFileName().str() );
+ FileInfo cfi( op.includeFileName().str() );
fd = createFileDef( cfi.dirPath(), cfi.fileName() );
}
getCodeParser(locLangExt).parseCode(
m_ci,
- op->context(),
- op->text(),
+ op.context(),
+ op.text(),
langExt,
- op->isExample(),
- op->exampleFile(),
+ op.isExample(),
+ op.exampleFile(),
fd, // fileDef
- op->line(), // startLine
+ op.line(), // startLine
-1, // endLine
FALSE, // inline fragment
0, // memberDef
- op->showLineNo(), // show line numbers
+ op.showLineNo(), // show line numbers
m_ctx // search context
);
if (fd) delete fd;
@@ -882,7 +863,7 @@ void HtmlDocVisitor::visit(DocIncOperator *op)
pushHidden(m_hide);
m_hide=TRUE;
}
- if (op->isLast())
+ if (op.isLast())
{
m_hide = popHidden();
if (!m_hide) m_ci.endCodeFragment("DoxyCode");
@@ -894,10 +875,10 @@ void HtmlDocVisitor::visit(DocIncOperator *op)
}
}
-void HtmlDocVisitor::visit(DocFormula *f)
+void HtmlDocVisitor::operator()(const DocFormula &f)
{
if (m_hide) return;
- bool bDisplay = !f->isInline();
+ bool bDisplay = !f.isInline();
if (bDisplay)
{
forceEndParagraph(f);
@@ -906,7 +887,7 @@ void HtmlDocVisitor::visit(DocFormula *f)
if (Config_getBool(USE_MATHJAX))
{
- QCString text = f->text();
+ QCString text = f.text();
bool closeInline = FALSE;
if (!bDisplay && !text.isEmpty() && text.at(0)=='$' &&
text.at(text.length()-1)=='$')
@@ -931,9 +912,9 @@ void HtmlDocVisitor::visit(DocFormula *f)
m_t << "<img class=\"formula"
<< (bDisplay ? "Dsp" : "Inl");
m_t << "\" alt=\"";
- filterQuotedCdataAttr(f->text());
+ filterQuotedCdataAttr(f.text());
m_t << "\"";
- m_t << " src=\"" << f->relPath() << f->name();
+ m_t << " src=\"" << f.relPath() << f.name();
if (Config_getEnum(HTML_FORMULA_FORMAT)==HTML_FORMULA_FORMAT_t::svg)
{
m_t << ".svg";
@@ -942,7 +923,7 @@ void HtmlDocVisitor::visit(DocFormula *f)
{
m_t << ".png";
}
- FormulaManager::DisplaySize size = FormulaManager::instance().displaySize(f->id());
+ FormulaManager::DisplaySize size = FormulaManager::instance().displaySize(f.id());
if (size.width!=-1)
{
m_t << "\" width=\"" << size.width;
@@ -960,41 +941,41 @@ void HtmlDocVisitor::visit(DocFormula *f)
}
}
-void HtmlDocVisitor::visit(DocIndexEntry *e)
+void HtmlDocVisitor::operator()(const DocIndexEntry &e)
{
- QCString anchor = convertIndexWordToAnchor(e->entry());
- if (e->member())
+ QCString anchor = convertIndexWordToAnchor(e.entry());
+ if (e.member())
{
- anchor.prepend(e->member()->anchor()+"_");
+ anchor.prepend(e.member()->anchor()+"_");
}
m_t << "<a id=\"" << anchor << "\" name=\"" << anchor << "\"></a>";
//printf("*** DocIndexEntry: word='%s' scope='%s' member='%s'\n",
- // qPrint(e->entry()),
- // e->scope() ? qPrint(e->scope()->name()) : "<null>",
- // e->member() ? qPrint(e->member()->name()) : "<null>"
+ // qPrint(e.entry()),
+ // e.scope() ? qPrint(e.scope()->name()) : "<null>",
+ // e.member() ? qPrint(e.member()->name()) : "<null>"
// );
- Doxygen::indexList->addIndexItem(e->scope(),e->member(),anchor,e->entry());
+ Doxygen::indexList->addIndexItem(e.scope(),e.member(),anchor,e.entry());
}
-void HtmlDocVisitor::visit(DocSimpleSectSep *)
+void HtmlDocVisitor::operator()(const DocSimpleSectSep &)
{
m_t << "</dd>\n";
m_t << "<dd>\n";
}
-void HtmlDocVisitor::visit(DocCite *cite)
+void HtmlDocVisitor::operator()(const DocCite &cite)
{
if (m_hide) return;
- if (!cite->file().isEmpty())
+ if (!cite.file().isEmpty())
{
- startLink(cite->ref(),cite->file(),cite->relPath(),cite->anchor());
+ startLink(cite.ref(),cite.file(),cite.relPath(),cite.anchor());
}
else
{
m_t << "<b>[";
}
- filter(cite->text());
- if (!cite->file().isEmpty())
+ filter(cite.text());
+ if (!cite.file().isEmpty())
{
endLink();
}
@@ -1010,12 +991,12 @@ void HtmlDocVisitor::visit(DocCite *cite)
//--------------------------------------
-void HtmlDocVisitor::visitPre(DocAutoList *l)
+void HtmlDocVisitor::operator()(const DocAutoList &l)
{
//printf("DocAutoList::visitPre\n");
if (m_hide) return;
forceEndParagraph(l);
- if (l->isEnumList())
+ if (l.isEnumList())
{
//
// Do list type based on depth:
@@ -1025,20 +1006,15 @@ void HtmlDocVisitor::visitPre(DocAutoList *l)
// A.
// 1. (repeat)...
//
- m_t << "<ol type=\"" << types[l->depth() % NUM_HTML_LIST_TYPES] << "\">";
+ m_t << "<ol type=\"" << types[l.depth() % NUM_HTML_LIST_TYPES] << "\">";
}
else
{
m_t << "<ul>";
}
- if (!l->isPreformatted()) m_t << "\n";
-}
-
-void HtmlDocVisitor::visitPost(DocAutoList *l)
-{
- //printf("DocAutoList::visitPost\n");
- if (m_hide) return;
- if (l->isEnumList())
+ if (!l.isPreformatted()) m_t << "\n";
+ visitChildren(l);
+ if (l.isEnumList())
{
m_t << "</ol>";
}
@@ -1046,269 +1022,249 @@ void HtmlDocVisitor::visitPost(DocAutoList *l)
{
m_t << "</ul>";
}
- if (!l->isPreformatted()) m_t << "\n";
+ if (!l.isPreformatted()) m_t << "\n";
forceStartParagraph(l);
}
-void HtmlDocVisitor::visitPre(DocAutoListItem *)
+void HtmlDocVisitor::operator()(const DocAutoListItem &li)
{
if (m_hide) return;
m_t << "<li>";
+ visitChildren(li);
+ m_t << "</li>";
+ if (!li.isPreformatted()) m_t << "\n";
}
-void HtmlDocVisitor::visitPost(DocAutoListItem *li)
+template<class Node>
+static bool holds_value(const Node *val,const DocNodeVariant &v)
{
- if (m_hide) return;
- m_t << "</li>";
- if (!li->isPreformatted()) m_t << "\n";
+ bool b = std::visit([&](auto &&x) {
+ //printf("holds_value val=%s (%p) v=%s (%p)\n",
+ // docNodeName(*val),(void*)val,docNodeName(v),(void *)&x);
+ return val==static_cast<const DocNode*>(&x);
+ }, v);
+ return b;
}
template<class T>
-bool isFirstChildNode(T *parent, DocNode *node)
+bool isFirstChildNode(const T *parent, const DocPara &node)
{
- return !parent->children().empty() && parent->children().front().get()==node;
+ return !parent->children().empty() && holds_value(&node,parent->children().front());
}
template<class T>
-bool isLastChildNode(T *parent, DocNode *node)
+bool isLastChildNode(const T *parent, const DocPara &node)
{
- return !parent->children().empty() && parent->children().back().get()==node;
+ return !parent->children().empty() && holds_value(&node,parent->children().back());
}
-bool isSeparatedParagraph(DocSimpleSect *parent,DocPara *par)
+bool isSeparatedParagraph(const DocSimpleSect &parent,const DocPara &par)
{
- const DocNodeList &nodes = parent->children();
- auto it = std::find_if(nodes.begin(),nodes.end(),[par](const auto &n) { return n.get()==par; });
- if (it==nodes.end()) return FALSE;
- size_t i = it - nodes.begin();
- size_t count = parent->children().size();
- if (count>1 && i==0) // first node
+ const DocNodeList &nodes = parent.children();
+ auto it = std::find_if(std::begin(nodes),std::end(nodes),[&par](const auto &n) { return holds_value(&par,n); });
+ if (it==std::end(nodes)) return FALSE;
+ size_t count = parent.children().size();
+ auto isSeparator = [](auto &&it_) { return std::get_if<DocSimpleSectSep>(&(*it_))!=0; };
+ if (count>1 && it==std::begin(nodes)) // it points to first node
{
- if (nodes.at(i+1)->kind()==DocNode::Kind_SimpleSectSep)
- {
- return TRUE;
- }
+ return isSeparator(std::next(it));
}
- else if (count>1 && i==count-1) // last node
+ else if (count>1 && it==std::prev(std::end(nodes))) // it points to last node
{
- if (nodes.at(i-1)->kind()==DocNode::Kind_SimpleSectSep)
- {
- return TRUE;
- }
+ return isSeparator(std::prev(it));
}
- else if (count>2 && i>0 && i<count-1) // intermediate node
+ else if (count>2 && it!=std::begin(nodes) && it!=std::prev(std::end(nodes))) // it points to intermediate node
{
- if (nodes.at(i-1)->kind()==DocNode::Kind_SimpleSectSep &&
- nodes.at(i+1)->kind()==DocNode::Kind_SimpleSectSep)
- {
- return TRUE;
- }
+ return isSeparator(std::prev(it)) && isSeparator(std::next(it));
}
- return FALSE;
+ return false;
}
-static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast)
+static int getParagraphContext(const DocPara &p,bool &isFirst,bool &isLast)
{
int t=0;
isFirst=FALSE;
isLast=FALSE;
- if (p && p->parent())
+ if (p.parent())
{
- switch (p->parent()->kind())
+ const auto parBlock = std::get_if<DocParBlock>(p.parent());
+ if (parBlock)
{
- case DocNode::Kind_ParBlock:
- { // hierarchy: node N -> para -> parblock -> para
- // adapt return value to kind of N
- DocNode::Kind kind = DocNode::Kind_Para;
- if ( p->parent()->parent() && p->parent()->parent()->parent() )
- {
- kind = p->parent()->parent()->parent()->kind();
- }
- isFirst=isFirstChildNode((DocParBlock*)p->parent(),p);
- isLast =isLastChildNode ((DocParBlock*)p->parent(),p);
- t=NONE;
- if (isFirst)
- {
- if (kind==DocNode::Kind_HtmlListItem ||
- kind==DocNode::Kind_SecRefItem)
- {
- t=STARTLI;
- }
- else if (kind==DocNode::Kind_HtmlDescData ||
- kind==DocNode::Kind_XRefItem ||
- kind==DocNode::Kind_SimpleSect)
- {
- t=STARTDD;
- }
- else if (kind==DocNode::Kind_HtmlCell ||
- kind==DocNode::Kind_ParamList)
- {
- t=STARTTD;
- }
- }
- if (isLast)
- {
- if (kind==DocNode::Kind_HtmlListItem ||
- kind==DocNode::Kind_SecRefItem)
- {
- t=ENDLI;
- }
- else if (kind==DocNode::Kind_HtmlDescData ||
- kind==DocNode::Kind_XRefItem ||
- kind==DocNode::Kind_SimpleSect)
- {
- t=ENDDD;
- }
- else if (kind==DocNode::Kind_HtmlCell ||
- kind==DocNode::Kind_ParamList)
- {
- t=ENDTD;
- }
- }
- if (!isFirst && !isLast)
- {
- if (kind==DocNode::Kind_HtmlListItem ||
- kind==DocNode::Kind_SecRefItem)
- {
- t=INTERLI;
- }
- else if (kind==DocNode::Kind_HtmlDescData ||
- kind==DocNode::Kind_XRefItem ||
- kind==DocNode::Kind_SimpleSect)
- {
- t=INTERDD;
- }
- else if (kind==DocNode::Kind_HtmlCell ||
- kind==DocNode::Kind_ParamList)
- {
- t=INTERTD;
- }
- }
- break;
- }
- case DocNode::Kind_AutoListItem:
- isFirst=isFirstChildNode((DocAutoListItem*)p->parent(),p);
- isLast =isLastChildNode ((DocAutoListItem*)p->parent(),p);
- t=STARTLI; // not used
- break;
- case DocNode::Kind_SimpleListItem:
- isFirst=TRUE;
- isLast =TRUE;
- t=STARTLI; // not used
- break;
- case DocNode::Kind_ParamList:
- isFirst=TRUE;
- isLast =TRUE;
- t=STARTLI; // not used
- break;
- case DocNode::Kind_HtmlListItem:
- isFirst=isFirstChildNode((DocHtmlListItem*)p->parent(),p);
- isLast =isLastChildNode ((DocHtmlListItem*)p->parent(),p);
- if (isFirst) t=STARTLI;
- if (isLast) t=ENDLI;
- if (!isFirst && !isLast) t = INTERLI;
- break;
- case DocNode::Kind_SecRefItem:
- isFirst=isFirstChildNode((DocSecRefItem*)p->parent(),p);
- isLast =isLastChildNode ((DocSecRefItem*)p->parent(),p);
- if (isFirst) t=STARTLI;
- if (isLast) t=ENDLI;
- if (!isFirst && !isLast) t = INTERLI;
- break;
- case DocNode::Kind_HtmlDescData:
- isFirst=isFirstChildNode((DocHtmlDescData*)p->parent(),p);
- isLast =isLastChildNode ((DocHtmlDescData*)p->parent(),p);
- if (isFirst) t=STARTDD;
- if (isLast) t=ENDDD;
- if (!isFirst && !isLast) t = INTERDD;
- break;
- case DocNode::Kind_XRefItem:
- isFirst=isFirstChildNode((DocXRefItem*)p->parent(),p);
- isLast =isLastChildNode ((DocXRefItem*)p->parent(),p);
- if (isFirst) t=STARTDD;
- if (isLast) t=ENDDD;
- if (!isFirst && !isLast) t = INTERDD;
- break;
- case DocNode::Kind_SimpleSect:
- isFirst=isFirstChildNode((DocSimpleSect*)p->parent(),p);
- isLast =isLastChildNode ((DocSimpleSect*)p->parent(),p);
- if (isFirst) t=STARTDD;
- if (isLast) t=ENDDD;
- if (isSeparatedParagraph((DocSimpleSect*)p->parent(),p))
- // if the paragraph is enclosed with separators it will
- // be included in <dd>..</dd> so avoid addition paragraph
- // markers
- {
- isFirst=isLast=TRUE;
- }
- if (!isFirst && !isLast) t = INTERDD;
- break;
- case DocNode::Kind_HtmlCell:
- isFirst=isFirstChildNode((DocHtmlCell*)p->parent(),p);
- isLast =isLastChildNode ((DocHtmlCell*)p->parent(),p);
- if (isFirst) t=STARTTD;
- if (isLast) t=ENDTD;
- if (!isFirst && !isLast) t = INTERTD;
- break;
- default:
- break;
+ // hierarchy: node N -> para -> parblock -> para
+ // adapt return value to kind of N
+ const DocNodeVariant *p3 = 0;
+ if (::parent(p.parent()) && ::parent(::parent(p.parent())) )
+ {
+ p3 = ::parent(::parent(p.parent()));
+ }
+ isFirst=isFirstChildNode(parBlock,p);
+ isLast =isLastChildNode (parBlock,p);
+ bool isLI = p3!=0 && holds_one_of_alternatives<DocHtmlListItem,DocSecRefItem>(*p3);
+ bool isDD = p3!=0 && holds_one_of_alternatives<DocHtmlDescData,DocXRefItem,DocSimpleSect>(*p3);
+ bool isTD = p3!=0 && holds_one_of_alternatives<DocHtmlCell,DocParamList>(*p3);
+ t=NONE;
+ if (isFirst)
+ {
+ if (isLI) t=STARTLI; else if (isDD) t=STARTDD; else if (isTD) t=STARTTD;
+ }
+ if (isLast)
+ {
+ if (isLI) t=ENDLI; else if (isDD) t=ENDDD; else if (isTD) t=ENDTD;
+ }
+ if (!isFirst && !isLast)
+ {
+ if (isLI) t=INTERLI; else if (isDD) t=INTERDD; else if (isTD) t=INTERTD;
+ }
+ return t;
+ }
+ const auto docAutoListItem = std::get_if<DocAutoListItem>(p.parent());
+ if (docAutoListItem)
+ {
+ isFirst=isFirstChildNode(docAutoListItem,p);
+ isLast =isLastChildNode (docAutoListItem,p);
+ t=STARTLI; // not used
+ return t;
+ }
+ const auto docSimpleListItem = std::get_if<DocSimpleListItem>(p.parent());
+ if (docSimpleListItem)
+ {
+ isFirst=TRUE;
+ isLast =TRUE;
+ t=STARTLI; // not used
+ return t;
+ }
+ const auto docParamList = std::get_if<DocParamList>(p.parent());
+ if (docParamList)
+ {
+ isFirst=TRUE;
+ isLast =TRUE;
+ t=STARTLI; // not used
+ return t;
+ }
+ const auto docHtmlListItem = std::get_if<DocHtmlListItem>(p.parent());
+ if (docHtmlListItem)
+ {
+ isFirst=isFirstChildNode(docHtmlListItem,p);
+ isLast =isLastChildNode (docHtmlListItem,p);
+ if (isFirst) t=STARTLI;
+ if (isLast) t=ENDLI;
+ if (!isFirst && !isLast) t = INTERLI;
+ return t;
+ }
+ const auto docSecRefItem = std::get_if<DocSecRefItem>(p.parent());
+ if (docSecRefItem)
+ {
+ isFirst=isFirstChildNode(docSecRefItem,p);
+ isLast =isLastChildNode (docSecRefItem,p);
+ if (isFirst) t=STARTLI;
+ if (isLast) t=ENDLI;
+ if (!isFirst && !isLast) t = INTERLI;
+ return t;
+ }
+ const auto docHtmlDescData = std::get_if<DocHtmlDescData>(p.parent());
+ if (docHtmlDescData)
+ {
+ isFirst=isFirstChildNode(docHtmlDescData,p);
+ isLast =isLastChildNode (docHtmlDescData,p);
+ if (isFirst) t=STARTDD;
+ if (isLast) t=ENDDD;
+ if (!isFirst && !isLast) t = INTERDD;
+ return t;
+ }
+ const auto docXRefItem = std::get_if<DocXRefItem>(p.parent());
+ if (docXRefItem)
+ {
+ isFirst=isFirstChildNode(docXRefItem,p);
+ isLast =isLastChildNode (docXRefItem,p);
+ if (isFirst) t=STARTDD;
+ if (isLast) t=ENDDD;
+ if (!isFirst && !isLast) t = INTERDD;
+ return t;
+ }
+ const auto docSimpleSect = std::get_if<DocSimpleSect>(p.parent());
+ if (docSimpleSect)
+ {
+ isFirst=isFirstChildNode(docSimpleSect,p);
+ isLast =isLastChildNode (docSimpleSect,p);
+ if (isFirst) t=STARTDD;
+ if (isLast) t=ENDDD;
+ if (isSeparatedParagraph(*docSimpleSect,p))
+ // if the paragraph is enclosed with separators it will
+ // be included in <dd>..</dd> so avoid addition paragraph
+ // markers
+ {
+ isFirst=isLast=TRUE;
+ }
+ if (!isFirst && !isLast) t = INTERDD;
+ return t;
+ }
+ const auto docHtmlCell = std::get_if<DocHtmlCell>(p.parent());
+ if (docHtmlCell)
+ {
+ isFirst=isFirstChildNode(docHtmlCell,p);
+ isLast =isLastChildNode (docHtmlCell,p);
+ if (isFirst) t=STARTTD;
+ if (isLast) t=ENDTD;
+ if (!isFirst && !isLast) t = INTERTD;
+ return t;
}
- //printf("para=%p parent()->kind=%d isFirst=%d isLast=%d t=%d\n",
- // p,p->parent()->kind(),isFirst,isLast,t);
}
return t;
}
-void HtmlDocVisitor::visitPre(DocPara *p)
+static bool determineIfNeedsTag(const DocPara &p)
{
- if (m_hide) return;
-
- //printf("DocPara::visitPre: parent of kind %d ",
- // p->parent() ? p->parent()->kind() : -1);
-
bool needsTag = FALSE;
- if (p && p->parent())
- {
- switch (p->parent()->kind())
+ if (p.parent())
+ {
+ if (holds_one_of_alternatives<DocSection,
+ DocInternal,
+ DocHtmlListItem,
+ DocHtmlDescData,
+ DocHtmlCell,
+ DocSimpleListItem,
+ DocAutoListItem,
+ DocSimpleSect,
+ DocXRefItem,
+ DocHtmlBlockQuote,
+ DocParBlock
+ >(*p.parent()))
{
- case DocNode::Kind_Section:
- case DocNode::Kind_Internal:
- case DocNode::Kind_HtmlListItem:
- case DocNode::Kind_HtmlDescData:
- case DocNode::Kind_HtmlCell:
- case DocNode::Kind_SimpleListItem:
- case DocNode::Kind_AutoListItem:
- case DocNode::Kind_SimpleSect:
- case DocNode::Kind_XRefItem:
- case DocNode::Kind_Copy:
- case DocNode::Kind_HtmlBlockQuote:
- case DocNode::Kind_ParBlock:
- needsTag = TRUE;
- break;
- case DocNode::Kind_Root:
- needsTag = !((DocRoot*)p->parent())->singleLine();
- break;
- default:
- needsTag = FALSE;
+ needsTag = TRUE;
+ }
+ else if (std::get_if<DocRoot>(p.parent()))
+ {
+ needsTag = !std::get<DocRoot>(*p.parent()).singleLine();
}
}
+ return needsTag;
+}
+
+void HtmlDocVisitor::operator()(const DocPara &p)
+{
+ if (m_hide) return;
+
+ //printf("> DocPara\n");
+ //dumpDocNodeList(p.children());
+
+ bool needsTag = determineIfNeedsTag(p);
+ //printf(" needsTag=%d\n",needsTag);
+ bool needsTagBefore = needsTag;
+ bool needsTagAfter = needsTag;
// if the first element of a paragraph is something that should be outside of
// the paragraph (<ul>,<dl>,<table>,..) then that will already started the
// paragraph and we don't need to do it here
- size_t nodeIndex = 0;
- if (p && nodeIndex<p->children().size())
+ if (!p.children().empty())
{
- while (nodeIndex<p->children().size() && isInvisibleNode(p->children().at(nodeIndex).get()))
- {
- nodeIndex++;
- }
- if (nodeIndex<p->children().size())
+ auto it = std::find_if(std::begin(p.children()),std::end(p.children()),
+ [](const auto &node) { return !isInvisibleNode(node); });
+ if (it!=std::end(p.children()))
{
- const DocNode *n = p->children().at(nodeIndex).get();
+ const DocNodeVariant &n = *it;
if (mustBeOutsideParagraph(n))
{
- needsTag = FALSE;
+ needsTagBefore = FALSE;
}
}
}
@@ -1321,98 +1277,72 @@ void HtmlDocVisitor::visitPre(DocPara *p)
bool isLast;
t = getParagraphContext(p,isFirst,isLast);
//printf("startPara first=%d last=%d\n",isFirst,isLast);
- if (isFirst && isLast) needsTag=FALSE;
+ if (isFirst && isLast) needsTagBefore=FALSE;
- //printf(" needsTag=%d\n",needsTag);
+ //printf(" needsTagBefore=%d\n",needsTagBefore);
// write the paragraph tag (if needed)
- if (needsTag)
+ if (needsTagBefore)
{
if (strlen(contexts[t]))
- m_t << "<p class=\"" << contexts[t] << "\"" << htmlAttribsToString(p->attribs()) << ">";
+ m_t << "<p class=\"" << contexts[t] << "\"" << htmlAttribsToString(p.attribs()) << ">";
else
- m_t << "<p " << htmlAttribsToString(p->attribs()) << ">";
+ m_t << "<p " << htmlAttribsToString(p.attribs()) << ">";
}
-}
-void HtmlDocVisitor::visitPost(DocPara *p)
-{
-
- //printf("DocPara::visitPost: parent of kind %d ",
- // p->parent() ? p->parent()->kind() : -1);
-
- bool needsTag = FALSE;
- if (p->parent())
- {
- switch (p->parent()->kind())
- {
- case DocNode::Kind_Section:
- case DocNode::Kind_Internal:
- case DocNode::Kind_HtmlListItem:
- case DocNode::Kind_HtmlDescData:
- case DocNode::Kind_HtmlCell:
- case DocNode::Kind_SimpleListItem:
- case DocNode::Kind_AutoListItem:
- case DocNode::Kind_SimpleSect:
- case DocNode::Kind_XRefItem:
- case DocNode::Kind_Copy:
- case DocNode::Kind_HtmlBlockQuote:
- case DocNode::Kind_ParBlock:
- needsTag = TRUE;
- break;
- case DocNode::Kind_Root:
- needsTag = !((DocRoot*)p->parent())->singleLine();
- break;
- default:
- needsTag = FALSE;
- }
- }
+ visitChildren(p);
// if the last element of a paragraph is something that should be outside of
// the paragraph (<ul>,<dl>,<table>) then that will already have ended the
// paragraph and we don't need to do it here
- if (!p->children().empty())
+ if (!p.children().empty())
{
- int nodeIndex = static_cast<int>(p->children().size()-1);
- while (nodeIndex>=0 && isInvisibleNode(p->children().at(nodeIndex).get()))
+ auto it = std::prev(std::end(p.children()));
+ for (;;)
{
- nodeIndex--;
- }
- if (nodeIndex>=0)
- {
- const DocNode *n = p->children().at(nodeIndex).get();
- if (mustBeOutsideParagraph(n))
+ const DocNodeVariant &n = *it;
+ if (!isInvisibleNode(n))
+ {
+ if (mustBeOutsideParagraph(n))
+ {
+ needsTagAfter = FALSE;
+ }
+ // stop searching if we found a node that is visible
+ break;
+ }
+ if (it==std::begin(p.children()))
+ {
+ // stop searching if we are at the beginning of the list
+ break;
+ }
+ else
{
- needsTag = FALSE;
+ --it;
}
}
}
- bool isFirst;
- bool isLast;
- getParagraphContext(p,isFirst,isLast);
//printf("endPara first=%d last=%d\n",isFirst,isLast);
- if (isFirst && isLast) needsTag=FALSE;
-
- //printf("DocPara::visitPost needsTag=%d\n",needsTag);
-
- if (needsTag) m_t << "</p>\n";
+ if (isFirst && isLast) needsTagAfter=FALSE;
+ //printf(" needsTagAfter=%d\n",needsTagAfter);
+ if (needsTagAfter) m_t << "</p>\n";
+ //printf("< DocPara\n");
}
-void HtmlDocVisitor::visitPre(DocRoot *)
+void HtmlDocVisitor::operator()(const DocRoot &r)
{
+ //printf("> DocRoot\n");
+ //dumpDocNodeList(r.children());
+ visitChildren(r);
+ //printf("< DocRoot\n");
}
-void HtmlDocVisitor::visitPost(DocRoot *)
-{
-}
-
-void HtmlDocVisitor::visitPre(DocSimpleSect *s)
+void HtmlDocVisitor::operator()(const DocSimpleSect &s)
{
if (m_hide) return;
forceEndParagraph(s);
- m_t << "<dl class=\"section " << s->typeString() << "\"><dt>";
- switch(s->type())
+ m_t << "<dl class=\"section " << s.typeString() << "\"><dt>";
+ switch(s.type())
{
case DocSimpleSect::See:
m_t << theTranslator->trSeeAlso(); break;
@@ -1449,95 +1379,74 @@ void HtmlDocVisitor::visitPre(DocSimpleSect *s)
case DocSimpleSect::Unknown: break;
}
- // special case 1: user defined title
- if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
+ if (s.title())
{
- m_t << "</dt><dd>";
+ std::visit(*this,*s.title());
}
-}
-
-void HtmlDocVisitor::visitPost(DocSimpleSect *s)
-{
- if (m_hide) return;
+ m_t << "</dt><dd>";
+ visitChildren(s);
m_t << "</dd></dl>\n";
forceStartParagraph(s);
}
-void HtmlDocVisitor::visitPre(DocTitle *)
-{
-}
-
-void HtmlDocVisitor::visitPost(DocTitle *)
+void HtmlDocVisitor::operator()(const DocTitle &t)
{
if (m_hide) return;
- m_t << "</dt><dd>";
+ visitChildren(t);
}
-void HtmlDocVisitor::visitPre(DocSimpleList *sl)
+void HtmlDocVisitor::operator()(const DocSimpleList &sl)
{
if (m_hide) return;
forceEndParagraph(sl);
m_t << "<ul>";
- if (!sl->isPreformatted()) m_t << "\n";
-
-}
-
-void HtmlDocVisitor::visitPost(DocSimpleList *sl)
-{
- if (m_hide) return;
+ if (!sl.isPreformatted()) m_t << "\n";
+ visitChildren(sl);
m_t << "</ul>";
- if (!sl->isPreformatted()) m_t << "\n";
+ if (!sl.isPreformatted()) m_t << "\n";
forceStartParagraph(sl);
}
-void HtmlDocVisitor::visitPre(DocSimpleListItem *)
+void HtmlDocVisitor::operator()(const DocSimpleListItem &li)
{
if (m_hide) return;
m_t << "<li>";
-}
-
-void HtmlDocVisitor::visitPost(DocSimpleListItem *li)
-{
- if (m_hide) return;
+ if (li.paragraph())
+ {
+ visit(*this,*li.paragraph());
+ }
m_t << "</li>";
- if (!li->isPreformatted()) m_t << "\n";
+ if (!li.isPreformatted()) m_t << "\n";
}
-void HtmlDocVisitor::visitPre(DocSection *s)
+void HtmlDocVisitor::operator()(const DocSection &s)
{
if (m_hide) return;
forceEndParagraph(s);
- m_t << "<h" << s->level() << ">";
- m_t << "<a class=\"anchor\" id=\"" << s->anchor();
+ m_t << "<h" << s.level() << ">";
+ m_t << "<a class=\"anchor\" id=\"" << s.anchor();
m_t << "\"></a>\n";
- filter(convertCharEntitiesToUTF8(s->title()));
- m_t << "</h" << s->level() << ">\n";
-}
-
-void HtmlDocVisitor::visitPost(DocSection *s)
-{
+ filter(convertCharEntitiesToUTF8(s.title()));
+ m_t << "</h" << s.level() << ">\n";
+ visitChildren(s);
forceStartParagraph(s);
}
-void HtmlDocVisitor::visitPre(DocHtmlList *s)
+void HtmlDocVisitor::operator()(const DocHtmlList &s)
{
if (m_hide) return;
forceEndParagraph(s);
- if (s->type()==DocHtmlList::Ordered)
+ if (s.type()==DocHtmlList::Ordered)
{
- m_t << "<ol" << htmlAttribsToString(s->attribs());
+ m_t << "<ol" << htmlAttribsToString(s.attribs());
}
else
{
- m_t << "<ul" << htmlAttribsToString(s->attribs());
+ m_t << "<ul" << htmlAttribsToString(s.attribs());
}
m_t << ">\n";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlList *s)
-{
- if (m_hide) return;
- if (s->type()==DocHtmlList::Ordered)
+ visitChildren(s);
+ if (s.type()==DocHtmlList::Ordered)
{
m_t << "</ol>";
}
@@ -1545,199 +1454,156 @@ void HtmlDocVisitor::visitPost(DocHtmlList *s)
{
m_t << "</ul>";
}
- if (!s->isPreformatted()) m_t << "\n";
+ if (!s.isPreformatted()) m_t << "\n";
forceStartParagraph(s);
}
-void HtmlDocVisitor::visitPre(DocHtmlListItem *i)
-{
- if (m_hide) return;
- m_t << "<li" << htmlAttribsToString(i->attribs()) << ">";
- if (!i->isPreformatted()) m_t << "\n";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlListItem *)
+void HtmlDocVisitor::operator()(const DocHtmlListItem &i)
{
if (m_hide) return;
+ m_t << "<li" << htmlAttribsToString(i.attribs()) << ">";
+ if (!i.isPreformatted()) m_t << "\n";
+ visitChildren(i);
m_t << "</li>\n";
}
-void HtmlDocVisitor::visitPre(DocHtmlDescList *dl)
+void HtmlDocVisitor::operator()(const DocHtmlDescList &dl)
{
if (m_hide) return;
forceEndParagraph(dl);
- m_t << "<dl" << htmlAttribsToString(dl->attribs()) << ">\n";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlDescList *dl)
-{
- if (m_hide) return;
+ m_t << "<dl" << htmlAttribsToString(dl.attribs()) << ">\n";
+ visitChildren(dl);
m_t << "</dl>\n";
forceStartParagraph(dl);
}
-void HtmlDocVisitor::visitPre(DocHtmlDescTitle *dt)
-{
- if (m_hide) return;
- m_t << "<dt" << htmlAttribsToString(dt->attribs()) << ">";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlDescTitle *)
+void HtmlDocVisitor::operator()(const DocHtmlDescTitle &dt)
{
if (m_hide) return;
+ m_t << "<dt" << htmlAttribsToString(dt.attribs()) << ">";
+ visitChildren(dt);
m_t << "</dt>\n";
}
-void HtmlDocVisitor::visitPre(DocHtmlDescData *dd)
-{
- if (m_hide) return;
- m_t << "<dd" << htmlAttribsToString(dd->attribs()) << ">";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlDescData *)
+void HtmlDocVisitor::operator()(const DocHtmlDescData &dd)
{
if (m_hide) return;
+ m_t << "<dd" << htmlAttribsToString(dd.attribs()) << ">";
+ visitChildren(dd);
m_t << "</dd>\n";
}
-void HtmlDocVisitor::visitPre(DocHtmlTable *t)
+void HtmlDocVisitor::operator()(const DocHtmlTable &t)
{
if (m_hide) return;
forceEndParagraph(t);
- if (t->hasCaption())
+ if (t.caption())
{
- QCString anc = t->caption()->anchor();
+ QCString anc = std::get<DocHtmlCaption>(*t.caption()).anchor();
if (!anc.isEmpty())
{
m_t << "<a class=\"anchor\" id=\"" << anc << "\"></a>\n";
}
}
- QCString attrs = htmlAttribsToString(t->attribs());
+ QCString attrs = htmlAttribsToString(t.attribs());
if (attrs.isEmpty())
{
m_t << "<table class=\"doxtable\">\n";
}
else
{
- m_t << "<table" << htmlAttribsToString(t->attribs()) << ">\n";
+ m_t << "<table" << htmlAttribsToString(t.attribs()) << ">\n";
}
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlTable *t)
-{
- if (m_hide) return;
+ if (t.caption())
+ {
+ std::visit(*this,*t.caption());
+ }
+ visitChildren(t);
m_t << "</table>\n";
forceStartParagraph(t);
}
-void HtmlDocVisitor::visitPre(DocHtmlRow *tr)
-{
- if (m_hide) return;
- m_t << "<tr" << htmlAttribsToString(tr->attribs()) << ">\n";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlRow *)
+void HtmlDocVisitor::operator()(const DocHtmlRow &tr)
{
if (m_hide) return;
+ m_t << "<tr" << htmlAttribsToString(tr.attribs()) << ">\n";
+ visitChildren(tr);
m_t << "</tr>\n";
}
-void HtmlDocVisitor::visitPre(DocHtmlCell *c)
+void HtmlDocVisitor::operator()(const DocHtmlCell &c)
{
if (m_hide) return;
- if (c->isHeading())
+ if (c.isHeading())
{
- m_t << "<th" << htmlAttribsToString(c->attribs()) << ">";
+ m_t << "<th" << htmlAttribsToString(c.attribs()) << ">";
}
else
{
- m_t << "<td" << htmlAttribsToString(c->attribs()) << ">";
+ m_t << "<td" << htmlAttribsToString(c.attribs()) << ">";
}
+ visitChildren(c);
+ if (c.isHeading()) m_t << "</th>"; else m_t << "</td>";
}
-void HtmlDocVisitor::visitPost(DocHtmlCell *c)
-{
- if (m_hide) return;
- if (c->isHeading()) m_t << "</th>"; else m_t << "</td>";
-}
-
-void HtmlDocVisitor::visitPre(DocHtmlCaption *c)
-{
- if (m_hide) return;
- m_t << "<caption" << htmlAttribsToString(c->attribs()) << ">";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlCaption *)
+void HtmlDocVisitor::operator()(const DocHtmlCaption &c)
{
if (m_hide) return;
+ m_t << "<caption" << htmlAttribsToString(c.attribs()) << ">";
+ visitChildren(c);
m_t << "</caption>\n";
}
-void HtmlDocVisitor::visitPre(DocInternal *)
+void HtmlDocVisitor::operator()(const DocInternal &i)
{
if (m_hide) return;
- //forceEndParagraph(i);
- //m_t << "<p><b>" << theTranslator->trForInternalUseOnly() << "</b></p>\n";
+ visitChildren(i);
}
-void HtmlDocVisitor::visitPost(DocInternal *)
+void HtmlDocVisitor::operator()(const DocHRef &href)
{
if (m_hide) return;
- //forceStartParagraph(i);
-}
-
-void HtmlDocVisitor::visitPre(DocHRef *href)
-{
- if (m_hide) return;
- if (href->url().left(7)=="mailto:")
+ if (href.url().left(7)=="mailto:")
{
- writeObfuscatedMailAddress(href->url().mid(7));
+ writeObfuscatedMailAddress(href.url().mid(7));
}
else
{
- QCString url = correctURL(href->url(),href->relPath());
+ QCString url = correctURL(href.url(),href.relPath());
m_t << "<a href=\"" << convertToHtml(url) << "\""
- << htmlAttribsToString(href->attribs()) << ">";
+ << htmlAttribsToString(href.attribs()) << ">";
}
-}
-
-void HtmlDocVisitor::visitPost(DocHRef *)
-{
- if (m_hide) return;
+ visitChildren(href);
m_t << "</a>";
}
-void HtmlDocVisitor::visitPre(DocHtmlHeader *header)
+void HtmlDocVisitor::operator()(const DocHtmlHeader &header)
{
if (m_hide) return;
forceEndParagraph(header);
- m_t << "<h" << header->level() << htmlAttribsToString(header->attribs()) << ">";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlHeader *header)
-{
- if (m_hide) return;
- m_t << "</h" << header->level() << ">\n";
+ m_t << "<h" << header.level() << htmlAttribsToString(header.attribs()) << ">";
+ visitChildren(header);
+ m_t << "</h" << header.level() << ">\n";
forceStartParagraph(header);
}
-void HtmlDocVisitor::visitPre(DocImage *img)
+void HtmlDocVisitor::operator()(const DocImage &img)
{
- if (img->type()==DocImage::Html)
+ if (img.type()==DocImage::Html)
{
- bool inlineImage = img->isInlineImage();
- bool typeSVG = img->isSVG();
- QCString url = img->url();
+ bool inlineImage = img.isInlineImage();
+ bool typeSVG = img.isSVG();
+ QCString url = img.url();
if (!inlineImage)
{
forceEndParagraph(img);
}
if (m_hide) return;
- QCString baseName=img->name();
+ QCString baseName=img.name();
int i;
if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
{
@@ -1745,15 +1611,15 @@ void HtmlDocVisitor::visitPre(DocImage *img)
}
if (!inlineImage) m_t << "<div class=\"image\">\n";
QCString sizeAttribs;
- if (!img->width().isEmpty())
+ if (!img.width().isEmpty())
{
- sizeAttribs+=" width=\""+img->width()+"\"";
+ sizeAttribs+=" width=\""+img.width()+"\"";
}
- if (!img->height().isEmpty()) // link to local file
+ if (!img.height().isEmpty()) // link to local file
{
- sizeAttribs+=" height=\""+img->height()+"\"";
+ sizeAttribs+=" height=\""+img.height()+"\"";
}
- // 16 cases: url.isEmpty() | typeSVG | inlineImage | img->hasCaption()
+ // 16 cases: url.isEmpty() | typeSVG | inlineImage | img.hasCaption()
HtmlAttribList extraAttribs;
if (typeSVG)
@@ -1764,16 +1630,16 @@ void HtmlDocVisitor::visitPre(DocImage *img)
extraAttribs.push_back(opt);
}
QCString alt;
- mergeHtmlAttributes(img->attribs(),extraAttribs);
+ mergeHtmlAttributes(img.attribs(),extraAttribs);
QCString attrs = htmlAttribsToString(extraAttribs,&alt);
QCString src;
if (url.isEmpty())
{
- src = img->relPath()+img->name();
+ src = img.relPath()+img.name();
}
else
{
- src = correctURL(url,img->relPath());
+ src = correctURL(url,img.relPath());
}
if (typeSVG && !inlineImage)
{
@@ -1800,7 +1666,7 @@ void HtmlDocVisitor::visitPre(DocImage *img)
m_t << "/>\n";
}
}
- if (img->hasCaption())
+ if (img.hasCaption())
{
if (inlineImage)
{
@@ -1816,21 +1682,10 @@ void HtmlDocVisitor::visitPre(DocImage *img)
{
m_t << "/>";
}
- }
- else // other format -> skip
- {
- pushHidden(m_hide);
- m_hide=TRUE;
- }
-}
-void HtmlDocVisitor::visitPost(DocImage *img)
-{
- if (img->type()==DocImage::Html)
- {
- if (m_hide) return;
- bool inlineImage = img->isInlineImage();
- if (img->hasCaption())
+ visitChildren(img);
+
+ if (img.hasCaption())
{
if (inlineImage)
{
@@ -1848,150 +1703,123 @@ void HtmlDocVisitor::visitPost(DocImage *img)
forceStartParagraph(img);
}
}
- else // other format
+ else // other format -> skip
{
- m_hide = popHidden();
}
}
-void HtmlDocVisitor::visitPre(DocDotFile *df)
+void HtmlDocVisitor::operator()(const DocDotFile &df)
{
if (m_hide) return;
- if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file()));
+ if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
m_t << "<div class=\"dotgraph\">\n";
- writeDotFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine());
- if (df->hasCaption())
+ writeDotFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
+ if (df.hasCaption())
{
m_t << "<div class=\"caption\">\n";
}
-}
-
-void HtmlDocVisitor::visitPost(DocDotFile *df)
-{
- if (m_hide) return;
- if (df->hasCaption())
+ visitChildren(df);
+ if (df.hasCaption())
{
m_t << "</div>\n";
}
m_t << "</div>\n";
}
-void HtmlDocVisitor::visitPre(DocMscFile *df)
+void HtmlDocVisitor::operator()(const DocMscFile &df)
{
if (m_hide) return;
- if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file()));
+ if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
m_t << "<div class=\"mscgraph\">\n";
- writeMscFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine());
- if (df->hasCaption())
+ writeMscFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
+ if (df.hasCaption())
{
m_t << "<div class=\"caption\">\n";
}
-}
-void HtmlDocVisitor::visitPost(DocMscFile *df)
-{
- if (m_hide) return;
- if (df->hasCaption())
+ visitChildren(df);
+ if (df.hasCaption())
{
m_t << "</div>\n";
}
m_t << "</div>\n";
}
-void HtmlDocVisitor::visitPre(DocDiaFile *df)
+void HtmlDocVisitor::operator()(const DocDiaFile &df)
{
if (m_hide) return;
- if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df->file()));
+ if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(HTML_OUTPUT)+"/"+stripPath(df.file()));
m_t << "<div class=\"diagraph\">\n";
- writeDiaFile(df->file(),df->relPath(),df->context(),df->srcFile(),df->srcLine());
- if (df->hasCaption())
+ writeDiaFile(df.file(),df.relPath(),df.context(),df.srcFile(),df.srcLine());
+ if (df.hasCaption())
{
m_t << "<div class=\"caption\">\n";
}
-}
-void HtmlDocVisitor::visitPost(DocDiaFile *df)
-{
- if (m_hide) return;
- if (df->hasCaption())
+ visitChildren(df);
+ if (df.hasCaption())
{
m_t << "</div>\n";
}
m_t << "</div>\n";
}
-void HtmlDocVisitor::visitPre(DocLink *lnk)
-{
- if (m_hide) return;
- startLink(lnk->ref(),lnk->file(),lnk->relPath(),lnk->anchor());
-}
-
-void HtmlDocVisitor::visitPost(DocLink *)
+void HtmlDocVisitor::operator()(const DocLink &lnk)
{
if (m_hide) return;
+ startLink(lnk.ref(),lnk.file(),lnk.relPath(),lnk.anchor());
+ visitChildren(lnk);
endLink();
}
-void HtmlDocVisitor::visitPre(DocRef *ref)
+void HtmlDocVisitor::operator()(const DocRef &ref)
{
if (m_hide) return;
- if (!ref->file().isEmpty())
+ if (!ref.file().isEmpty())
{
- // when ref->isSubPage()==TRUE we use ref->file() for HTML and
- // ref->anchor() for LaTeX/RTF
- startLink(ref->ref(),ref->file(),ref->relPath(),ref->isSubPage() ? QCString() : ref->anchor());
+ // when ref.isSubPage()==TRUE we use ref.file() for HTML and
+ // ref.anchor() for LaTeX/RTF
+ startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
}
- if (!ref->hasLinkText()) filter(ref->targetTitle());
-}
-
-void HtmlDocVisitor::visitPost(DocRef *ref)
-{
- if (m_hide) return;
- if (!ref->file().isEmpty()) endLink();
+ if (!ref.hasLinkText()) filter(ref.targetTitle());
+ visitChildren(ref);
+ if (!ref.file().isEmpty()) endLink();
//m_t << " ";
}
-void HtmlDocVisitor::visitPre(DocSecRefItem *ref)
+void HtmlDocVisitor::operator()(const DocSecRefItem &ref)
{
if (m_hide) return;
- if (!ref->file().isEmpty())
+ if (!ref.file().isEmpty())
{
m_t << "<li>";
- startLink(ref->ref(),ref->file(),ref->relPath(),ref->isSubPage() ? QCString() : ref->anchor());
+ startLink(ref.ref(),ref.file(),ref.relPath(),ref.isSubPage() ? QCString() : ref.anchor());
}
-}
-
-void HtmlDocVisitor::visitPost(DocSecRefItem *ref)
-{
- if (m_hide) return;
- if (!ref->file().isEmpty())
+ visitChildren(ref);
+ if (!ref.file().isEmpty())
{
endLink();
m_t << "</li>\n";
}
}
-void HtmlDocVisitor::visitPre(DocSecRefList *s)
+void HtmlDocVisitor::operator()(const DocSecRefList &s)
{
if (m_hide) return;
forceEndParagraph(s);
m_t << "<div>\n";
m_t << "<ul class=\"multicol\">\n";
-}
-
-void HtmlDocVisitor::visitPost(DocSecRefList *s)
-{
- if (m_hide) return;
+ visitChildren(s);
m_t << "</ul>\n";
m_t << "</div>\n";
forceStartParagraph(s);
}
-void HtmlDocVisitor::visitPre(DocParamSect *s)
+void HtmlDocVisitor::operator()(const DocParamSect &s)
{
if (m_hide) return;
forceEndParagraph(s);
QCString className;
QCString heading;
- switch(s->type())
+ switch(s.type())
{
case DocParamSect::Param:
heading=theTranslator->trParameters();
@@ -2016,42 +1844,40 @@ void HtmlDocVisitor::visitPre(DocParamSect *s)
m_t << heading;
m_t << "</dt><dd>\n";
m_t << " <table class=\"" << className << "\">\n";
-}
-
-void HtmlDocVisitor::visitPost(DocParamSect *s)
-{
- if (m_hide) return;
+ visitChildren(s);
m_t << " </table>\n";
m_t << " </dd>\n";
m_t << "</dl>\n";
forceStartParagraph(s);
}
-void HtmlDocVisitor::visitPre(DocParamList *pl)
+void HtmlDocVisitor::operator()(const DocSeparator &s)
+{
+ if (m_hide) return;
+ m_t << "&#160;" << s.chars() << "&#160;";
+}
+
+void HtmlDocVisitor::operator()(const DocParamList &pl)
{
//printf("DocParamList::visitPre\n");
if (m_hide) return;
m_t << " <tr>";
- DocParamSect *sect = 0;
- if (pl->parent()->kind()==DocNode::Kind_ParamSect)
- {
- sect=(DocParamSect*)pl->parent();
- }
+ const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
if (sect && sect->hasInOutSpecifier())
{
m_t << "<td class=\"paramdir\">";
- if (pl->direction()!=DocParamSect::Unspecified)
+ if (pl.direction()!=DocParamSect::Unspecified)
{
m_t << "[";
- if (pl->direction()==DocParamSect::In)
+ if (pl.direction()==DocParamSect::In)
{
m_t << "in";
}
- else if (pl->direction()==DocParamSect::Out)
+ else if (pl.direction()==DocParamSect::Out)
{
m_t << "out";
}
- else if (pl->direction()==DocParamSect::InOut)
+ else if (pl.direction()==DocParamSect::InOut)
{
m_t << "in,out";
}
@@ -2062,115 +1888,80 @@ void HtmlDocVisitor::visitPre(DocParamList *pl)
if (sect && sect->hasTypeSpecifier())
{
m_t << "<td class=\"paramtype\">";
- for (const auto &type : pl->paramTypes())
+ for (const auto &type : pl.paramTypes())
{
- if (type->kind()==DocNode::Kind_Word)
- {
- visit((DocWord*)type.get());
- }
- else if (type->kind()==DocNode::Kind_LinkedWord)
- {
- visit((DocLinkedWord*)type.get());
- }
- else if (type->kind()==DocNode::Kind_Sep)
- {
- m_t << "&#160;" << ((DocSeparator *)type.get())->chars() << "&#160;";
- }
+ std::visit(*this,type);
}
m_t << "</td>";
}
m_t << "<td class=\"paramname\">";
bool first=TRUE;
- for (const auto &param : pl->parameters())
+ for (const auto &param : pl.parameters())
{
if (!first) m_t << ","; else first=FALSE;
- if (param->kind()==DocNode::Kind_Word)
- {
- visit((DocWord*)param.get());
- }
- else if (param->kind()==DocNode::Kind_LinkedWord)
- {
- visit((DocLinkedWord*)param.get());
- }
+ std::visit(*this,param);
}
m_t << "</td><td>";
-}
-
-void HtmlDocVisitor::visitPost(DocParamList *)
-{
- //printf("DocParamList::visitPost\n");
- if (m_hide) return;
+ for (const auto &par : pl.paragraphs())
+ {
+ std::visit(*this,par);
+ }
m_t << "</td></tr>\n";
}
-void HtmlDocVisitor::visitPre(DocXRefItem *x)
+void HtmlDocVisitor::operator()(const DocXRefItem &x)
{
if (m_hide) return;
- if (x->title().isEmpty()) return;
+ if (x.title().isEmpty()) return;
forceEndParagraph(x);
- bool anonymousEnum = x->file()=="@";
+ bool anonymousEnum = x.file()=="@";
if (!anonymousEnum)
{
- m_t << "<dl class=\"" << x->key() << "\"><dt><b><a class=\"el\" href=\""
- << x->relPath() << addHtmlExtensionIfMissing(x->file())
- << "#" << x->anchor() << "\">";
+ m_t << "<dl class=\"" << x.key() << "\"><dt><b><a class=\"el\" href=\""
+ << x.relPath() << addHtmlExtensionIfMissing(x.file())
+ << "#" << x.anchor() << "\">";
}
else
{
- m_t << "<dl class=\"" << x->key() << "\"><dt><b>";
+ m_t << "<dl class=\"" << x.key() << "\"><dt><b>";
}
- filter(x->title());
+ filter(x.title());
m_t << ":";
if (!anonymousEnum) m_t << "</a>";
m_t << "</b></dt><dd>";
-}
-
-void HtmlDocVisitor::visitPost(DocXRefItem *x)
-{
- if (m_hide) return;
- if (x->title().isEmpty()) return;
+ visitChildren(x);
+ if (x.title().isEmpty()) return;
m_t << "</dd></dl>\n";
forceStartParagraph(x);
}
-void HtmlDocVisitor::visitPre(DocInternalRef *ref)
-{
- if (m_hide) return;
- startLink(QCString(),ref->file(),ref->relPath(),ref->anchor());
-}
-
-void HtmlDocVisitor::visitPost(DocInternalRef *)
+void HtmlDocVisitor::operator()(const DocInternalRef &ref)
{
if (m_hide) return;
+ startLink(QCString(),ref.file(),ref.relPath(),ref.anchor());
+ visitChildren(ref);
endLink();
m_t << " ";
}
-void HtmlDocVisitor::visitPre(DocText *)
+void HtmlDocVisitor::operator()(const DocText &t)
{
+ visitChildren(t);
}
-void HtmlDocVisitor::visitPost(DocText *)
-{
-}
-
-void HtmlDocVisitor::visitPre(DocHtmlBlockQuote *b)
+void HtmlDocVisitor::operator()(const DocHtmlBlockQuote &b)
{
if (m_hide) return;
forceEndParagraph(b);
- QCString attrs = htmlAttribsToString(b->attribs());
- m_t << "<blockquote class=\"doxtable\"" << htmlAttribsToString(b->attribs()) << ">\n";
-}
-
-void HtmlDocVisitor::visitPost(DocHtmlBlockQuote *b)
-{
- if (m_hide) return;
+ QCString attrs = htmlAttribsToString(b.attribs());
+ m_t << "<blockquote class=\"doxtable\"" << htmlAttribsToString(b.attribs()) << ">\n";
+ visitChildren(b);
m_t << "</blockquote>\n";
forceStartParagraph(b);
}
-void HtmlDocVisitor::visitPre(DocVhdlFlow *vf)
+void HtmlDocVisitor::operator()(const DocVhdlFlow &vf)
{
if (m_hide) return;
if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
@@ -2184,16 +1975,12 @@ void HtmlDocVisitor::visitPre(DocVhdlFlow *vf)
m_t << ".svg\">";
m_t << VhdlDocGen::getFlowMember()->name();
m_t << "</a>";
- if (vf->hasCaption())
+ if (vf.hasCaption())
{
m_t << "<br />";
}
}
-}
-
-void HtmlDocVisitor::visitPost(DocVhdlFlow *vf)
-{
- if (m_hide) return;
+ visitChildren(vf);
if (VhdlDocGen::getFlowMember()) // use VHDL flow chart creator
{
m_t << "</p>";
@@ -2201,18 +1988,12 @@ void HtmlDocVisitor::visitPost(DocVhdlFlow *vf)
}
}
-void HtmlDocVisitor::visitPre(DocParBlock *)
-{
- if (m_hide) return;
-}
-
-void HtmlDocVisitor::visitPost(DocParBlock *)
+void HtmlDocVisitor::operator()(const DocParBlock &pb)
{
if (m_hide) return;
+ visitChildren(pb);
}
-
-
void HtmlDocVisitor::filter(const QCString &str, const bool retainNewline)
{
if (str.isEmpty()) return;
@@ -2393,7 +2174,7 @@ void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString
{
baseName=baseName.left(i);
}
- static QCString outDir = Config_getString(HTML_OUTPUT);
+ QCString outDir = Config_getString(HTML_OUTPUT);
QCString imgExt = getDotImageExtension();
if (imgExt=="svg")
{
@@ -2415,33 +2196,41 @@ void HtmlDocVisitor::writePlantUMLFile(const QCString &fileName, const QCString
must be located outside of a paragraph, i.e. it is a center, div, or pre tag.
See also bug746162.
*/
-static bool insideStyleChangeThatIsOutsideParagraph(DocPara *para,int nodeIndex)
+static bool insideStyleChangeThatIsOutsideParagraph(const DocPara *para,
+ DocNodeList::const_iterator it)
{
//printf("insideStyleChangeThatIsOutputParagraph(index=%d)\n",nodeIndex);
int styleMask=0;
bool styleOutsideParagraph=FALSE;
- while (nodeIndex>=0 && !styleOutsideParagraph)
+ while (!styleOutsideParagraph)
{
- DocNode *n = para->children().at(nodeIndex).get();
- if (n->kind()==DocNode::Kind_StyleChange)
+ const DocNodeVariant *n = &(*it);
+ const DocStyleChange *sc = std::get_if<DocStyleChange>(n);
+ if (sc)
{
- DocStyleChange *sc = (DocStyleChange*)n;
if (!sc->enable()) // remember styles that has been closed already
{
- styleMask|=(int)sc->style();
+ styleMask|=static_cast<int>(sc->style());
}
bool paraStyle = sc->style()==DocStyleChange::Center ||
sc->style()==DocStyleChange::Div ||
sc->style()==DocStyleChange::Preformatted;
//printf("Found style change %s enabled=%d\n",sc->styleString(),sc->enable());
- if (sc->enable() && (styleMask&(int)sc->style())==0 && // style change that is still active
+ if (sc->enable() && (styleMask&static_cast<int>(sc->style()))==0 && // style change that is still active
paraStyle
)
{
styleOutsideParagraph=TRUE;
}
}
- nodeIndex--;
+ if (it!=std::begin(para->children()))
+ {
+ --it;
+ }
+ else
+ {
+ break;
+ }
}
return styleOutsideParagraph;
}
@@ -2450,34 +2239,53 @@ static bool insideStyleChangeThatIsOutsideParagraph(DocPara *para,int nodeIndex)
* have to be outside of the paragraph. This method will forcefully end
* the current paragraph and forceStartParagraph() will restart it.
*/
-void HtmlDocVisitor::forceEndParagraph(DocNode *n)
+template<class Node>
+void HtmlDocVisitor::forceEndParagraph(const Node &n)
{
- //printf("forceEndParagraph(%p) %d\n",n,n->kind());
- if (n->parent() && n->parent()->kind()==DocNode::Kind_Para)
+ const DocPara *para=std::get_if<DocPara>(n.parent());
+ if (para)
{
- DocPara *para = (DocPara*)n->parent();
const DocNodeList &children = para->children();
- auto it = std::find_if(children.begin(),children.end(),[n](const auto &np) { return np.get()==n; });
- if (it==children.end()) return;
- int nodeIndex = static_cast<int>(it - children.begin());
- nodeIndex--;
- if (nodeIndex<0) return; // first node in paragraph
- while (nodeIndex>=0 && isInvisibleNode(children.at(nodeIndex).get()))
+
+ //printf("forceEndParagraph\n");
+ //dumpDocNodeList(children);
+
+ auto it = std::find_if(std::begin(children),std::end(children),
+ [&n](const auto &np) { return holds_value(&n,np); });
+ if (it==std::end(children)) return;
+ if (it==std::begin(children)) return; // first node in paragraph
+ it = std::prev(it);
+ bool found=false;
+ while (!found)
+ {
+ found = !isInvisibleNode(*it);
+ if (found) break;
+ if (it!=std::begin(children))
+ {
+ --it;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (!found) return; // first visible node in paragraph
+ const DocNodeVariant &v = *it;
+ if (mustBeOutsideParagraph(v)) return; // previous node already outside paragraph context
+ bool styleOutsideParagraph=false;
+ if (it!=std::begin(children))
{
- nodeIndex--;
+ it = std::prev(it);
+ styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
}
- if (nodeIndex<0) return; // first visible node in paragraph
- n = children.at(nodeIndex).get();
- if (mustBeOutsideParagraph(n)) return; // previous node already outside paragraph context
- nodeIndex--;
- bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,nodeIndex);
bool isFirst;
bool isLast;
- getParagraphContext(para,isFirst,isLast);
+ getParagraphContext(*para,isFirst,isLast);
//printf("forceEnd first=%d last=%d styleOutsideParagraph=%d\n",isFirst,isLast,styleOutsideParagraph);
if (isFirst && isLast) return;
if (styleOutsideParagraph) return;
+ //printf("adding </p>\n");
m_t << "</p>";
}
}
@@ -2486,29 +2294,33 @@ void HtmlDocVisitor::forceEndParagraph(DocNode *n)
* have to be outside of the paragraph. This method will forcefully start
* the paragraph, that was previously ended by forceEndParagraph().
*/
-void HtmlDocVisitor::forceStartParagraph(DocNode *n)
+template<class Node>
+void HtmlDocVisitor::forceStartParagraph(const Node &n)
{
- //printf("forceStartParagraph(%p) %d\n",n,n->kind());
- if (n->parent() && n->parent()->kind()==DocNode::Kind_Para) // if we are inside a paragraph
+ //printf("> forceStartParagraph(%s)\n",docNodeName(n));
+ const DocPara *para=0;
+ if (n.parent() && (para = std::get_if<DocPara>(n.parent()))) // if we are inside a paragraph
{
- DocPara *para = (DocPara*)n->parent();
const DocNodeList &children = para->children();
- auto it = std::find_if(children.begin(),children.end(),[n](const auto &np) { return np.get()==n; });
- if (it==children.end()) return;
- int nodeIndex = static_cast<int>(it - children.begin());
- int numNodes = static_cast<int>(para->children().size());
- bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,nodeIndex);
+
+ auto it = std::find_if(std::begin(children),
+ std::end(children),
+ [&n](const auto &np)
+ { return holds_value(&n,np); });
+ if (it==std::end(children)) return;
+ bool styleOutsideParagraph=insideStyleChangeThatIsOutsideParagraph(para,it);
+ //printf("it=%s (%p) styleOutsideParagraph=%d\n",
+ // docNodeName(*it), (void *)&*it, styleOutsideParagraph);
if (styleOutsideParagraph) return;
- nodeIndex++;
- if (nodeIndex==numNodes) return; // last node
- while (nodeIndex<numNodes && isInvisibleNode(para->children().at(nodeIndex).get()))
+ it = std::next(it);
+ while (it!=std::end(children) && isInvisibleNode(*it))
{
- nodeIndex++;
+ ++it;
}
- if (nodeIndex<numNodes)
+ if (it!=std::end(children))
{
- n = para->children().at(nodeIndex).get();
- if (mustBeOutsideParagraph(n)) return; // next element also outside paragraph
+ const DocNodeVariant &v = *it;
+ if (mustBeOutsideParagraph(v)) return; // next element also outside paragraph
}
else
{
@@ -2518,7 +2330,7 @@ void HtmlDocVisitor::forceStartParagraph(DocNode *n)
bool needsTag = TRUE;
bool isFirst;
bool isLast;
- getParagraphContext(para,isFirst,isLast);
+ getParagraphContext(*para,isFirst,isLast);
if (isFirst && isLast) needsTag = FALSE;
//printf("forceStart first=%d last=%d needsTag=%d\n",isFirst,isLast,needsTag);