1 /******************************************************************************
6 * Copyright (C) 1997-2012 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 <qfileinfo.h>
19 #include "latexdocvisitor.h"
20 #include "docparser.h"
23 #include "outputgen.h"
27 #include "parserintf.h"
29 #include "htmlattrib.h"
32 static QCString escapeLabelName(const char *s)
41 case '%': result+="\\%"; break;
42 case '|': result+="\\texttt{\"|}"; break;
43 case '!': result+="\"!"; break;
50 const int maxLevels=5;
51 static const char *secLabels[maxLevels] =
52 { "section","subsection","subsubsection","paragraph","subparagraph" };
54 static const char *getSectionName(int level)
56 static bool compactLatex = Config_getBool("COMPACT_LATEX");
58 if (compactLatex) l++;
59 if (Doxygen::insideMainPage) l--;
60 return secLabels[QMIN(maxLevels-1,l)];
63 QCString LatexDocVisitor::escapeMakeIndexChars(const char *s)
67 char str[2]; str[1]=0;
73 case '!': m_t << "\"!"; break;
74 case '"': m_t << "\"\""; break;
75 case '@': m_t << "\"@"; break;
76 case '|': m_t << "\\texttt{\"|}"; break;
77 case '[': m_t << "["; break;
78 case ']': m_t << "]"; break;
79 default: str[0]=c; filter(str); break;
86 LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci,
87 const char *langExt,bool insideTabbing)
88 : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE),
89 m_insideItem(FALSE), m_hide(FALSE), m_insideTabbing(insideTabbing),
90 m_insideTable(FALSE), m_langExt(langExt), m_currentColumn(0),
91 m_inRowspan(FALSE), m_inColspan(FALSE)
93 m_rowSpans.setAutoDelete(TRUE);
96 //--------------------------------------
97 // visitor functions for leaf nodes
98 //--------------------------------------
100 void LatexDocVisitor::visit(DocWord *w)
106 void LatexDocVisitor::visit(DocLinkedWord *w)
109 startLink(w->ref(),w->file(),w->anchor());
111 endLink(w->ref(),w->file(),w->anchor());
114 void LatexDocVisitor::visit(DocWhiteSpace *w)
127 void LatexDocVisitor::visit(DocSymbol *s)
132 case DocSymbol::BSlash: m_t << "\\textbackslash{}"; break;
133 case DocSymbol::At: m_t << "@"; break;
134 case DocSymbol::Less: if (m_insidePre) m_t << "<"; else m_t << "$<$";
136 case DocSymbol::Greater: if (m_insidePre) m_t << ">"; else m_t << "$>$"; break;
137 case DocSymbol::Amp: m_t << "\\&"; break;
138 case DocSymbol::Dollar: m_t << "\\$"; break;
139 case DocSymbol::Hash: m_t << "\\#"; break;
140 case DocSymbol::DoubleColon: m_t << "::"; break;
141 case DocSymbol::Percent: m_t << "\\%"; break;
142 case DocSymbol::Pipe: m_t << "$|$"; break;
143 case DocSymbol::Copy: m_t << "\\copyright"; break;
144 case DocSymbol::Tm: m_t << "\\texttrademark"; break;
145 case DocSymbol::Reg: m_t << "\\textregistered"; break;
146 case DocSymbol::Apos: m_t << "'"; break;
147 case DocSymbol::Quot: m_t << "\""; break;
148 case DocSymbol::Lsquo: m_t << "`"; break;
149 case DocSymbol::Rsquo: m_t << "'"; break;
150 case DocSymbol::Ldquo: m_t << "``"; break;
151 case DocSymbol::Rdquo: m_t << "''"; break;
152 case DocSymbol::Ndash: m_t << "--"; break;
153 case DocSymbol::Mdash: m_t << "---"; break;
155 if (s->letter()=='i')
158 m_t << "\\\"{" << s->letter() << "}";
160 case DocSymbol::Acute:
161 if (s->letter()=='i')
164 m_t << "\\'{" << s->letter() << "}";
166 case DocSymbol::Grave:
167 if (s->letter()=='i')
170 m_t << "\\`{" << s->letter() << "}";
172 case DocSymbol::Circ:
173 if (s->letter()=='i')
176 m_t << "\\^{" << s->letter() << "}";
178 case DocSymbol::Slash: if (tolower(s->letter())=='o')
179 m_t << "{\\" << s->letter() << "}";
183 case DocSymbol::Tilde: m_t << "\\~{" << s->letter() << "}"; break;
184 case DocSymbol::Szlig: m_t << "{\\ss}"; break;
185 case DocSymbol::Cedil: m_t << "\\c{" << s->letter() << "}"; break;
186 case DocSymbol::Ring: m_t << "\\" << s->letter() << s->letter(); break;
187 case DocSymbol::Nbsp: m_t << "~"; break;
188 case DocSymbol::AElig: m_t << "{\\AE}"; break;
189 case DocSymbol::Aelig: m_t << "{\\ae}"; break;
190 case DocSymbol::GrkGamma: m_t << "{$\\Gamma$}"; break;
191 case DocSymbol::GrkDelta: m_t << "{$\\Delta$}"; break;
192 case DocSymbol::GrkTheta: m_t << "{$\\Theta$}"; break;
193 case DocSymbol::GrkLambda: m_t << "{$\\Lambda$}"; break;
194 case DocSymbol::GrkXi: m_t << "{$\\Xi$}"; break;
195 case DocSymbol::GrkPi: m_t << "{$\\Pi$}"; break;
196 case DocSymbol::GrkSigma: m_t << "{$\\Sigma$}"; break;
197 case DocSymbol::GrkUpsilon: m_t << "{$\\Upsilon$}"; break;
198 case DocSymbol::GrkPhi: m_t << "{$\\Phi$}"; break;
199 case DocSymbol::GrkPsi: m_t << "{$\\Psi$}"; break;
200 case DocSymbol::GrkOmega: m_t << "{$\\Omega$}"; break;
201 case DocSymbol::Grkalpha: m_t << "{$\\alpha$}"; break;
202 case DocSymbol::Grkbeta: m_t << "{$\\beta$}"; break;
203 case DocSymbol::Grkgamma: m_t << "{$\\gamma$}"; break;
204 case DocSymbol::Grkdelta: m_t << "{$\\delta$}"; break;
205 case DocSymbol::Grkepsilon: m_t << "{$\\varepsilon$}"; break;
206 case DocSymbol::Grkzeta: m_t << "{$\\zeta$}"; break;
207 case DocSymbol::Grketa: m_t << "{$\\eta$}"; break;
208 case DocSymbol::Grktheta: m_t << "{$\\theta$}"; break;
209 case DocSymbol::Grkiota: m_t << "{$\\iota$}"; break;
210 case DocSymbol::Grkkappa: m_t << "{$\\kappa$}"; break;
211 case DocSymbol::Grklambda: m_t << "{$\\lambda$}"; break;
212 case DocSymbol::Grkmu: m_t << "{$\\mu$}"; break;
213 case DocSymbol::Grknu: m_t << "{$\\nu$}"; break;
214 case DocSymbol::Grkxi: m_t << "{$\\xi$}"; break;
215 case DocSymbol::Grkpi: m_t << "{$\\pi$}"; break;
216 case DocSymbol::Grkrho: m_t << "{$\\rho$}"; break;
217 case DocSymbol::Grksigma: m_t << "{$\\sigma$}"; break;
218 case DocSymbol::Grktau: m_t << "{$\\tau$}"; break;
219 case DocSymbol::Grkupsilon: m_t << "{$\\upsilon$}"; break;
220 case DocSymbol::Grkphi: m_t << "{$\\varphi$}"; break;
221 case DocSymbol::Grkchi: m_t << "{$\\chi$}"; break;
222 case DocSymbol::Grkpsi: m_t << "{$\\psi$}"; break;
223 case DocSymbol::Grkomega: m_t << "{$\\omega$}"; break;
224 case DocSymbol::Grkvarsigma: m_t << "{$\\varsigma$}"; break;
225 case DocSymbol::Section: m_t << "{$\\S$}"; break;
226 case DocSymbol::Degree: m_t << "\\textdegree"; break;
227 case DocSymbol::Prime: m_t << "'"; break;
228 case DocSymbol::DoublePrime: m_t << "''"; break;
229 case DocSymbol::Infinity: m_t << "{$\\infty$}"; break;
230 case DocSymbol::EmptySet: m_t << "{$\\emptyset$}"; break;
231 case DocSymbol::PlusMinus: m_t << "{$\\pm$}"; break;
232 case DocSymbol::Times: m_t << "{$\\times$}"; break;
233 case DocSymbol::Minus: m_t << "-"; break;
234 case DocSymbol::CenterDot: m_t << "{$\\cdot$}"; break;
235 case DocSymbol::Partial: m_t << "{$\\partial$}"; break;
236 case DocSymbol::Nabla: m_t << "{$\\nabla$}"; break;
237 case DocSymbol::SquareRoot: m_t << "{$\\surd$}"; break;
238 case DocSymbol::Perpendicular: m_t << "{$\\perp$}"; break;
239 case DocSymbol::Sum: m_t << "{$\\sum$}"; break;
240 case DocSymbol::Integral: m_t << "{$\\int$}"; break;
241 case DocSymbol::Product: m_t << "{$\\prod$}"; break;
242 case DocSymbol::Similar: m_t << "{$\\sim$}"; break;
243 case DocSymbol::Approx: m_t << "{$\\approx$}"; break;
244 case DocSymbol::NotEqual: m_t << "{$\\ne$}"; break;
245 case DocSymbol::Equivalent: m_t << "{$\\equiv$}"; break;
246 case DocSymbol::Proportional: m_t << "{$\\propto$}"; break;
247 case DocSymbol::LessEqual: m_t << "{$\\le$}"; break;
248 case DocSymbol::GreaterEqual: m_t << "{$\\ge$}"; break;
249 case DocSymbol::LeftArrow: m_t << "{$\\leftarrow$}"; break;
250 case DocSymbol::RightArrow: m_t << "{$\\rightarrow$}"; break;
251 case DocSymbol::SetIn: m_t << "{$\\in$}"; break;
252 case DocSymbol::SetNotIn: m_t << "{$\\notin$}"; break;
253 case DocSymbol::LeftCeil: m_t << "{$\\lceil$}"; break;
254 case DocSymbol::RightCeil: m_t << "{$\\rceil$}"; break;
255 case DocSymbol::LeftFloor: m_t << "{$\\lfloor$}"; break;
256 case DocSymbol::RightFloor: m_t << "{$\\rfloor$}"; break;
258 err("error: unknown symbol found\n");
262 void LatexDocVisitor::visit(DocURL *u)
265 if (Config_getBool("PDF_HYPERLINKS"))
268 if (u->isEmail()) m_t << "mailto:";
269 m_t << u->url() << "}";
276 void LatexDocVisitor::visit(DocLineBreak *)
279 if (m_insideTable) m_t << "\\newline\n";
280 else m_t << "\\par\n";
283 void LatexDocVisitor::visit(DocHorRuler *)
289 void LatexDocVisitor::visit(DocStyleChange *s)
294 case DocStyleChange::Bold:
295 if (s->enable()) m_t << "{\\bfseries "; else m_t << "}";
297 case DocStyleChange::Italic:
298 if (s->enable()) m_t << "{\\itshape "; else m_t << "}";
300 case DocStyleChange::Code:
301 if (s->enable()) m_t << "{\\ttfamily "; else m_t << "}";
303 case DocStyleChange::Subscript:
304 if (s->enable()) m_t << "$_{\\mbox{"; else m_t << "}}$ ";
306 case DocStyleChange::Superscript:
307 if (s->enable()) m_t << "$^{\\mbox{"; else m_t << "}}$ ";
309 case DocStyleChange::Center:
310 if (s->enable()) m_t << "\\begin{center}"; else m_t << "\\end{center} ";
312 case DocStyleChange::Small:
313 if (s->enable()) m_t << "\n\\footnotesize "; else m_t << "\n\\normalsize ";
315 case DocStyleChange::Preformatted:
318 m_t << "\n\\begin{DoxyPre}";
324 m_t << "\\end{DoxyPre}\n";
327 case DocStyleChange::Div: /* HTML only */ break;
328 case DocStyleChange::Span: /* HTML only */ break;
332 void LatexDocVisitor::visit(DocVerbatim *s)
335 QCString lang = m_langExt;
336 if (!s->language().isEmpty()) // explicit language setting
338 lang = s->language();
342 case DocVerbatim::Code:
344 m_t << "\n\\begin{DoxyCode}\n";
345 Doxygen::parserManager->getParser(lang)
346 ->parseCode(m_ci,s->context(),s->text(),
347 s->isExample(),s->exampleFile());
348 m_t << "\\end{DoxyCode}\n";
351 case DocVerbatim::Verbatim:
352 m_t << "\\begin{DoxyVerb}";
354 m_t << "\\end{DoxyVerb}\n";
356 case DocVerbatim::HtmlOnly:
357 case DocVerbatim::XmlOnly:
358 case DocVerbatim::ManOnly:
359 case DocVerbatim::RtfOnly:
362 case DocVerbatim::LatexOnly:
365 case DocVerbatim::Dot:
367 static int dotindex = 1;
368 QCString fileName(4096);
370 fileName.sprintf("%s%d%s",
371 (Config_getString("LATEX_OUTPUT")+"/inline_dotgraph_").data(),
375 QFile file(fileName);
376 if (!file.open(IO_WriteOnly))
378 err("Could not open file %s for writing\n",fileName.data());
380 file.writeBlock( s->text(), s->text().length() );
383 m_t << "\\begin{center}\n";
384 startDotFile(fileName,"","",FALSE);
386 m_t << "\\end{center}\n";
388 if (Config_getBool("DOT_CLEANUP")) file.remove();
391 case DocVerbatim::Msc:
393 static int mscindex = 1;
394 QCString baseName(4096);
396 baseName.sprintf("%s%d",
397 (Config_getString("LATEX_OUTPUT")+"/inline_mscgraph_").data(),
400 QFile file(baseName+".msc");
401 if (!file.open(IO_WriteOnly))
403 err("Could not open file %s.msc for writing\n",baseName.data());
405 QCString text = "msc {";
408 file.writeBlock( text, text.length() );
411 m_t << "\\begin{center}\n";
412 writeMscFile(baseName);
413 m_t << "\\end{center}\n";
415 if (Config_getBool("DOT_CLEANUP")) file.remove();
421 void LatexDocVisitor::visit(DocAnchor *anc)
424 m_t << "\\label{" << anc->file() << "_" << anc->anchor() << "}%" << endl;
425 if (!anc->file().isEmpty() && Config_getBool("PDF_HYPERLINKS"))
427 m_t << "\\hypertarget{" << anc->file() << "_" << anc->anchor()
432 void LatexDocVisitor::visit(DocInclude *inc)
437 case DocInclude::IncWithLines:
439 m_t << "\n\\begin{DoxyCodeInclude}\n";
440 QFileInfo cfi( inc->file() );
441 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
442 Doxygen::parserManager->getParser(inc->extension())
443 ->parseCode(m_ci,inc->context(),
446 inc->exampleFile(), &fd);
447 m_t << "\\end{DoxyCodeInclude}" << endl;
450 case DocInclude::Include:
451 m_t << "\n\\begin{DoxyCodeInclude}\n";
452 Doxygen::parserManager->getParser(inc->extension())
453 ->parseCode(m_ci,inc->context(),
454 inc->text(),inc->isExample(),
456 m_t << "\\end{DoxyCodeInclude}\n";
458 case DocInclude::DontInclude:
460 case DocInclude::HtmlInclude:
462 case DocInclude::VerbInclude:
463 m_t << "\n\\begin{DoxyVerbInclude}\n";
465 m_t << "\\end{DoxyVerbInclude}\n";
467 case DocInclude::Snippet:
469 m_t << "\n\\begin{DoxyCodeInclude}\n";
470 Doxygen::parserManager->getParser(inc->extension())
473 extractBlock(inc->text(),inc->blockId()),
477 m_t << "\\end{DoxyCodeInclude}" << endl;
483 void LatexDocVisitor::visit(DocIncOperator *op)
485 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
486 // op->type(),op->isFirst(),op->isLast(),op->text().data());
489 if (!m_hide) m_t << "\n\\begin{DoxyCodeInclude}\n";
493 if (op->type()!=DocIncOperator::Skip)
498 Doxygen::parserManager->getParser(m_langExt)
499 ->parseCode(m_ci,op->context(),op->text(),
500 op->isExample(),op->exampleFile());
508 if (!m_hide) m_t << "\n\\end{DoxyCodeInclude}\n";
512 if (!m_hide) m_t << endl;
516 void LatexDocVisitor::visit(DocFormula *f)
522 void LatexDocVisitor::visit(DocIndexEntry *i)
525 m_t << "\\index{" << escapeLabelName(i->entry()) << "@{";
526 escapeMakeIndexChars(i->entry());
530 void LatexDocVisitor::visit(DocSimpleSectSep *)
534 void LatexDocVisitor::visit(DocCite *cite)
537 if (!cite->file().isEmpty())
539 //startLink(cite->ref(),cite->file(),cite->anchor());
540 QCString anchor = cite->anchor();
541 anchor = anchor.mid(CiteConsts::anchorPrefix.length()); // strip prefix
542 m_t << "\\cite{" << anchor << "}";
546 m_t << "{\\bfseries [";
547 filter(cite->text());
552 //--------------------------------------
553 // visitor functions for compound nodes
554 //--------------------------------------
556 void LatexDocVisitor::visitPre(DocAutoList *l)
561 m_t << "\n\\begin{DoxyEnumerate}";
565 m_t << "\n\\begin{DoxyItemize}";
569 void LatexDocVisitor::visitPost(DocAutoList *l)
574 m_t << "\n\\end{DoxyEnumerate}";
578 m_t << "\n\\end{DoxyItemize}";
582 void LatexDocVisitor::visitPre(DocAutoListItem *)
588 void LatexDocVisitor::visitPost(DocAutoListItem *)
592 void LatexDocVisitor::visitPre(DocPara *)
596 void LatexDocVisitor::visitPost(DocPara *p)
599 if (!p->isLast() && // omit <p> for last paragraph
600 !(p->parent() && // and for parameter sections
601 p->parent()->kind()==DocNode::Kind_ParamSect
603 ) m_t << endl << endl;
606 void LatexDocVisitor::visitPre(DocRoot *)
610 void LatexDocVisitor::visitPost(DocRoot *)
614 void LatexDocVisitor::visitPre(DocSimpleSect *s)
619 case DocSimpleSect::See:
620 m_t << "\\begin{DoxySeeAlso}{";
621 filter(theTranslator->trSeeAlso());
623 case DocSimpleSect::Return:
624 m_t << "\\begin{DoxyReturn}{";
625 filter(theTranslator->trReturns());
627 case DocSimpleSect::Author:
628 m_t << "\\begin{DoxyAuthor}{";
629 filter(theTranslator->trAuthor(TRUE,TRUE));
631 case DocSimpleSect::Authors:
632 m_t << "\\begin{DoxyAuthor}{";
633 filter(theTranslator->trAuthor(TRUE,FALSE));
635 case DocSimpleSect::Version:
636 m_t << "\\begin{DoxyVersion}{";
637 filter(theTranslator->trVersion());
639 case DocSimpleSect::Since:
640 m_t << "\\begin{DoxySince}{";
641 filter(theTranslator->trSince());
643 case DocSimpleSect::Date:
644 m_t << "\\begin{DoxyDate}{";
645 filter(theTranslator->trDate());
647 case DocSimpleSect::Note:
648 m_t << "\\begin{DoxyNote}{";
649 filter(theTranslator->trNote());
651 case DocSimpleSect::Warning:
652 m_t << "\\begin{DoxyWarning}{";
653 filter(theTranslator->trWarning());
655 case DocSimpleSect::Pre:
656 m_t << "\\begin{DoxyPrecond}{";
657 filter(theTranslator->trPrecondition());
659 case DocSimpleSect::Post:
660 m_t << "\\begin{DoxyPostcond}{";
661 filter(theTranslator->trPostcondition());
663 case DocSimpleSect::Copyright:
664 m_t << "\\begin{DoxyCopyright}{";
665 filter(theTranslator->trCopyright());
667 case DocSimpleSect::Invar:
668 m_t << "\\begin{DoxyInvariant}{";
669 filter(theTranslator->trInvariant());
671 case DocSimpleSect::Remark:
672 m_t << "\\begin{DoxyRemark}{";
673 filter(theTranslator->trRemarks());
675 case DocSimpleSect::Attention:
676 m_t << "\\begin{DoxyAttention}{";
677 filter(theTranslator->trAttention());
679 case DocSimpleSect::User:
680 m_t << "\\begin{DoxyParagraph}{";
682 case DocSimpleSect::Rcs:
683 m_t << "\\begin{DoxyParagraph}{";
685 case DocSimpleSect::Unknown: break;
688 // special case 1: user defined title
689 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
699 void LatexDocVisitor::visitPost(DocSimpleSect *s)
704 case DocSimpleSect::See:
705 m_t << "\n\\end{DoxySeeAlso}\n";
707 case DocSimpleSect::Return:
708 m_t << "\n\\end{DoxyReturn}\n";
710 case DocSimpleSect::Author:
711 m_t << "\n\\end{DoxyAuthor}\n";
713 case DocSimpleSect::Authors:
714 m_t << "\n\\end{DoxyAuthor}\n";
716 case DocSimpleSect::Version:
717 m_t << "\n\\end{DoxyVersion}\n";
719 case DocSimpleSect::Since:
720 m_t << "\n\\end{DoxySince}\n";
722 case DocSimpleSect::Date:
723 m_t << "\n\\end{DoxyDate}\n";
725 case DocSimpleSect::Note:
726 m_t << "\n\\end{DoxyNote}\n";
728 case DocSimpleSect::Warning:
729 m_t << "\n\\end{DoxyWarning}\n";
731 case DocSimpleSect::Pre:
732 m_t << "\n\\end{DoxyPrecond}\n";
734 case DocSimpleSect::Post:
735 m_t << "\n\\end{DoxyPostcond}\n";
737 case DocSimpleSect::Copyright:
738 m_t << "\n\\end{DoxyCopyright}\n";
740 case DocSimpleSect::Invar:
741 m_t << "\n\\end{DoxyInvariant}\n";
743 case DocSimpleSect::Remark:
744 m_t << "\n\\end{DoxyRemark}\n";
746 case DocSimpleSect::Attention:
747 m_t << "\n\\end{DoxyAttention}\n";
749 case DocSimpleSect::User:
750 m_t << "\n\\end{DoxyParagraph}\n";
752 case DocSimpleSect::Rcs:
753 m_t << "\n\\end{DoxyParagraph}\n";
760 void LatexDocVisitor::visitPre(DocTitle *)
764 void LatexDocVisitor::visitPost(DocTitle *)
771 void LatexDocVisitor::visitPre(DocSimpleList *)
774 m_t << "\\begin{DoxyItemize}" << endl;
777 void LatexDocVisitor::visitPost(DocSimpleList *)
780 m_t << "\\end{DoxyItemize}" << endl;
783 void LatexDocVisitor::visitPre(DocSimpleListItem *)
789 void LatexDocVisitor::visitPost(DocSimpleListItem *)
793 void LatexDocVisitor::visitPre(DocSection *s)
796 if (Config_getBool("PDF_HYPERLINKS"))
798 m_t << "\\hypertarget{" << s->file() << "_" << s->anchor() << "}{}";
800 m_t << "\\" << getSectionName(s->level()) << "{";
801 filter(convertCharEntitiesToUTF8(s->title().data()));
802 m_t << "}\\label{" << s->file() << "_" << s->anchor() << "}" << endl;
805 void LatexDocVisitor::visitPost(DocSection *)
809 void LatexDocVisitor::visitPre(DocHtmlList *s)
812 if (s->type()==DocHtmlList::Ordered)
813 m_t << "\n\\begin{DoxyEnumerate}";
815 m_t << "\n\\begin{DoxyItemize}";
818 void LatexDocVisitor::visitPost(DocHtmlList *s)
821 if (s->type()==DocHtmlList::Ordered)
822 m_t << "\n\\end{DoxyEnumerate}";
824 m_t << "\n\\end{DoxyItemize}";
827 void LatexDocVisitor::visitPre(DocHtmlListItem *)
833 void LatexDocVisitor::visitPost(DocHtmlListItem *)
837 //void LatexDocVisitor::visitPre(DocHtmlPre *)
839 // m_t << "\\small\\begin{alltt}";
843 //void LatexDocVisitor::visitPost(DocHtmlPre *)
845 // m_insidePre=FALSE;
846 // m_t << "\\end{alltt}\\normalsize " << endl;
849 void LatexDocVisitor::visitPre(DocHtmlDescList *dl)
852 QCString val = dl->attribs().find("class");
855 m_t << "\n\\begin{DoxyRefList}";
859 m_t << "\n\\begin{DoxyDescription}";
863 void LatexDocVisitor::visitPost(DocHtmlDescList *dl)
866 QCString val = dl->attribs().find("class");
869 m_t << "\n\\end{DoxyRefList}";
873 m_t << "\n\\end{DoxyDescription}";
877 void LatexDocVisitor::visitPre(DocHtmlDescTitle *)
884 void LatexDocVisitor::visitPost(DocHtmlDescTitle *)
891 void LatexDocVisitor::visitPre(DocHtmlDescData *)
895 void LatexDocVisitor::visitPost(DocHtmlDescData *)
899 void LatexDocVisitor::visitPre(DocHtmlTable *t)
906 m_t << "\\begin{table}[h]";
908 m_t << "\\begin{TabularC}{" << t->numColumns() << "}\n";
909 m_numCols = t->numColumns();
913 void LatexDocVisitor::visitPost(DocHtmlTable *t)
919 m_t << "\\end{table}\n";
923 m_t << "\\end{TabularC}\n";
927 void LatexDocVisitor::visitPre(DocHtmlCaption *)
930 m_t << "\\end{TabularC}\n\\centering\n\\caption{";
933 void LatexDocVisitor::visitPost(DocHtmlCaption *)
939 void LatexDocVisitor::visitPre(DocHtmlRow *r)
942 if (r->isHeading()) m_t << "\\rowcolor{lightgray}";
945 void LatexDocVisitor::visitPost(DocHtmlRow *row)
949 int c=m_currentColumn;
950 while (c<=m_numCols) // end of row while inside a row span?
953 for (i=0;i<m_rowSpans.count();i++)
955 ActiveRowSpan *span = m_rowSpans.at(i);
956 //printf(" founc row span: column=%d rs=%d cs=%d rowIdx=%d cell->rowIdx=%d\n",
957 // span->column, span->rowSpan,span->colSpan,row->rowIndex(),span->cell->rowIndex());
958 if (span->rowSpan>0 && span->column==c && // we are at a cell in a row span
959 row->rowIndex()>span->cell->rowIndex() // but not the row that started the span
963 if (span->colSpan>1) // row span is also part of a column span
965 m_t << "\\multicolumn{" << span->colSpan << "}{";
966 m_t << "p{(\\linewidth-\\tabcolsep*"
967 << m_numCols << "-\\arrayrulewidth*"
968 << row->visibleCells() << ")*"
969 << span->colSpan <<"/"<< m_numCols << "}|}{}";
971 else // solitary row span
973 m_t << "\\multicolumn{1}{c|}{}";
984 for (i=0;i<m_rowSpans.count();i++)
986 ActiveRowSpan *span = m_rowSpans.at(i);
987 if (span->rowSpan>0) span->rowSpan--;
988 if (span->rowSpan<=0)
992 else if (span->column>col)
994 m_t << "\\cline{" << col << "-" << (span->column-1) << "}";
995 col = span->column+span->colSpan;
999 col = span->column+span->colSpan;
1003 if (col <= m_numCols)
1005 m_t << "\\cline{" << col << "-" << m_numCols << "}";
1011 void LatexDocVisitor::visitPre(DocHtmlCell *c)
1015 DocHtmlRow *row = 0;
1016 if (c->parent() && c->parent()->kind()==DocNode::Kind_HtmlRow)
1018 row = (DocHtmlRow*)c->parent();
1023 //Skip columns that span from above.
1025 for (i=0;i<m_rowSpans.count();i++)
1027 ActiveRowSpan *span = m_rowSpans.at(i);
1028 if (span->rowSpan>0 && span->column==m_currentColumn)
1030 if (row && span->colSpan>1)
1032 m_t << "\\multicolumn{" << span->colSpan << "}{";
1033 if (m_currentColumn /*c->columnIndex()*/==1) // add extra | for first column
1037 m_t << "p{(\\linewidth-\\tabcolsep*"
1038 << m_numCols << "-\\arrayrulewidth*"
1039 << row->visibleCells() << ")*"
1040 << span->colSpan <<"/"<< m_numCols << "}|}{}";
1041 m_currentColumn+=span->colSpan;
1052 QMap<int, int>::Iterator it = m_rowspanIndices.find(m_currentColumn);
1053 if (it!=m_rowspanIndices.end() && it.data()>0)
1061 int cs = c->colSpan();
1065 m_t << "\\multicolumn{" << cs << "}{";
1066 if (c->columnIndex()==1) // add extra | for first column
1070 m_t << "p{(\\linewidth-\\tabcolsep*"
1071 << m_numCols << "-\\arrayrulewidth*"
1072 << row->visibleCells() << ")*"
1073 << cs <<"/"<< m_numCols << "}|}{";
1074 if (c->isHeading()) m_t << "\\cellcolor{lightgray}";
1076 int rs = c->rowSpan();
1080 //m_rowspanIndices[m_currentColumn] = rs;
1081 m_rowSpans.append(new ActiveRowSpan(c,rs,cs,m_currentColumn));
1082 m_t << "\\multirow{" << rs << "}{\\linewidth}{";
1084 int a = c->alignment();
1085 if (a==DocHtmlCell::Center)
1087 m_t << "\\PBS\\centering ";
1089 else if (a==DocHtmlCell::Right)
1091 m_t << "\\PBS\\raggedleft ";
1099 m_currentColumn+=cs-1;
1103 void LatexDocVisitor::visitPost(DocHtmlCell *c)
1112 m_inRowspan = FALSE;
1117 m_inColspan = FALSE;
1120 if (!c->isLast()) m_t << "&";
1123 void LatexDocVisitor::visitPre(DocInternal *)
1126 //m_t << "\\begin{DoxyInternal}{";
1127 //filter(theTranslator->trForInternalUseOnly());
1131 void LatexDocVisitor::visitPost(DocInternal *)
1134 //m_t << "\\end{DoxyInternal}" << endl;
1137 void LatexDocVisitor::visitPre(DocHRef *href)
1140 if (Config_getBool("PDF_HYPERLINKS"))
1149 void LatexDocVisitor::visitPost(DocHRef *)
1155 void LatexDocVisitor::visitPre(DocHtmlHeader *header)
1158 m_t << "\\" << getSectionName(header->level()) << "*{";
1161 void LatexDocVisitor::visitPost(DocHtmlHeader *)
1167 void LatexDocVisitor::visitPre(DocImage *img)
1169 if (img->type()==DocImage::Latex)
1172 if (img->hasCaption())
1174 m_t << "\n\\begin{DoxyImage}\n";
1178 m_t << "\n\\begin{DoxyImageNoCaption}\n"
1181 QCString gfxName = img->name();
1182 if (gfxName.right(4)==".eps" || gfxName.right(4)==".pdf")
1184 gfxName=gfxName.left(gfxName.length()-4);
1186 m_t << "\\includegraphics";
1187 if (!img->width().isEmpty())
1189 m_t << "[width=" << img->width() << "]";
1191 else if (!img->height().isEmpty())
1193 m_t << "[height=" << img->height() << "]";
1195 m_t << "{" << gfxName << "}";
1196 if (img->hasCaption())
1198 m_t << "\n\\caption{";
1201 else // other format -> skip
1208 void LatexDocVisitor::visitPost(DocImage *img)
1210 if (img->type()==DocImage::Latex)
1213 m_t << "}\n"; // end mbox or caption
1214 if (img->hasCaption())
1216 m_t << "\\end{DoxyImage}\n";
1219 m_t << "\\end{DoxyImageNoCaption}\n";
1222 else // other format
1228 void LatexDocVisitor::visitPre(DocDotFile *df)
1231 startDotFile(df->file(),df->width(),df->height(),df->hasCaption());
1234 void LatexDocVisitor::visitPost(DocDotFile *df)
1237 endDotFile(df->hasCaption());
1239 void LatexDocVisitor::visitPre(DocMscFile *df)
1242 startMscFile(df->file(),df->width(),df->height(),df->hasCaption());
1245 void LatexDocVisitor::visitPost(DocMscFile *df)
1248 endMscFile(df->hasCaption());
1250 void LatexDocVisitor::visitPre(DocLink *lnk)
1253 startLink(lnk->ref(),lnk->file(),lnk->anchor());
1256 void LatexDocVisitor::visitPost(DocLink *lnk)
1259 endLink(lnk->ref(),lnk->file(),lnk->anchor());
1262 void LatexDocVisitor::visitPre(DocRef *ref)
1265 // when ref->isSubPage()==TRUE we use ref->file() for HTML and
1266 // ref->anchor() for LaTeX/RTF
1267 if (ref->isSubPage())
1269 startLink(ref->ref(),0,ref->anchor());
1273 if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
1275 if (!ref->hasLinkText()) filter(ref->targetTitle());
1278 void LatexDocVisitor::visitPost(DocRef *ref)
1281 if (ref->isSubPage())
1283 endLink(ref->ref(),0,ref->anchor());
1287 if (!ref->file().isEmpty()) endLink(ref->ref(),ref->file(),ref->anchor());
1291 void LatexDocVisitor::visitPre(DocSecRefItem *)
1294 m_t << "\\item \\contentsline{section}{";
1297 void LatexDocVisitor::visitPost(DocSecRefItem *ref)
1300 m_t << "}{\\ref{" << ref->file() << "_" << ref->anchor() << "}}{}" << endl;
1303 void LatexDocVisitor::visitPre(DocSecRefList *)
1306 m_t << "\\footnotesize" << endl;
1307 m_t << "\\begin{multicols}{2}" << endl;
1308 m_t << "\\begin{DoxyCompactList}" << endl;
1311 void LatexDocVisitor::visitPost(DocSecRefList *)
1314 m_t << "\\end{DoxyCompactList}" << endl;
1315 m_t << "\\end{multicols}" << endl;
1316 m_t << "\\normalsize" << endl;
1319 void LatexDocVisitor::visitPre(DocParamSect *s)
1322 bool hasInOutSpecs = s->hasInOutSpecifier();
1323 bool hasTypeSpecs = s->hasTypeSpecifier();
1326 case DocParamSect::Param:
1327 m_t << "\n\\begin{DoxyParams}";
1328 if (hasInOutSpecs && hasTypeSpecs) m_t << "[2]"; // 2 extra cols
1329 else if (hasInOutSpecs || hasTypeSpecs) m_t << "[1]"; // 1 extra col
1331 filter(theTranslator->trParameters());
1333 case DocParamSect::RetVal:
1334 m_t << "\n\\begin{DoxyRetVals}{";
1335 filter(theTranslator->trReturnValues());
1337 case DocParamSect::Exception:
1338 m_t << "\n\\begin{DoxyExceptions}{";
1339 filter(theTranslator->trExceptions());
1341 case DocParamSect::TemplateParam:
1343 filter(theTranslator->trTemplateParam()); break;
1345 m_t << "\n\\begin{DoxyTemplParams}{";
1346 filter("Template Parameters");
1354 void LatexDocVisitor::visitPost(DocParamSect *s)
1359 case DocParamSect::Param:
1360 m_t << "\\end{DoxyParams}\n";
1362 case DocParamSect::RetVal:
1363 m_t << "\\end{DoxyRetVals}\n";
1365 case DocParamSect::Exception:
1366 m_t << "\\end{DoxyExceptions}\n";
1368 case DocParamSect::TemplateParam:
1369 m_t << "\\end{DoxyTemplParams}\n";
1376 void LatexDocVisitor::visitPre(DocParamList *pl)
1379 DocParamSect::Type parentType = DocParamSect::Unknown;
1380 DocParamSect *sect = 0;
1381 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1383 parentType = ((DocParamSect*)pl->parent())->type();
1384 sect=(DocParamSect*)pl->parent();
1386 bool useTable = parentType==DocParamSect::Param ||
1387 parentType==DocParamSect::RetVal ||
1388 parentType==DocParamSect::Exception ||
1389 parentType==DocParamSect::TemplateParam;
1394 if (sect && sect->hasInOutSpecifier())
1396 if (pl->direction()!=DocParamSect::Unspecified)
1398 m_t << "\\mbox{\\tt ";
1399 if (pl->direction()==DocParamSect::In)
1403 else if (pl->direction()==DocParamSect::Out)
1407 else if (pl->direction()==DocParamSect::InOut)
1413 if (useTable) m_t << " & ";
1415 if (sect && sect->hasTypeSpecifier())
1417 QListIterator<DocNode> li(pl->paramTypes());
1420 for (li.toFirst();(type=li.current());++li)
1422 if (!first) m_t << " | "; else first=FALSE;
1423 if (type->kind()==DocNode::Kind_Word)
1425 visit((DocWord*)type);
1427 else if (type->kind()==DocNode::Kind_LinkedWord)
1429 visit((DocLinkedWord*)type);
1432 if (useTable) m_t << " & ";
1435 //QStrListIterator li(pl->parameters());
1437 QListIterator<DocNode> li(pl->parameters());
1440 for (li.toFirst();(param=li.current());++li)
1442 if (!first) m_t << ","; else first=FALSE;
1444 if (param->kind()==DocNode::Kind_Word)
1446 visit((DocWord*)param);
1448 else if (param->kind()==DocNode::Kind_LinkedWord)
1450 visit((DocLinkedWord*)param);
1465 void LatexDocVisitor::visitPost(DocParamList *pl)
1468 DocParamSect::Type parentType = DocParamSect::Unknown;
1469 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1471 parentType = ((DocParamSect*)pl->parent())->type();
1473 bool useTable = parentType==DocParamSect::Param ||
1474 parentType==DocParamSect::RetVal ||
1475 parentType==DocParamSect::Exception ||
1476 parentType==DocParamSect::TemplateParam;
1479 m_t << "\\\\" << endl
1480 << "\\hline" << endl;
1484 void LatexDocVisitor::visitPre(DocXRefItem *x)
1487 m_t << "\\begin{DoxyRefDesc}{";
1490 bool anonymousEnum = x->file()=="@";
1492 if (Config_getBool("PDF_HYPERLINKS") && !anonymousEnum)
1494 m_t << "\\hyperlink{" << stripPath(x->file()) << "_" << x->anchor() << "}{";
1506 void LatexDocVisitor::visitPost(DocXRefItem *)
1509 m_t << "\\end{DoxyRefDesc}" << endl;
1512 void LatexDocVisitor::visitPre(DocInternalRef *ref)
1515 startLink(0,ref->file(),ref->anchor());
1518 void LatexDocVisitor::visitPost(DocInternalRef *ref)
1521 endLink(0,ref->file(),ref->anchor());
1524 void LatexDocVisitor::visitPre(DocCopy *)
1528 void LatexDocVisitor::visitPost(DocCopy *)
1532 void LatexDocVisitor::visitPre(DocText *)
1536 void LatexDocVisitor::visitPost(DocText *)
1540 void LatexDocVisitor::visitPre(DocHtmlBlockQuote *)
1543 m_t << "\\begin{quotation}" << endl;
1546 void LatexDocVisitor::visitPost(DocHtmlBlockQuote *)
1549 m_t << "\\end{quotation}" << endl;
1552 void LatexDocVisitor::filter(const char *str)
1554 filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem);
1557 void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
1559 if (ref.isEmpty() && Config_getBool("PDF_HYPERLINKS")) // internal PDF link
1561 if (ref.isEmpty()) {
1562 m_t << "\\hyperlink{";
1563 if (!file.isEmpty()) m_t << stripPath(file);
1564 if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
1565 if (!anchor.isEmpty()) m_t << anchor;
1572 if ((dest=Doxygen::tagDestinationDict[ref])) m_t << *dest << "/";
1573 if (!file.isEmpty()) m_t << file << Doxygen::htmlFileExtension;
1574 if (!anchor.isEmpty()) m_t << "#" << anchor;
1578 else if (ref.isEmpty()) // internal non-PDF link
1580 m_t << "\\doxyref{";
1582 else // external link
1588 void LatexDocVisitor::endLink(const QCString &ref,const QCString &file,const QCString &anchor)
1591 if (ref.isEmpty() && !Config_getBool("PDF_HYPERLINKS"))
1594 filter(theTranslator->trPageAbbreviation());
1595 m_t << "}{" << file;
1596 if (!anchor.isEmpty()) m_t << "_" << anchor;
1601 void LatexDocVisitor::pushEnabled()
1603 m_enabled.push(new bool(m_hide));
1606 void LatexDocVisitor::popEnabled()
1608 bool *v=m_enabled.pop();
1614 void LatexDocVisitor::startDotFile(const QCString &fileName,
1615 const QCString &width,
1616 const QCString &height,
1620 QCString baseName=fileName;
1622 if ((i=baseName.findRev('/'))!=-1)
1624 baseName=baseName.right(baseName.length()-i-1);
1626 if ((i=baseName.find('.'))!=-1)
1628 baseName=baseName.left(i);
1630 baseName.prepend("dot_");
1631 QCString outDir = Config_getString("LATEX_OUTPUT");
1632 QCString name = fileName;
1633 writeDotGraphFromFile(name,outDir,baseName,EPS);
1636 m_t << "\n\\begin{DoxyImage}\n";
1640 m_t << "\n\\begin{DoxyImageNoCaption}\n"
1643 m_t << "\\includegraphics";
1644 if (!width.isEmpty())
1646 m_t << "[width=" << width << "]";
1648 else if (!height.isEmpty())
1650 m_t << "[height=" << height << "]";
1654 m_t << "[width=\\textwidth]";
1656 m_t << "{" << baseName << "}";
1660 m_t << "\n\\caption{";
1664 void LatexDocVisitor::endDotFile(bool hasCaption)
1667 m_t << "}\n"; // end caption or mbox
1670 m_t << "\\end{DoxyImage}\n";
1674 m_t << "\\end{DoxyImageNoCaption}\n";
1678 void LatexDocVisitor::startMscFile(const QCString &fileName,
1679 const QCString &width,
1680 const QCString &height,
1684 QCString baseName=fileName;
1686 if ((i=baseName.findRev('/'))!=-1)
1688 baseName=baseName.right(baseName.length()-i-1);
1690 if ((i=baseName.find('.'))!=-1)
1692 baseName=baseName.left(i);
1694 baseName.prepend("msc_");
1696 QCString outDir = Config_getString("LATEX_OUTPUT");
1697 writeMscGraphFromFile(fileName,outDir,baseName,MSC_EPS);
1700 m_t << "\n\\begin{DoxyImage}\n";
1704 m_t << "\n\\begin{DoxyImageNoCaption}\n"
1707 m_t << "\\includegraphics";
1708 if (!width.isEmpty())
1710 m_t << "[width=" << width << "]";
1712 else if (!height.isEmpty())
1714 m_t << "[height=" << height << "]";
1718 m_t << "[width=\\textwidth]";
1720 m_t << "{" << baseName << "}";
1724 m_t << "\n\\caption{";
1728 void LatexDocVisitor::endMscFile(bool hasCaption)
1731 m_t << "}\n"; // end caption or mbox
1734 m_t << "\\end{DoxyImage}\n";
1738 m_t << "\\end{DoxyImageNoCaption}\n";
1743 void LatexDocVisitor::writeMscFile(const QCString &baseName)
1745 QCString shortName = baseName;
1747 if ((i=shortName.findRev('/'))!=-1)
1749 shortName=shortName.right(shortName.length()-i-1);
1751 QCString outDir = Config_getString("LATEX_OUTPUT");
1752 writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_EPS);
1753 m_t << "\n\\begin{DoxyImageNoCaption}"
1754 " \\mbox{\\includegraphics";
1755 m_t << "{" << shortName << "}";
1756 m_t << "}\n"; // end mbox
1757 m_t << "\\end{DoxyImageNoCaption}\n";