summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/commentscan.l61
-rw-r--r--src/docparser.cpp57
-rw-r--r--src/docparser.h23
-rw-r--r--src/doctokenizer.l26
-rw-r--r--src/htmldocvisitor.cpp5
-rw-r--r--src/latexdocvisitor.cpp70
-rw-r--r--src/latexdocvisitor.h3
-rw-r--r--src/latexgen.cpp5
-rw-r--r--src/printdocvisitor.h5
-rw-r--r--src/section.h3
-rw-r--r--templates/latex/doxygen.sty5
11 files changed, 192 insertions, 71 deletions
diff --git a/src/commentscan.l b/src/commentscan.l
index 406d966..9442ae3 100644
--- a/src/commentscan.l
+++ b/src/commentscan.l
@@ -834,6 +834,29 @@ static inline void setOutput(OutputContext ctx)
}
}
+
+static void addAnchor(const char *anchor)
+{
+ SectionInfo *si = Doxygen::sectionDict->find(anchor);
+ if (si)
+ {
+ if (si->lineNr != -1)
+ {
+ warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s, line %d)",anchor,si->fileName.data(),si->lineNr);
+ }
+ else
+ {
+ warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s)",anchor,si->fileName.data());
+ }
+ }
+ else
+ {
+ si = new SectionInfo(yyFileName,yyLineNr,anchor,0,SectionInfo::Anchor,0);
+ Doxygen::sectionDict->append(anchor,si);
+ current->anchors->append(si);
+ }
+}
+
// add a string to the output
static inline void addOutput(const char *s)
{
@@ -905,6 +928,7 @@ IMG [iI][mM][gG]
HR [hH][rR]
PARA [pP][aA][rR][aA]
CODE [cC][oO][dD][eE]
+CAPTION [cC][aA][pP][tT][iI][oO][nN]
DETAILEDHTML {PRE}|{UL}|{TABLE}|{OL}|{DL}|{P}|[Hh][1-6]|{IMG}|{HR}|{PARA}
DETAILEDHTMLOPT {CODE}
BN [ \t\n\r]
@@ -1053,6 +1077,24 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
<Comment>"</remarks>" { // end of a brief or detailed description
addOutput(yytext);
}
+<Comment>"<"{CAPTION}{ATTR}">" {
+ QCString tag=yytext;
+ int s=tag.find("id=");
+ if (s!=-1) // command has id attribute
+ {
+ char c=tag[s+3];
+ if (c=='\'' || c=='"') // valid start
+ {
+ int e=tag.find(c,s+4);
+ if (e!=-1) // found matching end
+ {
+ QCString id=tag.mid(s+4,e-s-4); // extract id
+ addAnchor(id);
+ }
+ }
+ }
+ addOutput(yytext);
+ }
<Comment>"<"{PRE}{ATTR}">" {
insidePre=TRUE;
addOutput(yytext);
@@ -1745,24 +1787,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$"
/* ----- handle arguments of the anchor command ------- */
<AnchorLabel>{LABELID} { // found argument
- SectionInfo *si = Doxygen::sectionDict->find(yytext);
- if (si)
- {
- if (si->lineNr != -1)
- {
- warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s, line %d)",yytext,si->fileName.data(),si->lineNr);
- }
- else
- {
- warn(yyFileName,yyLineNr,"multiple use of section label '%s' while adding anchor, (first occurrence: %s)",yytext,si->fileName.data());
- }
- }
- else
- {
- si = new SectionInfo(yyFileName,yyLineNr,yytext,0,SectionInfo::Anchor,0);
- Doxygen::sectionDict->append(yytext,si);
- current->anchors->append(si);
- }
+ addAnchor(yytext);
addOutput(yytext);
BEGIN( Comment );
}
diff --git a/src/docparser.cpp b/src/docparser.cpp
index f4261ac..468f862 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -2418,7 +2418,7 @@ void DocInternalRef::parse()
//---------------------------------------------------------------------------
DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
- m_refToSection(FALSE), m_refToAnchor(FALSE), m_isSubPage(FALSE)
+ m_refType(Unknown), m_isSubPage(FALSE)
{
m_parent = parent;
Definition *compound = 0;
@@ -2444,8 +2444,18 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) :
m_ref = sec->ref;
m_file = stripKnownExtensions(sec->fileName);
- m_refToAnchor = sec->type==SectionInfo::Anchor;
- m_refToSection = sec->type!=SectionInfo::Anchor;
+ if (sec->type==SectionInfo::Anchor)
+ {
+ m_refType = Anchor;
+ }
+ else if (sec->type==SectionInfo::Table)
+ {
+ m_refType = Table;
+ }
+ else
+ {
+ m_refType = Section;
+ }
m_isSubPage = pd && pd->hasParentPage();
if (sec->type!=SectionInfo::Page || m_isSubPage) m_anchor = sec->label;
//printf("m_text=%s,m_ref=%s,m_file=%s,m_refToAnchor=%d type=%d\n",
@@ -3239,6 +3249,41 @@ endindexentry:
//---------------------------------------------------------------------------
+DocHtmlCaption::DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs)
+{
+ m_hasCaptionId = FALSE;
+ HtmlAttribListIterator li(attribs);
+ HtmlAttrib *opt;
+ for (li.toFirst();(opt=li.current());++li)
+ {
+ if (opt->name=="id") // interpret id attribute as an anchor
+ {
+ SectionInfo *sec = Doxygen::sectionDict->find(opt->value);
+ if (sec)
+ {
+ //printf("Found anchor %s\n",id.data());
+ m_file = sec->fileName;
+ m_anchor = sec->label;
+ m_hasCaptionId = TRUE;
+ if (g_sectionDict && g_sectionDict->find(opt->value)==0)
+ {
+ //printf("Inserting in dictionary!\n");
+ g_sectionDict->append(opt->value,sec);
+ }
+ }
+ else
+ {
+ warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid caption id `%s'",qPrint(opt->value));
+ }
+ }
+ else // copy attribute
+ {
+ m_attribs.append(new HtmlAttrib(*opt));
+ }
+ }
+ m_parent = parent;
+}
+
int DocHtmlCaption::parse()
{
int retval=0;
@@ -3744,12 +3789,14 @@ void DocHtmlTable::accept(DocVisitor *v)
{
v->visitPre(this);
// for HTML output we put the caption first
- if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v);
+ //if (m_caption && v->id()==DocVisitor_Html) m_caption->accept(v);
+ // doxygen 1.8.11: always put the caption first
+ if (m_caption) m_caption->accept(v);
QListIterator<DocNode> cli(m_children);
DocNode *n;
for (cli.toFirst();(n=cli.current());++cli) n->accept(v);
// for other output formats we put the caption last
- if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v);
+ //if (m_caption && v->id()!=DocVisitor_Html) m_caption->accept(v);
v->visitPost(this);
}
diff --git a/src/docparser.h b/src/docparser.h
index 4984921..fcd18a4 100644
--- a/src/docparser.h
+++ b/src/docparser.h
@@ -822,15 +822,16 @@ class DocRef : public CompAccept<DocRef>, public DocNode
QCString anchor() const { return m_anchor; }
QCString targetTitle() const { return m_text; }
bool hasLinkText() const { return !m_children.isEmpty(); }
- bool refToAnchor() const { return m_refToAnchor; }
- bool refToSection() const { return m_refToSection; }
+ bool refToAnchor() const { return m_refType==Anchor; }
+ bool refToSection() const { return m_refType==Section; }
+ bool refToTable() const { return m_refType==Table; }
bool isSubPage() const { return m_isSubPage; }
void accept(DocVisitor *v) { CompAccept<DocRef>::accept(this,v); }
private:
- bool m_refToSection;
- bool m_refToAnchor;
- bool m_isSubPage;
+ enum RefType { Unknown, Anchor, Section, Table };
+ RefType m_refType;
+ bool m_isSubPage;
QCString m_file;
QCString m_relPath;
QCString m_ref;
@@ -1279,15 +1280,20 @@ class DocHtmlCell : public CompAccept<DocHtmlCell>, public DocNode
class DocHtmlCaption : public CompAccept<DocHtmlCaption>, public DocNode
{
public:
- DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs) :
- m_attribs(attribs) { m_parent = parent; }
+ DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs);
Kind kind() const { return Kind_HtmlCaption; }
void accept(DocVisitor *v) { CompAccept<DocHtmlCaption>::accept(this,v); }
const HtmlAttribList &attribs() const { return m_attribs; }
int parse();
+ bool hasCaptionId() const { return m_hasCaptionId; }
+ QCString file() const { return m_file; }
+ QCString anchor() const { return m_anchor; }
private:
HtmlAttribList m_attribs;
+ bool m_hasCaptionId;
+ QCString m_file;
+ QCString m_anchor;
};
/** Node representing a HTML table row */
@@ -1342,7 +1348,8 @@ class DocHtmlTable : public CompAccept<DocHtmlTable>, public DocNode
int parseXml();
uint numColumns() const { return m_numCols; }
void accept(DocVisitor *v);
- DocHtmlRow *firstRow() {
+ DocHtmlCaption *caption() const { return m_caption; }
+ DocHtmlRow *firstRow() const {
DocNode *n = m_children.getFirst();
if (n && n->kind()==Kind_HtmlRow) return (DocHtmlRow*)n;
return 0;
diff --git a/src/doctokenizer.l b/src/doctokenizer.l
index efc058a..8c58fb5 100644
--- a/src/doctokenizer.l
+++ b/src/doctokenizer.l
@@ -169,8 +169,7 @@ static void processSection()
if ((si=Doxygen::sectionDict->find(g_secLabel)))
{
si->fileName = file;
- //si = new SectionInfo(file,g_secLabel,g_secTitle,g_secType);
- //Doxygen::sectionDict.insert(g_secLabel,si);
+ si->type = g_secType;
}
}
@@ -389,6 +388,7 @@ WORD1 {ESCWORD}|{CHARWORDQ}+|"{"|"}"|"'\"'"|("\""[^"\n]*\n?[^"\n]*"\"")
WORD2 "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}"
WORD2NQ "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'"
+CAPTION [cC][aA][pP][tT][iI][oO][nN]
HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">"
HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p"
HTMLKEYU "STRONG"|"CENTER"|"TABLE"|"CAPTION"|"SMALL"|"CODE"|"DFN"|"VAR"|"IMG"|"PRE"|"SUB"|"SUP"|"TR"|"TD"|"TH"|"OL"|"UL"|"LI"|"TT"|"KBD"|"EM"|"HR"|"DL"|"DT"|"DD"|"BR"|"I"|"A"|"B"|"P"
@@ -1160,8 +1160,26 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3}|{REFWORD4}
/* State for the pass used to find the anchors and sections */
-<St_Sections>[^\n@\\]+
-<St_Sections>"@@"|"\\\\"
+<St_Sections>[^\n@\\<]+
+<St_Sections>"@@"|"\\\\"|"@<"|"\\<"
+<St_Sections>"<"{CAPTION}({WS}+{ATTRIB})*">" {
+ QCString tag=yytext;
+ int s=tag.find("id=");
+ if (s!=-1) // command has id attribute
+ {
+ char c=tag[s+3];
+ if (c=='\'' || c=='"') // valid start
+ {
+ int e=tag.find(c,s+4);
+ if (e!=-1) // found matching end
+ {
+ g_secType = SectionInfo::Table;
+ g_secLabel=tag.mid(s+4,e-s-4); // extract id
+ processSection();
+ }
+ }
+ }
+ }
<St_Sections>{CMD}"anchor"{BLANK}+ {
g_secType = SectionInfo::Anchor;
BEGIN(St_SecLabel1);
diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
index 0ce4030..54dca32 100644
--- a/src/htmldocvisitor.cpp
+++ b/src/htmldocvisitor.cpp
@@ -1353,9 +1353,14 @@ void HtmlDocVisitor::visitPost(DocHtmlCell *c)
void HtmlDocVisitor::visitPre(DocHtmlCaption *c)
{
if (m_hide) return;
+ if (c->hasCaptionId())
+ {
+ m_t << "<a class=\"anchor\" id=\"" << c->anchor() << "\"></a>\n";
+ }
bool hasAlign = FALSE;
HtmlAttribListIterator li(c->attribs());
HtmlAttrib *att;
+ QCString id;
for (li.toFirst();(att=li.current());++li)
{
if (att->name=="align") hasAlign=TRUE;
diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp
index b9e5839..22b3b32 100644
--- a/src/latexdocvisitor.cpp
+++ b/src/latexdocvisitor.cpp
@@ -171,7 +171,7 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s)
LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci,
const char *langExt,bool insideTabbing)
: DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE),
- m_insideItem(FALSE), m_hide(FALSE), m_insideTabbing(insideTabbing),
+ m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE), m_insideTabbing(insideTabbing),
m_insideTable(FALSE), m_langExt(langExt), m_currentColumn(0),
m_inRowspan(FALSE), m_inColspan(FALSE), m_firstRow(FALSE)
{
@@ -908,9 +908,28 @@ void LatexDocVisitor::visitPre(DocHtmlTable *t)
if (m_hide) return;
if (t->hasCaption())
{
- m_t << "\\begin{table}[h]";
+ DocHtmlCaption *c = t->caption();
+ static bool pdfHyperLinks = Config_getBool("PDF_HYPERLINKS");
+ if (!c->file().isEmpty() && pdfHyperLinks)
+ {
+ m_t << "\\hypertarget{" << stripPath(c->file()) << "_" << c->anchor()
+ << "}{}";
+ }
+ m_t << endl;
}
+
m_t << "\\begin{" << getTableName(t->parent()) << "}{" << t->numColumns() << "}\n";
+
+ if (t->hasCaption())
+ {
+ DocHtmlCaption *c = t->caption();
+ m_t << "\\caption{";
+ visitCaption(this, c->children());
+ m_t << "}";
+ m_t << "\\label{" << stripPath(c->file()) << "_" << c->anchor() << "}";
+ m_t << "\\\\\n";
+ }
+
m_numCols = t->numColumns();
m_t << "\\hline\n";
@@ -930,26 +949,18 @@ void LatexDocVisitor::visitPost(DocHtmlTable *t)
{
m_insideTable=FALSE;
if (m_hide) return;
- if (t->hasCaption())
- {
- m_t << "\\end{table}\n";
- }
- else
- {
- m_t << "\\end{" << getTableName(t->parent()) << "}\n";
- }
+ m_t << "\\end{" << getTableName(t->parent()) << "}\n";
}
void LatexDocVisitor::visitPre(DocHtmlCaption *c)
{
- if (m_hide) return;
- m_t << "\\end{" << getTableName(c->parent()->parent()) << "}\n\\centering\n\\caption{";
+ m_hideCaption = m_hide;
+ m_hide = TRUE;
}
-void LatexDocVisitor::visitPost(DocHtmlCaption *)
+void LatexDocVisitor::visitPost(DocHtmlCaption *c)
{
- if (m_hide) return;
- m_t << "}\n";
+ m_hide = m_hideCaption;
}
void LatexDocVisitor::visitPre(DocHtmlRow *r)
@@ -1029,6 +1040,8 @@ void LatexDocVisitor::visitPost(DocHtmlRow *row)
{
m_t << "\\endfirsthead" << endl;
m_t << "\\hline" << endl;
+ m_t << "\\endfoot" << endl;
+ m_t << "\\hline" << endl;
}
else
{
@@ -1077,16 +1090,6 @@ void LatexDocVisitor::visitPre(DocHtmlCell *c)
}
}
-#if 0
- QMap<int, int>::Iterator it = m_rowspanIndices.find(m_currentColumn);
- if (it!=m_rowspanIndices.end() && it.data()>0)
- {
- m_t << "&";
- m_currentColumn++;
- it++;
- }
-#endif
-
int cs = c->colSpan();
if (cs>1 && row)
{
@@ -1106,7 +1109,6 @@ void LatexDocVisitor::visitPre(DocHtmlCell *c)
if (rs>0)
{
m_inRowspan = TRUE;
- //m_rowspanIndices[m_currentColumn] = rs;
m_rowSpans.append(new ActiveRowSpan(c,rs,cs,m_currentColumn));
m_t << "\\multirow{" << rs << "}{\\linewidth}{";
}
@@ -1282,7 +1284,7 @@ void LatexDocVisitor::visitPre(DocRef *ref)
}
else
{
- if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
+ if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor(),ref->refToTable());
}
if (!ref->hasLinkText()) filter(ref->targetTitle());
}
@@ -1598,9 +1600,10 @@ void LatexDocVisitor::filter(const char *str)
filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem);
}
-void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
+void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor,bool refToTable)
{
- if (ref.isEmpty() && Config_getBool("PDF_HYPERLINKS")) // internal PDF link
+ static bool pdfHyperLinks = Config_getBool("PDF_HYPERLINKS");
+ if (ref.isEmpty() && pdfHyperLinks) // internal PDF link
{
m_t << "\\hyperlink{";
if (!file.isEmpty()) m_t << stripPath(file);
@@ -1608,6 +1611,10 @@ void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const Q
if (!anchor.isEmpty()) m_t << anchor;
m_t << "}{";
}
+ else if (refToTable)
+ {
+ m_t << "\\doxytableref{";
+ }
else if (ref.isEmpty()) // internal non-PDF link
{
m_t << "\\doxyref{";
@@ -1621,9 +1628,10 @@ void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const Q
void LatexDocVisitor::endLink(const QCString &ref,const QCString &file,const QCString &anchor)
{
m_t << "}";
- if (ref.isEmpty() && !Config_getBool("PDF_HYPERLINKS"))
+ static bool pdfHyperLinks = Config_getBool("PDF_HYPERLINKS");
+ if (ref.isEmpty() && !pdfHyperLinks)
{
- m_t << "{";
+ m_t << "{";
filter(theTranslator->trPageAbbreviation());
m_t << "}{" << file;
if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h
index e36e56c..de797ae 100644
--- a/src/latexdocvisitor.h
+++ b/src/latexdocvisitor.h
@@ -159,7 +159,7 @@ class LatexDocVisitor : public DocVisitor
void filter(const char *str);
void startLink(const QCString &ref,const QCString &file,
- const QCString &anchor);
+ const QCString &anchor,bool refToTable=FALSE);
void endLink(const QCString &ref,const QCString &file,
const QCString &anchor);
QCString escapeMakeIndexChars(const char *s);
@@ -190,6 +190,7 @@ class LatexDocVisitor : public DocVisitor
bool m_insidePre;
bool m_insideItem;
bool m_hide;
+ bool m_hideCaption;
bool m_insideTabbing;
bool m_insideTable;
int m_numCols;
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index 30e28ec..2ed30e9 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -455,9 +455,12 @@ static void writeDefaultHeaderPart1(FTextStream &t)
"\\newcommand{\\clearemptydoublepage}{%\n"
" \\newpage{\\pagestyle{empty}\\cleardoublepage}%\n"
"}\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";
+
// End of preamble, now comes the document contents
t << "%===== C O N T E N T S =====\n"
"\n"
diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h
index 95e7e47..b86670a 100644
--- a/src/printdocvisitor.h
+++ b/src/printdocvisitor.h
@@ -536,10 +536,11 @@ class PrintDocVisitor : public DocVisitor
indent_pre();
printf("<ref ref=\"%s\" file=\"%s\" "
"anchor=\"%s\" targetTitle=\"%s\""
- " hasLinkText=\"%s\" refToAnchor=\"%s\" refToSection=\"%s\">\n",
+ " hasLinkText=\"%s\" refToAnchor=\"%s\" refToSection=\"%s\" refToTable=\"%s\">\n",
ref->ref().data(),ref->file().data(),ref->anchor().data(),
ref->targetTitle().data(),ref->hasLinkText()?"yes":"no",
- ref->refToAnchor()?"yes":"no", ref->refToSection()?"yes":"no");
+ ref->refToAnchor()?"yes":"no", ref->refToSection()?"yes":"no",
+ ref->refToTable()?"yes":"no");
}
void visitPost(DocRef *)
{
diff --git a/src/section.h b/src/section.h
index 51668a2..b6268a9 100644
--- a/src/section.h
+++ b/src/section.h
@@ -31,7 +31,8 @@ struct SectionInfo
Subsection = 2,
Subsubsection = 3,
Paragraph = 4,
- Anchor = 5
+ Anchor = 5,
+ Table = 6
};
SectionInfo(const char *f,const int lin,const char *l,const char *t,
SectionType st,int lev,const char *r=0) :
diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty
index 66ffca3..64fb0f0 100644
--- a/templates/latex/doxygen.sty
+++ b/templates/latex/doxygen.sty
@@ -444,6 +444,11 @@
\textbf{#1} (\textnormal{#2}\,\pageref{#3})%
}
+% Used to link to a table when hyperlinks are turned off
+\newcommand{\doxytableref}[3]{%
+ \ref{#3}%
+}
+
% Used by @addindex
\newcommand{\lcurly}{\{}
\newcommand{\rcurly}{\}}