1 /******************************************************************************
6 * Copyright (C) 1997-2014 by Dimitri van Heesch.
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation under the terms of the GNU General Public License is hereby
10 * granted. No representations are made about the suitability of this software
11 * for any purpose. It is provided "as is" without express or implied warranty.
12 * See the GNU General Public License for more details.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
18 #include "htmlattrib.h"
19 #include <qfileinfo.h>
20 #include "latexdocvisitor.h"
21 #include "docparser.h"
24 #include "outputgen.h"
28 #include "parserintf.h"
34 #include "htmlentity.h"
36 static QCString escapeLabelName(const char *s)
47 case '%': result+="\\%"; break;
48 case '|': result+="\\texttt{\"|}"; break;
49 case '!': result+="\"!"; break;
50 case '{': result+="\\lcurly{}"; break;
51 case '}': result+="\\rcurly{}"; break;
52 case '~': result+="````~"; break; // to get it a bit better in index together with other special characters
60 const int maxLevels=5;
61 static const char *secLabels[maxLevels] =
62 { "section","subsection","subsubsection","paragraph","subparagraph" };
64 static const char *getSectionName(int level)
66 static bool compactLatex = Config_getBool("COMPACT_LATEX");
68 if (compactLatex) l++;
69 if (Doxygen::insideMainPage) l--;
70 return secLabels[QMIN(maxLevels-1,l)];
73 QCString LatexDocVisitor::escapeMakeIndexChars(const char *s)
77 char str[2]; str[1]=0;
85 case '!': m_t << "\"!"; break;
86 case '"': m_t << "\"\""; break;
87 case '@': m_t << "\"@"; break;
88 case '|': m_t << "\\texttt{\"|}"; break;
89 case '[': m_t << "["; break;
90 case ']': m_t << "]"; break;
91 case '{': m_t << "\\lcurly{}"; break;
92 case '}': m_t << "\\rcurly{}"; break;
93 default: str[0]=c; filter(str); break;
101 LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci,
102 const char *langExt,bool insideTabbing)
103 : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE),
104 m_insideItem(FALSE), m_hide(FALSE), m_insideTabbing(insideTabbing),
105 m_insideTable(FALSE), m_langExt(langExt), m_currentColumn(0),
106 m_inRowspan(FALSE), m_inColspan(FALSE)
108 m_rowSpans.setAutoDelete(TRUE);
111 //--------------------------------------
112 // visitor functions for leaf nodes
113 //--------------------------------------
115 void LatexDocVisitor::visit(DocWord *w)
121 void LatexDocVisitor::visit(DocLinkedWord *w)
124 startLink(w->ref(),w->file(),w->anchor());
126 endLink(w->ref(),w->file(),w->anchor());
129 void LatexDocVisitor::visit(DocWhiteSpace *w)
142 void LatexDocVisitor::visit(DocSymbol *s)
145 const char *res = HtmlEntityMapper::instance()->latex(s->symbol());
148 if (((s->symbol() == DocSymbol::Sym_lt) || (s->symbol() == DocSymbol::Sym_Less))&& (!m_insidePre))
152 else if (((s->symbol() == DocSymbol::Sym_gt) || (s->symbol() == DocSymbol::Sym_Greater)) && (!m_insidePre))
163 err("LaTeX: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
167 void LatexDocVisitor::visit(DocURL *u)
170 if (Config_getBool("PDF_HYPERLINKS"))
173 if (u->isEmail()) m_t << "mailto:";
174 m_t << u->url() << "}";
181 void LatexDocVisitor::visit(DocLineBreak *)
184 m_t << "~\\newline\n";
187 void LatexDocVisitor::visit(DocHorRuler *)
193 void LatexDocVisitor::visit(DocStyleChange *s)
198 case DocStyleChange::Bold:
199 if (s->enable()) m_t << "{\\bfseries "; else m_t << "}";
201 case DocStyleChange::Italic:
202 if (s->enable()) m_t << "{\\itshape "; else m_t << "}";
204 case DocStyleChange::Code:
205 if (s->enable()) m_t << "{\\ttfamily "; else m_t << "}";
207 case DocStyleChange::Subscript:
208 if (s->enable()) m_t << "\\textsubscript{"; else m_t << "}";
210 case DocStyleChange::Superscript:
211 if (s->enable()) m_t << "\\textsuperscript{"; else m_t << "}";
213 case DocStyleChange::Center:
214 if (s->enable()) m_t << "\\begin{center}"; else m_t << "\\end{center} ";
216 case DocStyleChange::Small:
217 if (s->enable()) m_t << "\n\\footnotesize "; else m_t << "\n\\normalsize ";
219 case DocStyleChange::Preformatted:
222 m_t << "\n\\begin{DoxyPre}";
228 m_t << "\\end{DoxyPre}\n";
231 case DocStyleChange::Div: /* HTML only */ break;
232 case DocStyleChange::Span: /* HTML only */ break;
236 void LatexDocVisitor::visit(DocVerbatim *s)
239 QCString lang = m_langExt;
240 if (!s->language().isEmpty()) // explicit language setting
242 lang = s->language();
244 SrcLangExt langExt = getLanguageFromFileName(lang);
247 case DocVerbatim::Code:
249 m_t << "\n\\begin{DoxyCode}\n";
250 Doxygen::parserManager->getParser(lang)
251 ->parseCode(m_ci,s->context(),s->text(),langExt,
252 s->isExample(),s->exampleFile());
253 m_t << "\\end{DoxyCode}\n";
256 case DocVerbatim::Verbatim:
257 m_t << "\\begin{DoxyVerb}";
259 m_t << "\\end{DoxyVerb}\n";
261 case DocVerbatim::HtmlOnly:
262 case DocVerbatim::XmlOnly:
263 case DocVerbatim::ManOnly:
264 case DocVerbatim::RtfOnly:
265 case DocVerbatim::DocbookOnly:
268 case DocVerbatim::LatexOnly:
271 case DocVerbatim::Dot:
273 static int dotindex = 1;
274 QCString fileName(4096);
276 fileName.sprintf("%s%d%s",
277 (Config_getString("LATEX_OUTPUT")+"/inline_dotgraph_").data(),
281 QFile file(fileName);
282 if (!file.open(IO_WriteOnly))
284 err("Could not open file %s for writing\n",fileName.data());
286 file.writeBlock( s->text(), s->text().length() );
289 m_t << "\\begin{center}\n";
290 startDotFile(fileName,"","",FALSE);
292 m_t << "\\end{center}\n";
294 if (Config_getBool("DOT_CLEANUP")) file.remove();
297 case DocVerbatim::Msc:
299 static int mscindex = 1;
300 QCString baseName(4096);
302 baseName.sprintf("%s%d",
303 (Config_getString("LATEX_OUTPUT")+"/inline_mscgraph_").data(),
306 QFile file(baseName+".msc");
307 if (!file.open(IO_WriteOnly))
309 err("Could not open file %s.msc for writing\n",baseName.data());
311 QCString text = "msc {";
314 file.writeBlock( text, text.length() );
317 m_t << "\\begin{center}\n";
318 writeMscFile(baseName);
319 m_t << "\\end{center}\n";
321 if (Config_getBool("DOT_CLEANUP")) file.remove();
327 void LatexDocVisitor::visit(DocAnchor *anc)
330 m_t << "\\label{" << stripPath(anc->file()) << "_" << anc->anchor() << "}%" << endl;
331 if (!anc->file().isEmpty() && Config_getBool("PDF_HYPERLINKS"))
333 m_t << "\\hypertarget{" << stripPath(anc->file()) << "_" << anc->anchor()
338 void LatexDocVisitor::visit(DocInclude *inc)
341 SrcLangExt langExt = getLanguageFromFileName(inc->extension());
344 case DocInclude::IncWithLines:
346 m_t << "\n\\begin{DoxyCodeInclude}\n";
347 QFileInfo cfi( inc->file() );
348 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
349 Doxygen::parserManager->getParser(inc->extension())
350 ->parseCode(m_ci,inc->context(),
354 inc->exampleFile(), &fd);
355 m_t << "\\end{DoxyCodeInclude}" << endl;
358 case DocInclude::Include:
359 m_t << "\n\\begin{DoxyCodeInclude}\n";
360 Doxygen::parserManager->getParser(inc->extension())
361 ->parseCode(m_ci,inc->context(),
362 inc->text(),langExt,inc->isExample(),
364 m_t << "\\end{DoxyCodeInclude}\n";
366 case DocInclude::DontInclude:
368 case DocInclude::HtmlInclude:
370 case DocInclude::LatexInclude:
373 case DocInclude::VerbInclude:
374 m_t << "\n\\begin{DoxyVerbInclude}\n";
376 m_t << "\\end{DoxyVerbInclude}\n";
378 case DocInclude::Snippet:
380 m_t << "\n\\begin{DoxyCodeInclude}\n";
381 Doxygen::parserManager->getParser(inc->extension())
384 extractBlock(inc->text(),inc->blockId()),
389 m_t << "\\end{DoxyCodeInclude}" << endl;
395 void LatexDocVisitor::visit(DocIncOperator *op)
397 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
398 // op->type(),op->isFirst(),op->isLast(),op->text().data());
401 if (!m_hide) m_t << "\n\\begin{DoxyCodeInclude}\n";
405 SrcLangExt langExt = getLanguageFromFileName(m_langExt);
406 if (op->type()!=DocIncOperator::Skip)
411 Doxygen::parserManager->getParser(m_langExt)
412 ->parseCode(m_ci,op->context(),op->text(),langExt,
413 op->isExample(),op->exampleFile());
421 if (!m_hide) m_t << "\n\\end{DoxyCodeInclude}\n";
425 if (!m_hide) m_t << endl;
429 void LatexDocVisitor::visit(DocFormula *f)
435 void LatexDocVisitor::visit(DocIndexEntry *i)
438 m_t << "\\index{" << escapeLabelName(i->entry()) << "@{";
439 escapeMakeIndexChars(i->entry());
443 void LatexDocVisitor::visit(DocSimpleSectSep *)
447 void LatexDocVisitor::visit(DocCite *cite)
450 if (!cite->file().isEmpty())
452 //startLink(cite->ref(),cite->file(),cite->anchor());
453 QCString anchor = cite->anchor();
454 anchor = anchor.mid(CiteConsts::anchorPrefix.length()); // strip prefix
455 m_t << "\\cite{" << anchor << "}";
459 m_t << "{\\bfseries [";
460 filter(cite->text());
465 //--------------------------------------
466 // visitor functions for compound nodes
467 //--------------------------------------
469 void LatexDocVisitor::visitPre(DocAutoList *l)
474 m_t << "\n\\begin{DoxyEnumerate}";
478 m_t << "\n\\begin{DoxyItemize}";
482 void LatexDocVisitor::visitPost(DocAutoList *l)
487 m_t << "\n\\end{DoxyEnumerate}";
491 m_t << "\n\\end{DoxyItemize}";
495 void LatexDocVisitor::visitPre(DocAutoListItem *)
501 void LatexDocVisitor::visitPost(DocAutoListItem *)
505 void LatexDocVisitor::visitPre(DocPara *)
509 void LatexDocVisitor::visitPost(DocPara *p)
512 if (!p->isLast() && // omit <p> for last paragraph
513 !(p->parent() && // and for parameter sections
514 p->parent()->kind()==DocNode::Kind_ParamSect
516 ) m_t << endl << endl;
519 void LatexDocVisitor::visitPre(DocRoot *)
523 void LatexDocVisitor::visitPost(DocRoot *)
527 void LatexDocVisitor::visitPre(DocSimpleSect *s)
532 case DocSimpleSect::See:
533 m_t << "\\begin{DoxySeeAlso}{";
534 filter(theTranslator->trSeeAlso());
536 case DocSimpleSect::Return:
537 m_t << "\\begin{DoxyReturn}{";
538 filter(theTranslator->trReturns());
540 case DocSimpleSect::Author:
541 m_t << "\\begin{DoxyAuthor}{";
542 filter(theTranslator->trAuthor(TRUE,TRUE));
544 case DocSimpleSect::Authors:
545 m_t << "\\begin{DoxyAuthor}{";
546 filter(theTranslator->trAuthor(TRUE,FALSE));
548 case DocSimpleSect::Version:
549 m_t << "\\begin{DoxyVersion}{";
550 filter(theTranslator->trVersion());
552 case DocSimpleSect::Since:
553 m_t << "\\begin{DoxySince}{";
554 filter(theTranslator->trSince());
556 case DocSimpleSect::Date:
557 m_t << "\\begin{DoxyDate}{";
558 filter(theTranslator->trDate());
560 case DocSimpleSect::Note:
561 m_t << "\\begin{DoxyNote}{";
562 filter(theTranslator->trNote());
564 case DocSimpleSect::Warning:
565 m_t << "\\begin{DoxyWarning}{";
566 filter(theTranslator->trWarning());
568 case DocSimpleSect::Pre:
569 m_t << "\\begin{DoxyPrecond}{";
570 filter(theTranslator->trPrecondition());
572 case DocSimpleSect::Post:
573 m_t << "\\begin{DoxyPostcond}{";
574 filter(theTranslator->trPostcondition());
576 case DocSimpleSect::Copyright:
577 m_t << "\\begin{DoxyCopyright}{";
578 filter(theTranslator->trCopyright());
580 case DocSimpleSect::Invar:
581 m_t << "\\begin{DoxyInvariant}{";
582 filter(theTranslator->trInvariant());
584 case DocSimpleSect::Remark:
585 m_t << "\\begin{DoxyRemark}{";
586 filter(theTranslator->trRemarks());
588 case DocSimpleSect::Attention:
589 m_t << "\\begin{DoxyAttention}{";
590 filter(theTranslator->trAttention());
592 case DocSimpleSect::User:
593 m_t << "\\begin{DoxyParagraph}{";
595 case DocSimpleSect::Rcs:
596 m_t << "\\begin{DoxyParagraph}{";
598 case DocSimpleSect::Unknown: break;
601 // special case 1: user defined title
602 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
612 void LatexDocVisitor::visitPost(DocSimpleSect *s)
617 case DocSimpleSect::See:
618 m_t << "\n\\end{DoxySeeAlso}\n";
620 case DocSimpleSect::Return:
621 m_t << "\n\\end{DoxyReturn}\n";
623 case DocSimpleSect::Author:
624 m_t << "\n\\end{DoxyAuthor}\n";
626 case DocSimpleSect::Authors:
627 m_t << "\n\\end{DoxyAuthor}\n";
629 case DocSimpleSect::Version:
630 m_t << "\n\\end{DoxyVersion}\n";
632 case DocSimpleSect::Since:
633 m_t << "\n\\end{DoxySince}\n";
635 case DocSimpleSect::Date:
636 m_t << "\n\\end{DoxyDate}\n";
638 case DocSimpleSect::Note:
639 m_t << "\n\\end{DoxyNote}\n";
641 case DocSimpleSect::Warning:
642 m_t << "\n\\end{DoxyWarning}\n";
644 case DocSimpleSect::Pre:
645 m_t << "\n\\end{DoxyPrecond}\n";
647 case DocSimpleSect::Post:
648 m_t << "\n\\end{DoxyPostcond}\n";
650 case DocSimpleSect::Copyright:
651 m_t << "\n\\end{DoxyCopyright}\n";
653 case DocSimpleSect::Invar:
654 m_t << "\n\\end{DoxyInvariant}\n";
656 case DocSimpleSect::Remark:
657 m_t << "\n\\end{DoxyRemark}\n";
659 case DocSimpleSect::Attention:
660 m_t << "\n\\end{DoxyAttention}\n";
662 case DocSimpleSect::User:
663 m_t << "\n\\end{DoxyParagraph}\n";
665 case DocSimpleSect::Rcs:
666 m_t << "\n\\end{DoxyParagraph}\n";
673 void LatexDocVisitor::visitPre(DocTitle *)
677 void LatexDocVisitor::visitPost(DocTitle *)
684 void LatexDocVisitor::visitPre(DocSimpleList *)
687 m_t << "\\begin{DoxyItemize}" << endl;
690 void LatexDocVisitor::visitPost(DocSimpleList *)
693 m_t << "\\end{DoxyItemize}" << endl;
696 void LatexDocVisitor::visitPre(DocSimpleListItem *)
702 void LatexDocVisitor::visitPost(DocSimpleListItem *)
706 void LatexDocVisitor::visitPre(DocSection *s)
709 if (Config_getBool("PDF_HYPERLINKS"))
711 m_t << "\\hypertarget{" << stripPath(s->file()) << "_" << s->anchor() << "}{}";
713 m_t << "\\" << getSectionName(s->level()) << "{";
714 filter(convertCharEntitiesToUTF8(s->title().data()));
715 m_t << "}\\label{" << stripPath(s->file()) << "_" << s->anchor() << "}" << endl;
718 void LatexDocVisitor::visitPost(DocSection *)
722 void LatexDocVisitor::visitPre(DocHtmlList *s)
725 if (s->type()==DocHtmlList::Ordered)
726 m_t << "\n\\begin{DoxyEnumerate}";
728 m_t << "\n\\begin{DoxyItemize}";
731 void LatexDocVisitor::visitPost(DocHtmlList *s)
734 if (s->type()==DocHtmlList::Ordered)
735 m_t << "\n\\end{DoxyEnumerate}";
737 m_t << "\n\\end{DoxyItemize}";
740 void LatexDocVisitor::visitPre(DocHtmlListItem *)
746 void LatexDocVisitor::visitPost(DocHtmlListItem *)
750 //void LatexDocVisitor::visitPre(DocHtmlPre *)
752 // m_t << "\\small\\begin{alltt}";
756 //void LatexDocVisitor::visitPost(DocHtmlPre *)
758 // m_insidePre=FALSE;
759 // m_t << "\\end{alltt}\\normalsize " << endl;
762 void LatexDocVisitor::visitPre(DocHtmlDescList *dl)
765 QCString val = dl->attribs().find("class");
768 m_t << "\n\\begin{DoxyRefList}";
772 m_t << "\n\\begin{DoxyDescription}";
776 void LatexDocVisitor::visitPost(DocHtmlDescList *dl)
779 QCString val = dl->attribs().find("class");
782 m_t << "\n\\end{DoxyRefList}";
786 m_t << "\n\\end{DoxyDescription}";
790 void LatexDocVisitor::visitPre(DocHtmlDescTitle *)
797 void LatexDocVisitor::visitPost(DocHtmlDescTitle *)
804 void LatexDocVisitor::visitPre(DocHtmlDescData *)
808 void LatexDocVisitor::visitPost(DocHtmlDescData *)
812 void LatexDocVisitor::visitPre(DocHtmlTable *t)
819 m_t << "\\begin{table}[h]";
821 m_t << "\\begin{TabularC}{" << t->numColumns() << "}\n";
822 m_numCols = t->numColumns();
826 void LatexDocVisitor::visitPost(DocHtmlTable *t)
832 m_t << "\\end{table}\n";
836 m_t << "\\end{TabularC}\n";
840 void LatexDocVisitor::visitPre(DocHtmlCaption *)
843 m_t << "\\end{TabularC}\n\\centering\n\\caption{";
846 void LatexDocVisitor::visitPost(DocHtmlCaption *)
852 void LatexDocVisitor::visitPre(DocHtmlRow *r)
855 if (r->isHeading()) m_t << "\\rowcolor{lightgray}";
858 void LatexDocVisitor::visitPost(DocHtmlRow *row)
862 int c=m_currentColumn;
863 while (c<=m_numCols) // end of row while inside a row span?
866 for (i=0;i<m_rowSpans.count();i++)
868 ActiveRowSpan *span = m_rowSpans.at(i);
869 //printf(" founc row span: column=%d rs=%d cs=%d rowIdx=%d cell->rowIdx=%d\n",
870 // span->column, span->rowSpan,span->colSpan,row->rowIndex(),span->cell->rowIndex());
871 if (span->rowSpan>0 && span->column==c && // we are at a cell in a row span
872 row->rowIndex()>span->cell->rowIndex() // but not the row that started the span
876 if (span->colSpan>1) // row span is also part of a column span
878 m_t << "\\multicolumn{" << span->colSpan << "}{";
879 m_t << "p{(\\linewidth-\\tabcolsep*"
880 << m_numCols << "-\\arrayrulewidth*"
881 << row->visibleCells() << ")*"
882 << span->colSpan <<"/"<< m_numCols << "}|}{}";
884 else // solitary row span
886 m_t << "\\multicolumn{1}{c|}{}";
897 for (i=0;i<m_rowSpans.count();i++)
899 ActiveRowSpan *span = m_rowSpans.at(i);
900 if (span->rowSpan>0) span->rowSpan--;
901 if (span->rowSpan<=0)
905 else if (span->column>col)
907 m_t << "\\cline{" << col << "-" << (span->column-1) << "}";
908 col = span->column+span->colSpan;
912 col = span->column+span->colSpan;
916 if (col <= m_numCols)
918 m_t << "\\cline{" << col << "-" << m_numCols << "}";
924 void LatexDocVisitor::visitPre(DocHtmlCell *c)
929 if (c->parent() && c->parent()->kind()==DocNode::Kind_HtmlRow)
931 row = (DocHtmlRow*)c->parent();
936 //Skip columns that span from above.
938 for (i=0;i<m_rowSpans.count();i++)
940 ActiveRowSpan *span = m_rowSpans.at(i);
941 if (span->rowSpan>0 && span->column==m_currentColumn)
943 if (row && span->colSpan>1)
945 m_t << "\\multicolumn{" << span->colSpan << "}{";
946 if (m_currentColumn /*c->columnIndex()*/==1) // add extra | for first column
950 m_t << "p{(\\linewidth-\\tabcolsep*"
951 << m_numCols << "-\\arrayrulewidth*"
952 << row->visibleCells() << ")*"
953 << span->colSpan <<"/"<< m_numCols << "}|}{}";
954 m_currentColumn+=span->colSpan;
965 QMap<int, int>::Iterator it = m_rowspanIndices.find(m_currentColumn);
966 if (it!=m_rowspanIndices.end() && it.data()>0)
974 int cs = c->colSpan();
978 m_t << "\\multicolumn{" << cs << "}{";
979 if (c->columnIndex()==1) // add extra | for first column
983 m_t << "p{(\\linewidth-\\tabcolsep*"
984 << m_numCols << "-\\arrayrulewidth*"
985 << row->visibleCells() << ")*"
986 << cs <<"/"<< m_numCols << "}|}{";
987 if (c->isHeading()) m_t << "\\cellcolor{lightgray}";
989 int rs = c->rowSpan();
993 //m_rowspanIndices[m_currentColumn] = rs;
994 m_rowSpans.append(new ActiveRowSpan(c,rs,cs,m_currentColumn));
995 m_t << "\\multirow{" << rs << "}{\\linewidth}{";
997 int a = c->alignment();
998 if (a==DocHtmlCell::Center)
1000 m_t << "\\PBS\\centering ";
1002 else if (a==DocHtmlCell::Right)
1004 m_t << "\\PBS\\raggedleft ";
1012 m_currentColumn+=cs-1;
1016 void LatexDocVisitor::visitPost(DocHtmlCell *c)
1025 m_inRowspan = FALSE;
1030 m_inColspan = FALSE;
1033 if (!c->isLast()) m_t << "&";
1036 void LatexDocVisitor::visitPre(DocInternal *)
1039 //m_t << "\\begin{DoxyInternal}{";
1040 //filter(theTranslator->trForInternalUseOnly());
1044 void LatexDocVisitor::visitPost(DocInternal *)
1047 //m_t << "\\end{DoxyInternal}" << endl;
1050 void LatexDocVisitor::visitPre(DocHRef *href)
1053 if (Config_getBool("PDF_HYPERLINKS"))
1062 void LatexDocVisitor::visitPost(DocHRef *)
1068 void LatexDocVisitor::visitPre(DocHtmlHeader *header)
1071 m_t << "\\" << getSectionName(header->level()) << "*{";
1074 void LatexDocVisitor::visitPost(DocHtmlHeader *)
1080 void LatexDocVisitor::visitPre(DocImage *img)
1082 if (img->type()==DocImage::Latex)
1085 if (img->hasCaption())
1087 m_t << "\n\\begin{DoxyImage}\n";
1091 m_t << "\n\\begin{DoxyImageNoCaption}\n"
1094 QCString gfxName = img->name();
1095 if (gfxName.right(4)==".eps" || gfxName.right(4)==".pdf")
1097 gfxName=gfxName.left(gfxName.length()-4);
1099 m_t << "\\includegraphics";
1100 if (!img->width().isEmpty())
1102 m_t << "[width=" << img->width() << "]";
1104 else if (!img->height().isEmpty())
1106 m_t << "[height=" << img->height() << "]";
1108 m_t << "{" << gfxName << "}";
1109 if (img->hasCaption())
1111 m_t << "\n\\caption{";
1114 else // other format -> skip
1121 void LatexDocVisitor::visitPost(DocImage *img)
1123 if (img->type()==DocImage::Latex)
1126 m_t << "}\n"; // end mbox or caption
1127 if (img->hasCaption())
1129 m_t << "\\end{DoxyImage}\n";
1132 m_t << "\\end{DoxyImageNoCaption}\n";
1135 else // other format
1141 void LatexDocVisitor::visitPre(DocDotFile *df)
1144 startDotFile(df->file(),df->width(),df->height(),df->hasCaption());
1147 void LatexDocVisitor::visitPost(DocDotFile *df)
1150 endDotFile(df->hasCaption());
1152 void LatexDocVisitor::visitPre(DocMscFile *df)
1155 startMscFile(df->file(),df->width(),df->height(),df->hasCaption());
1158 void LatexDocVisitor::visitPost(DocMscFile *df)
1161 endMscFile(df->hasCaption());
1164 void LatexDocVisitor::visitPre(DocDiaFile *df)
1167 startDiaFile(df->file(),df->width(),df->height(),df->hasCaption());
1170 void LatexDocVisitor::visitPost(DocDiaFile *df)
1173 endDiaFile(df->hasCaption());
1175 void LatexDocVisitor::visitPre(DocLink *lnk)
1178 startLink(lnk->ref(),lnk->file(),lnk->anchor());
1181 void LatexDocVisitor::visitPost(DocLink *lnk)
1184 endLink(lnk->ref(),lnk->file(),lnk->anchor());
1187 void LatexDocVisitor::visitPre(DocRef *ref)
1190 // when ref->isSubPage()==TRUE we use ref->file() for HTML and
1191 // ref->anchor() for LaTeX/RTF
1192 if (ref->isSubPage())
1194 startLink(ref->ref(),0,ref->anchor());
1198 if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
1200 if (!ref->hasLinkText()) filter(ref->targetTitle());
1203 void LatexDocVisitor::visitPost(DocRef *ref)
1206 if (ref->isSubPage())
1208 endLink(ref->ref(),0,ref->anchor());
1212 if (!ref->file().isEmpty()) endLink(ref->ref(),ref->file(),ref->anchor());
1216 void LatexDocVisitor::visitPre(DocSecRefItem *ref)
1219 m_t << "\\item \\contentsline{section}{";
1220 static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
1223 m_t << "\\hyperlink{" << ref->file() << "_" << ref->anchor() << "}{" ;
1227 void LatexDocVisitor::visitPost(DocSecRefItem *ref)
1230 static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
1235 m_t << "}{\\ref{" << ref->file() << "_" << ref->anchor() << "}}{}" << endl;
1238 void LatexDocVisitor::visitPre(DocSecRefList *)
1241 m_t << "\\footnotesize" << endl;
1242 m_t << "\\begin{multicols}{2}" << endl;
1243 m_t << "\\begin{DoxyCompactList}" << endl;
1246 void LatexDocVisitor::visitPost(DocSecRefList *)
1249 m_t << "\\end{DoxyCompactList}" << endl;
1250 m_t << "\\end{multicols}" << endl;
1251 m_t << "\\normalsize" << endl;
1254 void LatexDocVisitor::visitPre(DocParamSect *s)
1257 bool hasInOutSpecs = s->hasInOutSpecifier();
1258 bool hasTypeSpecs = s->hasTypeSpecifier();
1261 case DocParamSect::Param:
1262 m_t << "\n\\begin{DoxyParams}";
1263 if (hasInOutSpecs && hasTypeSpecs) m_t << "[2]"; // 2 extra cols
1264 else if (hasInOutSpecs || hasTypeSpecs) m_t << "[1]"; // 1 extra col
1266 filter(theTranslator->trParameters());
1268 case DocParamSect::RetVal:
1269 m_t << "\n\\begin{DoxyRetVals}{";
1270 filter(theTranslator->trReturnValues());
1272 case DocParamSect::Exception:
1273 m_t << "\n\\begin{DoxyExceptions}{";
1274 filter(theTranslator->trExceptions());
1276 case DocParamSect::TemplateParam:
1278 filter(theTranslator->trTemplateParam()); break;
1280 m_t << "\n\\begin{DoxyTemplParams}{";
1281 filter("Template Parameters");
1289 void LatexDocVisitor::visitPost(DocParamSect *s)
1294 case DocParamSect::Param:
1295 m_t << "\\end{DoxyParams}\n";
1297 case DocParamSect::RetVal:
1298 m_t << "\\end{DoxyRetVals}\n";
1300 case DocParamSect::Exception:
1301 m_t << "\\end{DoxyExceptions}\n";
1303 case DocParamSect::TemplateParam:
1304 m_t << "\\end{DoxyTemplParams}\n";
1311 void LatexDocVisitor::visitPre(DocParamList *pl)
1314 DocParamSect::Type parentType = DocParamSect::Unknown;
1315 DocParamSect *sect = 0;
1316 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1318 parentType = ((DocParamSect*)pl->parent())->type();
1319 sect=(DocParamSect*)pl->parent();
1321 bool useTable = parentType==DocParamSect::Param ||
1322 parentType==DocParamSect::RetVal ||
1323 parentType==DocParamSect::Exception ||
1324 parentType==DocParamSect::TemplateParam;
1329 if (sect && sect->hasInOutSpecifier())
1331 if (pl->direction()!=DocParamSect::Unspecified)
1333 m_t << "\\mbox{\\tt ";
1334 if (pl->direction()==DocParamSect::In)
1338 else if (pl->direction()==DocParamSect::Out)
1342 else if (pl->direction()==DocParamSect::InOut)
1348 if (useTable) m_t << " & ";
1350 if (sect && sect->hasTypeSpecifier())
1352 QListIterator<DocNode> li(pl->paramTypes());
1355 for (li.toFirst();(type=li.current());++li)
1357 if (!first) m_t << " | "; else first=FALSE;
1358 if (type->kind()==DocNode::Kind_Word)
1360 visit((DocWord*)type);
1362 else if (type->kind()==DocNode::Kind_LinkedWord)
1364 visit((DocLinkedWord*)type);
1367 if (useTable) m_t << " & ";
1370 //QStrListIterator li(pl->parameters());
1372 QListIterator<DocNode> li(pl->parameters());
1375 for (li.toFirst();(param=li.current());++li)
1377 if (!first) m_t << ","; else first=FALSE;
1379 if (param->kind()==DocNode::Kind_Word)
1381 visit((DocWord*)param);
1383 else if (param->kind()==DocNode::Kind_LinkedWord)
1385 visit((DocLinkedWord*)param);
1400 void LatexDocVisitor::visitPost(DocParamList *pl)
1403 DocParamSect::Type parentType = DocParamSect::Unknown;
1404 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1406 parentType = ((DocParamSect*)pl->parent())->type();
1408 bool useTable = parentType==DocParamSect::Param ||
1409 parentType==DocParamSect::RetVal ||
1410 parentType==DocParamSect::Exception ||
1411 parentType==DocParamSect::TemplateParam;
1414 m_t << "\\\\" << endl
1415 << "\\hline" << endl;
1419 void LatexDocVisitor::visitPre(DocXRefItem *x)
1422 if (x->title().isEmpty()) return;
1423 m_t << "\\begin{DoxyRefDesc}{";
1426 bool anonymousEnum = x->file()=="@";
1428 if (Config_getBool("PDF_HYPERLINKS") && !anonymousEnum)
1430 m_t << "\\hyperlink{" << stripPath(x->file()) << "_" << x->anchor() << "}{";
1442 void LatexDocVisitor::visitPost(DocXRefItem *x)
1445 if (x->title().isEmpty()) return;
1446 m_t << "\\end{DoxyRefDesc}" << endl;
1449 void LatexDocVisitor::visitPre(DocInternalRef *ref)
1452 startLink(0,ref->file(),ref->anchor());
1455 void LatexDocVisitor::visitPost(DocInternalRef *ref)
1458 endLink(0,ref->file(),ref->anchor());
1461 void LatexDocVisitor::visitPre(DocCopy *)
1465 void LatexDocVisitor::visitPost(DocCopy *)
1469 void LatexDocVisitor::visitPre(DocText *)
1473 void LatexDocVisitor::visitPost(DocText *)
1477 void LatexDocVisitor::visitPre(DocHtmlBlockQuote *)
1480 m_t << "\\begin{quote}" << endl;
1483 void LatexDocVisitor::visitPost(DocHtmlBlockQuote *)
1486 m_t << "\\end{quote}" << endl;
1489 void LatexDocVisitor::visitPre(DocVhdlFlow *)
1494 void LatexDocVisitor::visitPost(DocVhdlFlow *)
1499 void LatexDocVisitor::visitPre(DocParBlock *)
1504 void LatexDocVisitor::visitPost(DocParBlock *)
1509 void LatexDocVisitor::filter(const char *str)
1511 filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem);
1514 void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
1516 if (ref.isEmpty() && Config_getBool("PDF_HYPERLINKS")) // internal PDF link
1518 if (ref.isEmpty()) {
1519 m_t << "\\hyperlink{";
1520 if (!file.isEmpty()) m_t << stripPath(file);
1521 if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
1522 if (!anchor.isEmpty()) m_t << anchor;
1529 if ((dest=Doxygen::tagDestinationDict[ref])) m_t << *dest << "/";
1530 if (!file.isEmpty()) m_t << file << Doxygen::htmlFileExtension;
1531 if (!anchor.isEmpty()) m_t << "#" << anchor;
1535 else if (ref.isEmpty()) // internal non-PDF link
1537 m_t << "\\doxyref{";
1539 else // external link
1545 void LatexDocVisitor::endLink(const QCString &ref,const QCString &file,const QCString &anchor)
1548 if (ref.isEmpty() && !Config_getBool("PDF_HYPERLINKS"))
1551 filter(theTranslator->trPageAbbreviation());
1552 m_t << "}{" << file;
1553 if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
1554 m_t << anchor << "}";
1558 void LatexDocVisitor::pushEnabled()
1560 m_enabled.push(new bool(m_hide));
1563 void LatexDocVisitor::popEnabled()
1565 bool *v=m_enabled.pop();
1571 void LatexDocVisitor::startDotFile(const QCString &fileName,
1572 const QCString &width,
1573 const QCString &height,
1577 QCString baseName=fileName;
1579 if ((i=baseName.findRev('/'))!=-1)
1581 baseName=baseName.right(baseName.length()-i-1);
1583 if ((i=baseName.find('.'))!=-1)
1585 baseName=baseName.left(i);
1587 baseName.prepend("dot_");
1588 QCString outDir = Config_getString("LATEX_OUTPUT");
1589 QCString name = fileName;
1590 writeDotGraphFromFile(name,outDir,baseName,EPS);
1593 m_t << "\n\\begin{DoxyImage}\n";
1597 m_t << "\n\\begin{DoxyImageNoCaption}\n"
1600 m_t << "\\includegraphics";
1601 if (!width.isEmpty())
1603 m_t << "[width=" << width << "]";
1605 else if (!height.isEmpty())
1607 m_t << "[height=" << height << "]";
1611 m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
1613 m_t << "{" << baseName;
1614 //if (Config_getBool("USE_PDFLATEX"))
1626 m_t << "\n\\caption{";
1630 void LatexDocVisitor::endDotFile(bool hasCaption)
1633 m_t << "}\n"; // end caption or mbox
1636 m_t << "\\end{DoxyImage}\n";
1640 m_t << "\\end{DoxyImageNoCaption}\n";
1644 void LatexDocVisitor::startMscFile(const QCString &fileName,
1645 const QCString &width,
1646 const QCString &height,
1650 QCString baseName=fileName;
1652 if ((i=baseName.findRev('/'))!=-1)
1654 baseName=baseName.right(baseName.length()-i-1);
1656 if ((i=baseName.find('.'))!=-1)
1658 baseName=baseName.left(i);
1660 baseName.prepend("msc_");
1662 QCString outDir = Config_getString("LATEX_OUTPUT");
1663 writeMscGraphFromFile(fileName,outDir,baseName,MSC_EPS);
1666 m_t << "\n\\begin{DoxyImage}\n";
1670 m_t << "\n\\begin{DoxyImageNoCaption}\n"
1673 m_t << "\\includegraphics";
1674 if (!width.isEmpty())
1676 m_t << "[width=" << width << "]";
1678 else if (!height.isEmpty())
1680 m_t << "[height=" << height << "]";
1684 m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
1686 m_t << "{" << baseName;
1687 //if (Config_getBool("USE_PDFLATEX"))
1699 m_t << "\n\\caption{";
1703 void LatexDocVisitor::endMscFile(bool hasCaption)
1706 m_t << "}\n"; // end caption or mbox
1709 m_t << "\\end{DoxyImage}\n";
1713 m_t << "\\end{DoxyImageNoCaption}\n";
1718 void LatexDocVisitor::writeMscFile(const QCString &baseName)
1720 QCString shortName = baseName;
1722 if ((i=shortName.findRev('/'))!=-1)
1724 shortName=shortName.right(shortName.length()-i-1);
1726 QCString outDir = Config_getString("LATEX_OUTPUT");
1727 writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_EPS);
1728 m_t << "\n\\begin{DoxyImageNoCaption}"
1729 " \\mbox{\\includegraphics";
1730 m_t << "{" << shortName << "}";
1731 m_t << "}\n"; // end mbox
1732 m_t << "\\end{DoxyImageNoCaption}\n";
1735 void LatexDocVisitor::startDiaFile(const QCString &fileName,
1736 const QCString &width,
1737 const QCString &height,
1741 QCString baseName=fileName;
1743 if ((i=baseName.findRev('/'))!=-1)
1745 baseName=baseName.right(baseName.length()-i-1);
1747 if ((i=baseName.find('.'))!=-1)
1749 baseName=baseName.left(i);
1751 baseName.prepend("dia_");
1753 QCString outDir = Config_getString("LATEX_OUTPUT");
1754 writeDiaGraphFromFile(fileName,outDir,baseName,DIA_EPS);
1757 m_t << "\n\\begin{DoxyImage}\n";
1761 m_t << "\n\\begin{DoxyImageNoCaption}\n"
1764 m_t << "\\includegraphics";
1765 if (!width.isEmpty())
1767 m_t << "[width=" << width << "]";
1769 else if (!height.isEmpty())
1771 m_t << "[height=" << height << "]";
1775 m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
1777 m_t << "{" << baseName;
1778 //if (Config_getBool("USE_PDFLATEX"))
1790 m_t << "\n\\caption{";
1794 void LatexDocVisitor::endDiaFile(bool hasCaption)
1797 m_t << "}\n"; // end caption or mbox
1800 m_t << "\\end{DoxyImage}\n";
1804 m_t << "\\end{DoxyImageNoCaption}\n";
1809 void LatexDocVisitor::writeDiaFile(const QCString &baseName)
1811 QCString shortName = baseName;
1813 if ((i=shortName.findRev('/'))!=-1)
1815 shortName=shortName.right(shortName.length()-i-1);
1817 QCString outDir = Config_getString("LATEX_OUTPUT");
1818 writeDiaGraphFromFile(baseName+".dia",outDir,shortName,DIA_EPS);
1819 m_t << "\n\\begin{DoxyImageNoCaption}"
1820 " \\mbox{\\includegraphics";
1821 m_t << "{" << shortName << "}";
1822 m_t << "}\n"; // end mbox
1823 m_t << "\\end{DoxyImageNoCaption}\n";