Imported Upstream version 1.8.8
[platform/upstream/doxygen.git] / src / latexdocvisitor.cpp
1 /******************************************************************************
2  *
3  * 
4  *
5  *
6  * Copyright (C) 1997-2014 by Dimitri van Heesch.
7  *
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.
13  *
14  * Documents produced by Doxygen are derivative works derived from the
15  * input used in their production; they are not affected by this license.
16  *
17  */
18 #include "htmlattrib.h"
19 #include <qfileinfo.h> 
20 #include "latexdocvisitor.h"
21 #include "docparser.h"
22 #include "language.h"
23 #include "doxygen.h"
24 #include "outputgen.h"
25 #include "dot.h"
26 #include "util.h"
27 #include "message.h"
28 #include "parserintf.h"
29 #include "msc.h"
30 #include "dia.h"
31 #include "cite.h"
32 #include "filedef.h"
33 #include "config.h"
34 #include "htmlentity.h"
35 #include "plantuml.h"
36
37 static QCString escapeLabelName(const char *s)
38 {
39   QCString result;
40   const char *p=s;
41   char c;
42   if (p)
43   {
44     while ((c=*p++))
45     {
46       switch (c)
47       {
48         case '%': result+="\\%"; break;
49         case '|': result+="\\texttt{\"|}"; break;
50         case '!': result+="\"!"; break;
51         case '{': result+="\\lcurly{}"; break;
52         case '}': result+="\\rcurly{}"; break;
53         case '~': result+="````~"; break; // to get it a bit better in index together with other special characters
54         default: result+=c;
55       }
56     }
57   }
58   return result;
59 }
60
61 const int maxLevels=5;
62 static const char *secLabels[maxLevels] = 
63    { "section","subsection","subsubsection","paragraph","subparagraph" };
64
65 static const char *getSectionName(int level)
66 {
67   static bool compactLatex = Config_getBool("COMPACT_LATEX");
68   int l = level;
69   if (compactLatex) l++;
70   if (Doxygen::insideMainPage) l--;
71   return secLabels[QMIN(maxLevels-1,l)];
72 }
73
74 QCString LatexDocVisitor::escapeMakeIndexChars(const char *s)
75 {
76   QCString result;
77   const char *p=s;
78   char str[2]; str[1]=0;
79   char c;
80   if (p)
81   {
82     while ((c=*p++))
83     {
84       switch (c)
85       {
86         case '!': m_t << "\"!"; break;
87         case '"': m_t << "\"\""; break;
88         case '@': m_t << "\"@"; break;
89         case '|': m_t << "\\texttt{\"|}"; break;
90         case '[': m_t << "["; break;
91         case ']': m_t << "]"; break;
92         case '{': m_t << "\\lcurly{}"; break;
93         case '}': m_t << "\\rcurly{}"; break;
94         default:  str[0]=c; filter(str); break;
95       }
96     }
97   }
98   return result;
99 }
100
101
102 LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci,
103                                  const char *langExt,bool insideTabbing) 
104   : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE), 
105     m_insideItem(FALSE), m_hide(FALSE), m_insideTabbing(insideTabbing),
106     m_insideTable(FALSE), m_langExt(langExt), m_currentColumn(0), 
107     m_inRowspan(FALSE), m_inColspan(FALSE)
108 {
109   m_rowSpans.setAutoDelete(TRUE);
110 }
111
112   //--------------------------------------
113   // visitor functions for leaf nodes
114   //--------------------------------------
115
116 void LatexDocVisitor::visit(DocWord *w)
117 {
118   if (m_hide) return;
119   filter(w->word());
120 }
121
122 void LatexDocVisitor::visit(DocLinkedWord *w)
123 {
124   if (m_hide) return;
125   startLink(w->ref(),w->file(),w->anchor());
126   filter(w->word());
127   endLink(w->ref(),w->file(),w->anchor());
128 }
129
130 void LatexDocVisitor::visit(DocWhiteSpace *w)
131 {
132   if (m_hide) return;
133   if (m_insidePre)
134   {
135     m_t << w->chars();
136   }
137   else
138   {
139     m_t << " ";
140   }
141 }
142
143 void LatexDocVisitor::visit(DocSymbol *s)
144 {
145   if (m_hide) return;
146   const char *res = HtmlEntityMapper::instance()->latex(s->symbol());
147   if (res)
148   {
149     if (((s->symbol() == DocSymbol::Sym_lt) || (s->symbol() == DocSymbol::Sym_Less))&& (!m_insidePre))
150     {
151       m_t << "$<$";
152     }
153     else if (((s->symbol() == DocSymbol::Sym_gt) || (s->symbol() == DocSymbol::Sym_Greater)) && (!m_insidePre))
154     {
155       m_t << "$>$";
156     }
157     else
158     {
159       m_t << res;
160     }
161   }
162   else
163   {
164     err("LaTeX: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
165   }
166 }
167
168 void LatexDocVisitor::visit(DocURL *u)
169 {
170   if (m_hide) return;
171   if (Config_getBool("PDF_HYPERLINKS"))
172   {
173     m_t << "\\href{";
174     if (u->isEmail()) m_t << "mailto:";
175     m_t << u->url() << "}";
176   }
177   m_t << "{\\tt ";
178   filter(u->url());
179   m_t << "}";
180 }
181
182 void LatexDocVisitor::visit(DocLineBreak *)
183 {
184   if (m_hide) return;
185   m_t << "~\\newline\n";
186 }
187
188 void LatexDocVisitor::visit(DocHorRuler *)
189 {
190   if (m_hide) return;
191   m_t << "\n\n";
192 }
193
194 void LatexDocVisitor::visit(DocStyleChange *s)
195 {
196   if (m_hide) return;
197   switch (s->style())
198   {
199     case DocStyleChange::Bold:
200       if (s->enable()) m_t << "{\\bfseries ";      else m_t << "}";
201       break;
202     case DocStyleChange::Italic:
203       if (s->enable()) m_t << "{\\itshape ";     else m_t << "}";
204       break;
205     case DocStyleChange::Code:
206       if (s->enable()) m_t << "{\\ttfamily ";   else m_t << "}";
207       break;
208     case DocStyleChange::Subscript:
209       if (s->enable()) m_t << "\\textsubscript{";    else m_t << "}";
210       break;
211     case DocStyleChange::Superscript:
212       if (s->enable()) m_t << "\\textsuperscript{";    else m_t << "}";
213       break;
214     case DocStyleChange::Center:
215       if (s->enable()) m_t << "\\begin{center}"; else m_t << "\\end{center} ";
216       break;
217     case DocStyleChange::Small:
218       if (s->enable()) m_t << "\n\\footnotesize ";  else m_t << "\n\\normalsize ";
219       break;
220     case DocStyleChange::Preformatted:
221       if (s->enable()) 
222       {
223         m_t << "\n\\begin{DoxyPre}";
224         m_insidePre=TRUE;
225       }
226       else
227       {
228         m_insidePre=FALSE;
229         m_t << "\\end{DoxyPre}\n";
230       }
231       break;
232     case DocStyleChange::Div:  /* HTML only */ break;
233     case DocStyleChange::Span: /* HTML only */ break;
234   }
235 }
236
237 void LatexDocVisitor::visit(DocVerbatim *s)
238 {
239   if (m_hide) return;
240   QCString lang = m_langExt;
241   if (!s->language().isEmpty()) // explicit language setting
242   {
243     lang = s->language();
244   }
245   SrcLangExt langExt = getLanguageFromFileName(lang);
246   switch(s->type())
247   {
248     case DocVerbatim::Code: 
249       {
250         m_t << "\n\\begin{DoxyCode}\n";
251         Doxygen::parserManager->getParser(lang)
252                               ->parseCode(m_ci,s->context(),s->text(),langExt,
253                                           s->isExample(),s->exampleFile());
254         m_t << "\\end{DoxyCode}\n";
255       }
256       break;
257     case DocVerbatim::Verbatim: 
258       m_t << "\\begin{DoxyVerb}";
259       m_t << s->text();
260       m_t << "\\end{DoxyVerb}\n";
261       break;
262     case DocVerbatim::HtmlOnly: 
263     case DocVerbatim::XmlOnly: 
264     case DocVerbatim::ManOnly: 
265     case DocVerbatim::RtfOnly:
266     case DocVerbatim::DocbookOnly:
267       /* nothing */ 
268       break;
269     case DocVerbatim::LatexOnly: 
270       m_t << s->text(); 
271       break;
272     case DocVerbatim::Dot: 
273       {
274         static int dotindex = 1;
275         QCString fileName(4096);
276
277         fileName.sprintf("%s%d%s", 
278             (Config_getString("LATEX_OUTPUT")+"/inline_dotgraph_").data(), 
279             dotindex++,
280             ".dot"
281            );
282         QFile file(fileName);
283         if (!file.open(IO_WriteOnly))
284         {
285           err("Could not open file %s for writing\n",fileName.data());
286         }
287         file.writeBlock( s->text(), s->text().length() );
288         file.close();
289
290         m_t << "\\begin{center}\n";
291         startDotFile(fileName,"","",FALSE);
292         endDotFile(FALSE);
293         m_t << "\\end{center}\n";
294
295         if (Config_getBool("DOT_CLEANUP")) file.remove();
296       }
297       break;
298     case DocVerbatim::Msc: 
299       {
300         static int mscindex = 1;
301         QCString baseName(4096);
302
303         baseName.sprintf("%s%d", 
304             (Config_getString("LATEX_OUTPUT")+"/inline_mscgraph_").data(), 
305             mscindex++
306            );
307         QFile file(baseName+".msc");
308         if (!file.open(IO_WriteOnly))
309         {
310           err("Could not open file %s.msc for writing\n",baseName.data());
311         }
312         QCString text = "msc {";
313         text+=s->text();
314         text+="}";
315         file.writeBlock( text, text.length() );
316         file.close();
317
318         m_t << "\\begin{center}\n";
319         writeMscFile(baseName);
320         m_t << "\\end{center}\n";
321
322         if (Config_getBool("DOT_CLEANUP")) file.remove();
323       }
324       break;
325     case DocVerbatim::PlantUML: 
326       {
327         QCString latexOutput = Config_getString("LATEX_OUTPUT");
328         QCString baseName = writePlantUMLSource(latexOutput,s->exampleFile(),s->text());
329
330         m_t << "\\begin{center}\n";
331         writePlantUMLFile(baseName);
332         m_t << "\\end{center}\n";
333       }
334       break;
335   }
336 }
337
338 void LatexDocVisitor::visit(DocAnchor *anc)
339 {
340   if (m_hide) return;
341   m_t << "\\label{" << stripPath(anc->file()) << "_" << anc->anchor() << "}%" << endl;
342   if (!anc->file().isEmpty() && Config_getBool("PDF_HYPERLINKS")) 
343   {
344     m_t << "\\hypertarget{" << stripPath(anc->file()) << "_" << anc->anchor() 
345       << "}{}%" << endl;
346   }    
347 }
348
349 void LatexDocVisitor::visit(DocInclude *inc)
350 {
351   if (m_hide) return;
352   SrcLangExt langExt = getLanguageFromFileName(inc->extension());
353   switch(inc->type())
354   {
355     case DocInclude::IncWithLines:
356       { 
357          m_t << "\n\\begin{DoxyCodeInclude}\n";
358          QFileInfo cfi( inc->file() );
359          FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
360          Doxygen::parserManager->getParser(inc->extension())
361                                ->parseCode(m_ci,inc->context(),
362                                            inc->text(),
363                                            langExt,
364                                            inc->isExample(),
365                                            inc->exampleFile(), &fd);
366          m_t << "\\end{DoxyCodeInclude}" << endl;
367       }
368       break;    
369     case DocInclude::Include: 
370       m_t << "\n\\begin{DoxyCodeInclude}\n";
371       Doxygen::parserManager->getParser(inc->extension())
372                             ->parseCode(m_ci,inc->context(),
373                                         inc->text(),langExt,inc->isExample(),
374                                         inc->exampleFile());
375       m_t << "\\end{DoxyCodeInclude}\n";
376       break;
377     case DocInclude::DontInclude: 
378       break;
379     case DocInclude::HtmlInclude: 
380       break;
381     case DocInclude::LatexInclude:
382       m_t << inc->text();
383       break;
384     case DocInclude::VerbInclude: 
385       m_t << "\n\\begin{DoxyVerbInclude}\n";
386       m_t << inc->text();
387       m_t << "\\end{DoxyVerbInclude}\n";
388       break;
389     case DocInclude::Snippet:
390       {
391          m_t << "\n\\begin{DoxyCodeInclude}\n";
392          Doxygen::parserManager->getParser(inc->extension())
393                                ->parseCode(m_ci,
394                                            inc->context(),
395                                            extractBlock(inc->text(),inc->blockId()),
396                                            langExt,
397                                            inc->isExample(),
398                                            inc->exampleFile()
399                                           );
400          m_t << "\\end{DoxyCodeInclude}" << endl;
401       }
402       break;
403   }
404 }
405
406 void LatexDocVisitor::visit(DocIncOperator *op)
407 {
408   //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
409   //    op->type(),op->isFirst(),op->isLast(),op->text().data());
410   if (op->isFirst()) 
411   {
412     if (!m_hide) m_t << "\n\\begin{DoxyCodeInclude}\n";
413     pushEnabled();
414     m_hide = TRUE;
415   }
416   SrcLangExt langExt = getLanguageFromFileName(m_langExt);
417   if (op->type()!=DocIncOperator::Skip) 
418   {
419     popEnabled();
420     if (!m_hide) 
421     {
422       Doxygen::parserManager->getParser(m_langExt)
423                             ->parseCode(m_ci,op->context(),op->text(),langExt,
424                                         op->isExample(),op->exampleFile());
425     }
426     pushEnabled();
427     m_hide=TRUE;
428   }
429   if (op->isLast())  
430   {
431     popEnabled();
432     if (!m_hide) m_t << "\n\\end{DoxyCodeInclude}\n";
433   }
434   else
435   {
436     if (!m_hide) m_t << endl;
437   }
438 }
439
440 void LatexDocVisitor::visit(DocFormula *f)
441 {
442   if (m_hide) return;
443   m_t << f->text();
444 }
445
446 void LatexDocVisitor::visit(DocIndexEntry *i)
447 {
448   if (m_hide) return;
449   m_t << "\\index{" << escapeLabelName(i->entry()) << "@{";
450   escapeMakeIndexChars(i->entry());
451   m_t << "}}";
452 }
453
454 void LatexDocVisitor::visit(DocSimpleSectSep *)
455 {
456 }
457
458 void LatexDocVisitor::visit(DocCite *cite)
459 {
460   if (m_hide) return;
461   if (!cite->file().isEmpty()) 
462   {
463     //startLink(cite->ref(),cite->file(),cite->anchor());
464     QCString anchor = cite->anchor();
465     anchor = anchor.mid(CiteConsts::anchorPrefix.length()); // strip prefix
466     m_t << "\\cite{" << anchor << "}";
467   }
468   else
469   {
470     m_t << "{\\bfseries [";
471     filter(cite->text());
472     m_t << "]}";
473   }
474 }
475
476 //--------------------------------------
477 // visitor functions for compound nodes
478 //--------------------------------------
479
480 void LatexDocVisitor::visitPre(DocAutoList *l)
481 {
482   if (m_hide) return;
483   if (l->isEnumList())
484   {
485     m_t << "\n\\begin{DoxyEnumerate}";
486   }
487   else
488   {
489     m_t << "\n\\begin{DoxyItemize}";
490   }
491 }
492
493 void LatexDocVisitor::visitPost(DocAutoList *l)
494 {
495   if (m_hide) return;
496   if (l->isEnumList())
497   {
498     m_t << "\n\\end{DoxyEnumerate}";
499   }
500   else
501   {
502     m_t << "\n\\end{DoxyItemize}";
503   }
504 }
505
506 void LatexDocVisitor::visitPre(DocAutoListItem *)
507 {
508   if (m_hide) return;
509   m_t << "\n\\item ";
510 }
511
512 void LatexDocVisitor::visitPost(DocAutoListItem *) 
513 {
514 }
515
516 void LatexDocVisitor::visitPre(DocPara *) 
517 {
518 }
519
520 void LatexDocVisitor::visitPost(DocPara *p)
521 {
522   if (m_hide) return;
523   if (!p->isLast() &&            // omit <p> for last paragraph
524       !(p->parent() &&           // and for parameter sections
525         p->parent()->kind()==DocNode::Kind_ParamSect
526        )
527      ) m_t << endl << endl;
528 }
529
530 void LatexDocVisitor::visitPre(DocRoot *)
531 {
532 }
533
534 void LatexDocVisitor::visitPost(DocRoot *)
535 {
536 }
537
538 void LatexDocVisitor::visitPre(DocSimpleSect *s)
539 {
540   if (m_hide) return;
541   switch(s->type())
542   {
543     case DocSimpleSect::See:
544       m_t << "\\begin{DoxySeeAlso}{";
545       filter(theTranslator->trSeeAlso());
546       break;
547     case DocSimpleSect::Return:
548       m_t << "\\begin{DoxyReturn}{";
549       filter(theTranslator->trReturns());
550       break;
551     case DocSimpleSect::Author:
552       m_t << "\\begin{DoxyAuthor}{";
553       filter(theTranslator->trAuthor(TRUE,TRUE));
554       break;
555     case DocSimpleSect::Authors:
556       m_t << "\\begin{DoxyAuthor}{";
557       filter(theTranslator->trAuthor(TRUE,FALSE));
558       break;
559     case DocSimpleSect::Version:
560       m_t << "\\begin{DoxyVersion}{";
561       filter(theTranslator->trVersion());
562       break;
563     case DocSimpleSect::Since:
564       m_t << "\\begin{DoxySince}{";
565       filter(theTranslator->trSince());
566       break;
567     case DocSimpleSect::Date:
568       m_t << "\\begin{DoxyDate}{";
569       filter(theTranslator->trDate());
570       break;
571     case DocSimpleSect::Note:
572       m_t << "\\begin{DoxyNote}{";
573       filter(theTranslator->trNote());
574       break;
575     case DocSimpleSect::Warning:
576       m_t << "\\begin{DoxyWarning}{";
577       filter(theTranslator->trWarning());
578       break;
579     case DocSimpleSect::Pre:
580       m_t << "\\begin{DoxyPrecond}{";
581       filter(theTranslator->trPrecondition());
582       break;
583     case DocSimpleSect::Post:
584       m_t << "\\begin{DoxyPostcond}{";
585       filter(theTranslator->trPostcondition());
586       break;
587     case DocSimpleSect::Copyright:
588       m_t << "\\begin{DoxyCopyright}{";
589       filter(theTranslator->trCopyright());
590       break;
591     case DocSimpleSect::Invar:
592       m_t << "\\begin{DoxyInvariant}{";
593       filter(theTranslator->trInvariant());
594       break;
595     case DocSimpleSect::Remark:
596       m_t << "\\begin{DoxyRemark}{";
597       filter(theTranslator->trRemarks());
598       break;
599     case DocSimpleSect::Attention:
600       m_t << "\\begin{DoxyAttention}{";
601       filter(theTranslator->trAttention());
602       break;
603     case DocSimpleSect::User:
604       m_t << "\\begin{DoxyParagraph}{";
605       break;
606     case DocSimpleSect::Rcs: 
607       m_t << "\\begin{DoxyParagraph}{";
608       break;
609     case DocSimpleSect::Unknown:  break;
610   }
611
612   // special case 1: user defined title
613   if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
614   {
615     m_t << "}\n";
616   }
617   else
618   {
619     m_insideItem=TRUE;
620   }
621 }
622
623 void LatexDocVisitor::visitPost(DocSimpleSect *s)
624 {
625   if (m_hide) return;
626   switch(s->type())
627   {
628     case DocSimpleSect::See:
629       m_t << "\n\\end{DoxySeeAlso}\n";
630       break;
631     case DocSimpleSect::Return:
632       m_t << "\n\\end{DoxyReturn}\n";
633       break;
634     case DocSimpleSect::Author:
635       m_t << "\n\\end{DoxyAuthor}\n";
636       break;
637     case DocSimpleSect::Authors:
638       m_t << "\n\\end{DoxyAuthor}\n";
639       break;
640     case DocSimpleSect::Version:
641       m_t << "\n\\end{DoxyVersion}\n";
642       break;
643     case DocSimpleSect::Since:
644       m_t << "\n\\end{DoxySince}\n";
645       break;
646     case DocSimpleSect::Date:
647       m_t << "\n\\end{DoxyDate}\n";
648       break;
649     case DocSimpleSect::Note:
650       m_t << "\n\\end{DoxyNote}\n";
651       break;
652     case DocSimpleSect::Warning:
653       m_t << "\n\\end{DoxyWarning}\n";
654       break;
655     case DocSimpleSect::Pre:
656       m_t << "\n\\end{DoxyPrecond}\n";
657       break;
658     case DocSimpleSect::Post:
659       m_t << "\n\\end{DoxyPostcond}\n";
660       break;
661     case DocSimpleSect::Copyright:
662       m_t << "\n\\end{DoxyCopyright}\n";
663       break;
664     case DocSimpleSect::Invar:
665       m_t << "\n\\end{DoxyInvariant}\n";
666       break;
667     case DocSimpleSect::Remark:
668       m_t << "\n\\end{DoxyRemark}\n";
669       break;
670     case DocSimpleSect::Attention:
671       m_t << "\n\\end{DoxyAttention}\n";
672       break;
673     case DocSimpleSect::User:
674       m_t << "\n\\end{DoxyParagraph}\n";
675       break;
676     case DocSimpleSect::Rcs: 
677       m_t << "\n\\end{DoxyParagraph}\n";
678       break;
679     default:
680       break;
681   }
682 }
683
684 void LatexDocVisitor::visitPre(DocTitle *)
685 {
686 }
687
688 void LatexDocVisitor::visitPost(DocTitle *)
689 {
690   if (m_hide) return;
691   m_insideItem=FALSE;
692   m_t << "}\n";
693 }
694
695 void LatexDocVisitor::visitPre(DocSimpleList *)
696 {
697   if (m_hide) return;
698   m_t << "\\begin{DoxyItemize}" << endl;
699 }
700
701 void LatexDocVisitor::visitPost(DocSimpleList *)
702 {
703   if (m_hide) return;
704   m_t << "\\end{DoxyItemize}" << endl;
705 }
706
707 void LatexDocVisitor::visitPre(DocSimpleListItem *)
708 {
709   if (m_hide) return;
710   m_t << "\\item ";
711 }
712
713 void LatexDocVisitor::visitPost(DocSimpleListItem *) 
714 {
715 }
716
717 void LatexDocVisitor::visitPre(DocSection *s)
718 {
719   if (m_hide) return;
720   if (Config_getBool("PDF_HYPERLINKS"))
721   {
722     m_t << "\\hypertarget{" << stripPath(s->file()) << "_" << s->anchor() << "}{}";
723   }
724   m_t << "\\" << getSectionName(s->level()) << "{";
725   filter(convertCharEntitiesToUTF8(s->title().data()));
726   m_t << "}\\label{" << stripPath(s->file()) << "_" << s->anchor() << "}" << endl;
727 }
728
729 void LatexDocVisitor::visitPost(DocSection *) 
730 {
731 }
732
733 void LatexDocVisitor::visitPre(DocHtmlList *s)
734 {
735   if (m_hide) return;
736   if (s->type()==DocHtmlList::Ordered) 
737     m_t << "\n\\begin{DoxyEnumerate}";
738   else 
739     m_t << "\n\\begin{DoxyItemize}";
740 }
741
742 void LatexDocVisitor::visitPost(DocHtmlList *s) 
743 {
744   if (m_hide) return;
745   if (s->type()==DocHtmlList::Ordered) 
746     m_t << "\n\\end{DoxyEnumerate}";
747   else 
748     m_t << "\n\\end{DoxyItemize}";
749 }
750
751 void LatexDocVisitor::visitPre(DocHtmlListItem *)
752 {
753   if (m_hide) return;
754   m_t << "\n\\item ";
755 }
756
757 void LatexDocVisitor::visitPost(DocHtmlListItem *) 
758 {
759 }
760
761 //void LatexDocVisitor::visitPre(DocHtmlPre *)
762 //{
763 //  m_t << "\\small\\begin{alltt}";
764 //  m_insidePre=TRUE;
765 //}
766
767 //void LatexDocVisitor::visitPost(DocHtmlPre *) 
768 //{
769 //  m_insidePre=FALSE;
770 //  m_t << "\\end{alltt}\\normalsize " << endl;
771 //}
772
773 void LatexDocVisitor::visitPre(DocHtmlDescList *dl)
774 {
775   if (m_hide) return;
776   QCString val = dl->attribs().find("class");
777   if (val=="reflist")
778   {
779     m_t << "\n\\begin{DoxyRefList}";
780   }
781   else
782   {
783     m_t << "\n\\begin{DoxyDescription}";
784   }
785 }
786
787 void LatexDocVisitor::visitPost(DocHtmlDescList *dl) 
788 {
789   if (m_hide) return;
790   QCString val = dl->attribs().find("class");
791   if (val=="reflist")
792   {
793     m_t << "\n\\end{DoxyRefList}";
794   }
795   else
796   {
797     m_t << "\n\\end{DoxyDescription}";
798   }
799 }
800
801 void LatexDocVisitor::visitPre(DocHtmlDescTitle *)
802 {
803   if (m_hide) return;
804   m_t << "\n\\item[";
805   m_insideItem=TRUE;
806 }
807
808 void LatexDocVisitor::visitPost(DocHtmlDescTitle *) 
809 {
810   if (m_hide) return;
811   m_insideItem=FALSE;
812   m_t << "]";
813 }
814
815 void LatexDocVisitor::visitPre(DocHtmlDescData *)
816 {
817 }
818
819 void LatexDocVisitor::visitPost(DocHtmlDescData *) 
820 {
821 }
822
823 static const char *getTableName(const DocNode *n)
824 {
825   bool isNested=FALSE;
826   while (n && !isNested)
827   {
828     isNested = n->kind()==DocNode::Kind_HtmlTable;
829     n  = n->parent();
830   }
831   return isNested ? "TabularNC" : "TabularC";
832 }
833
834 void LatexDocVisitor::visitPre(DocHtmlTable *t)
835 {
836   m_rowSpans.clear();
837   m_insideTable=TRUE;
838   if (m_hide) return;
839   if (t->hasCaption())
840   {
841     m_t << "\\begin{table}[h]";
842   }
843   m_t << "\\begin{" << getTableName(t->parent()) << "}{" << t->numColumns() << "}\n";
844   m_numCols = t->numColumns();
845   m_t << "\\hline\n";
846 }
847
848 void LatexDocVisitor::visitPost(DocHtmlTable *t)
849 {
850   m_insideTable=FALSE;
851   if (m_hide) return;
852   if (t->hasCaption())
853   {
854     m_t << "\\end{table}\n";
855   }
856   else
857   {
858     m_t << "\\end{" << getTableName(t->parent()) << "}\n";
859   }
860 }
861
862 void LatexDocVisitor::visitPre(DocHtmlCaption *c)
863 {
864   if (m_hide) return;
865   m_t << "\\end{" << getTableName(c->parent()) << "}\n\\centering\n\\caption{";
866 }
867
868 void LatexDocVisitor::visitPost(DocHtmlCaption *) 
869 {
870   if (m_hide) return;
871   m_t << "}\n";
872 }
873
874 void LatexDocVisitor::visitPre(DocHtmlRow *r)
875 {
876   m_currentColumn = 0;
877   if (r->isHeading()) m_t << "\\rowcolor{lightgray}";
878 }
879
880 void LatexDocVisitor::visitPost(DocHtmlRow *row) 
881 {
882   if (m_hide) return;
883
884   int c=m_currentColumn;
885   while (c<=m_numCols) // end of row while inside a row span?
886   {
887     uint i;
888     for (i=0;i<m_rowSpans.count();i++)
889     {
890       ActiveRowSpan *span = m_rowSpans.at(i);
891       //printf("  founc row span: column=%d rs=%d cs=%d rowIdx=%d cell->rowIdx=%d\n",
892       //    span->column, span->rowSpan,span->colSpan,row->rowIndex(),span->cell->rowIndex());
893       if (span->rowSpan>0 && span->column==c &&  // we are at a cell in a row span
894           row->rowIndex()>span->cell->rowIndex() // but not the row that started the span
895          )
896       {
897         m_t << "&";
898         if (span->colSpan>1) // row span is also part of a column span
899         {
900           m_t << "\\multicolumn{" << span->colSpan << "}{";
901           m_t << "p{(\\linewidth-\\tabcolsep*" 
902             << m_numCols << "-\\arrayrulewidth*"
903             << row->visibleCells() << ")*" 
904             << span->colSpan <<"/"<< m_numCols << "}|}{}";
905         }
906         else // solitary row span
907         {
908           m_t << "\\multicolumn{1}{c|}{}";
909         }
910       }
911     }
912     c++;
913   }
914
915   m_t << "\\\\";
916   
917   int col = 1;
918   uint i;
919   for (i=0;i<m_rowSpans.count();i++)
920   {
921     ActiveRowSpan *span = m_rowSpans.at(i);
922     if (span->rowSpan>0) span->rowSpan--;
923     if (span->rowSpan<=0)
924     {
925       // inactive span
926     }
927     else if (span->column>col)
928     {
929       m_t << "\\cline{" << col << "-" << (span->column-1) << "}";
930       col = span->column+span->colSpan;
931     }
932     else
933     {
934       col = span->column+span->colSpan;
935     }
936   }
937
938   if (col <= m_numCols)
939   {
940     m_t << "\\cline{" << col << "-" << m_numCols << "}";
941   }
942
943   m_t << "\n";
944 }
945
946 void LatexDocVisitor::visitPre(DocHtmlCell *c)
947 {
948   if (m_hide) return;
949
950   DocHtmlRow *row = 0;
951   if (c->parent() && c->parent()->kind()==DocNode::Kind_HtmlRow)
952   {
953     row = (DocHtmlRow*)c->parent();
954   }
955   
956   m_currentColumn++;
957
958   //Skip columns that span from above.
959   uint i;
960   for (i=0;i<m_rowSpans.count();i++)
961   {
962     ActiveRowSpan *span = m_rowSpans.at(i);
963     if (span->rowSpan>0 && span->column==m_currentColumn)
964     {
965       if (row && span->colSpan>1)
966       {
967         m_t << "\\multicolumn{" << span->colSpan << "}{";
968         if (m_currentColumn /*c->columnIndex()*/==1) // add extra | for first column
969         {
970           m_t << "|";
971         }
972         m_t << "p{(\\linewidth-\\tabcolsep*" 
973             << m_numCols << "-\\arrayrulewidth*"
974             << row->visibleCells() << ")*" 
975             << span->colSpan <<"/"<< m_numCols << "}|}{}";
976         m_currentColumn+=span->colSpan;
977       }
978       else
979       {
980         m_currentColumn++;
981       }
982       m_t << "&";
983     }
984   }
985
986 #if 0
987   QMap<int, int>::Iterator it = m_rowspanIndices.find(m_currentColumn);
988   if (it!=m_rowspanIndices.end() && it.data()>0)
989   {
990     m_t << "&";
991     m_currentColumn++;
992     it++;
993   }
994 #endif
995
996   int cs = c->colSpan();
997   if (cs>1 && row)
998   {
999     m_inColspan = TRUE;
1000     m_t << "\\multicolumn{" << cs << "}{";
1001     if (c->columnIndex()==1) // add extra | for first column
1002     {
1003       m_t << "|";
1004     }
1005     m_t << "p{(\\linewidth-\\tabcolsep*" 
1006         << m_numCols << "-\\arrayrulewidth*"
1007         << row->visibleCells() << ")*" 
1008         << cs <<"/"<< m_numCols << "}|}{";
1009     if (c->isHeading()) m_t << "\\cellcolor{lightgray}";
1010   }
1011   int rs = c->rowSpan();
1012   if (rs>0)
1013   {
1014     m_inRowspan = TRUE;
1015     //m_rowspanIndices[m_currentColumn] = rs;
1016     m_rowSpans.append(new ActiveRowSpan(c,rs,cs,m_currentColumn));
1017     m_t << "\\multirow{" << rs << "}{\\linewidth}{";
1018   }
1019   int a = c->alignment();
1020   if (a==DocHtmlCell::Center)
1021   {
1022     m_t << "\\PBS\\centering ";
1023   }
1024   else if (a==DocHtmlCell::Right)
1025   {
1026     m_t << "\\PBS\\raggedleft ";
1027   }
1028   if (c->isHeading())
1029   {
1030     m_t << "{\\bf ";
1031   }
1032   if (cs>1)
1033   {
1034     m_currentColumn+=cs-1;
1035   }
1036 }
1037
1038 void LatexDocVisitor::visitPost(DocHtmlCell *c) 
1039 {
1040   if (m_hide) return;
1041   if (c->isHeading())
1042   {
1043     m_t << "}";
1044   }
1045   if (m_inRowspan)
1046   {
1047     m_inRowspan = FALSE;
1048     m_t << "}";
1049   }
1050   if (m_inColspan)
1051   {
1052     m_inColspan = FALSE;
1053     m_t << "}";
1054   }
1055   if (!c->isLast()) m_t << "&";
1056 }
1057
1058 void LatexDocVisitor::visitPre(DocInternal *)
1059 {
1060   if (m_hide) return;
1061   //m_t << "\\begin{DoxyInternal}{";
1062   //filter(theTranslator->trForInternalUseOnly());
1063   //m_t << "}\n";
1064 }
1065
1066 void LatexDocVisitor::visitPost(DocInternal *) 
1067 {
1068   if (m_hide) return;
1069   //m_t << "\\end{DoxyInternal}" << endl;
1070 }
1071
1072 void LatexDocVisitor::visitPre(DocHRef *href)
1073 {
1074   if (m_hide) return;
1075   if (Config_getBool("PDF_HYPERLINKS"))
1076   {
1077     m_t << "\\href{";
1078     m_t << href->url();
1079     m_t << "}";
1080   }
1081   m_t << "{\\tt ";
1082 }
1083
1084 void LatexDocVisitor::visitPost(DocHRef *) 
1085 {
1086   if (m_hide) return;
1087   m_t << "}";
1088 }
1089
1090 void LatexDocVisitor::visitPre(DocHtmlHeader *header)
1091 {
1092   if (m_hide) return;
1093   m_t << "\\" << getSectionName(header->level()) << "*{";
1094 }
1095
1096 void LatexDocVisitor::visitPost(DocHtmlHeader *) 
1097 {
1098   if (m_hide) return;
1099   m_t << "}";
1100 }
1101
1102 void LatexDocVisitor::visitPre(DocImage *img)
1103 {
1104   if (img->type()==DocImage::Latex)
1105   {
1106     if (m_hide) return;
1107     if (img->hasCaption())
1108     {
1109       m_t << "\n\\begin{DoxyImage}\n";
1110     }
1111     else
1112     {
1113       m_t << "\n\\begin{DoxyImageNoCaption}\n"
1114              "  \\mbox{";
1115     }
1116     QCString gfxName = img->name();
1117     if (gfxName.right(4)==".eps" || gfxName.right(4)==".pdf")
1118     {
1119       gfxName=gfxName.left(gfxName.length()-4);
1120     }
1121     m_t << "\\includegraphics";
1122     if (!img->width().isEmpty())
1123     {
1124       m_t << "[width=" << img->width() << "]";
1125     }
1126     else if (!img->height().isEmpty())
1127     {
1128       m_t << "[height=" << img->height() << "]";
1129     }
1130     m_t << "{" << gfxName << "}";
1131     if (img->hasCaption())
1132     {
1133       m_t << "\n\\caption{";
1134     }
1135   }
1136   else // other format -> skip
1137   {
1138     pushEnabled();
1139     m_hide=TRUE;
1140   }
1141 }
1142
1143 void LatexDocVisitor::visitPost(DocImage *img) 
1144 {
1145   if (img->type()==DocImage::Latex)
1146   {
1147     if (m_hide) return;
1148     m_t << "}\n"; // end mbox or caption
1149     if (img->hasCaption())
1150     {
1151       m_t << "\\end{DoxyImage}\n";
1152     }
1153     else{
1154       m_t << "\\end{DoxyImageNoCaption}\n";
1155     }
1156   }
1157   else // other format
1158   {
1159     popEnabled();
1160   }
1161 }
1162
1163 void LatexDocVisitor::visitPre(DocDotFile *df)
1164 {
1165   if (m_hide) return;
1166   startDotFile(df->file(),df->width(),df->height(),df->hasCaption());
1167 }
1168
1169 void LatexDocVisitor::visitPost(DocDotFile *df) 
1170 {
1171   if (m_hide) return;
1172   endDotFile(df->hasCaption());
1173 }
1174 void LatexDocVisitor::visitPre(DocMscFile *df)
1175 {
1176   if (m_hide) return;
1177   startMscFile(df->file(),df->width(),df->height(),df->hasCaption());
1178 }
1179
1180 void LatexDocVisitor::visitPost(DocMscFile *df) 
1181 {
1182   if (m_hide) return;
1183   endMscFile(df->hasCaption());
1184 }
1185
1186 void LatexDocVisitor::visitPre(DocDiaFile *df)
1187 {
1188   if (m_hide) return;
1189   startDiaFile(df->file(),df->width(),df->height(),df->hasCaption());
1190 }
1191
1192 void LatexDocVisitor::visitPost(DocDiaFile *df)
1193 {
1194   if (m_hide) return;
1195   endDiaFile(df->hasCaption());
1196 }
1197 void LatexDocVisitor::visitPre(DocLink *lnk)
1198 {
1199   if (m_hide) return;
1200   startLink(lnk->ref(),lnk->file(),lnk->anchor());
1201 }
1202
1203 void LatexDocVisitor::visitPost(DocLink *lnk) 
1204 {
1205   if (m_hide) return;
1206   endLink(lnk->ref(),lnk->file(),lnk->anchor());
1207 }
1208
1209 void LatexDocVisitor::visitPre(DocRef *ref)
1210 {
1211   if (m_hide) return;
1212   // when ref->isSubPage()==TRUE we use ref->file() for HTML and
1213   // ref->anchor() for LaTeX/RTF
1214   if (ref->isSubPage())
1215   {
1216     startLink(ref->ref(),0,ref->anchor());
1217   }
1218   else
1219   {
1220     if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
1221   }
1222   if (!ref->hasLinkText()) filter(ref->targetTitle());
1223 }
1224
1225 void LatexDocVisitor::visitPost(DocRef *ref) 
1226 {
1227   if (m_hide) return;
1228   if (ref->isSubPage())
1229   {
1230     endLink(ref->ref(),0,ref->anchor());
1231   }
1232   else
1233   {
1234     if (!ref->file().isEmpty()) endLink(ref->ref(),ref->file(),ref->anchor());
1235   }
1236 }
1237
1238 void LatexDocVisitor::visitPre(DocSecRefItem *ref)
1239 {
1240   if (m_hide) return;
1241   m_t << "\\item \\contentsline{section}{";
1242   static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
1243   if (pdfHyperlinks)
1244   {
1245     m_t << "\\hyperlink{" << ref->file() << "_" << ref->anchor() << "}{" ;
1246   }
1247 }
1248
1249 void LatexDocVisitor::visitPost(DocSecRefItem *ref) 
1250 {
1251   if (m_hide) return;
1252   static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
1253   if (pdfHyperlinks)
1254   {
1255     m_t << "}";
1256   }
1257   m_t << "}{\\ref{" << ref->file() << "_" << ref->anchor() << "}}{}" << endl;
1258 }
1259
1260 void LatexDocVisitor::visitPre(DocSecRefList *)
1261 {
1262   if (m_hide) return;
1263   m_t << "\\footnotesize" << endl;
1264   m_t << "\\begin{multicols}{2}" << endl;
1265   m_t << "\\begin{DoxyCompactList}" << endl;
1266 }
1267
1268 void LatexDocVisitor::visitPost(DocSecRefList *) 
1269 {
1270   if (m_hide) return;
1271   m_t << "\\end{DoxyCompactList}" << endl;
1272   m_t << "\\end{multicols}" << endl;
1273   m_t << "\\normalsize" << endl;
1274 }
1275
1276 void LatexDocVisitor::visitPre(DocParamSect *s)
1277 {
1278   if (m_hide) return;
1279   bool hasInOutSpecs = s->hasInOutSpecifier();
1280   bool hasTypeSpecs  = s->hasTypeSpecifier();
1281   switch(s->type())
1282   {
1283     case DocParamSect::Param:
1284       m_t << "\n\\begin{DoxyParams}";
1285       if      (hasInOutSpecs && hasTypeSpecs) m_t << "[2]"; // 2 extra cols
1286       else if (hasInOutSpecs || hasTypeSpecs) m_t << "[1]"; // 1 extra col
1287       m_t << "{";
1288       filter(theTranslator->trParameters());
1289       break;
1290     case DocParamSect::RetVal:
1291       m_t << "\n\\begin{DoxyRetVals}{";
1292       filter(theTranslator->trReturnValues());
1293       break;
1294     case DocParamSect::Exception: 
1295       m_t << "\n\\begin{DoxyExceptions}{";
1296       filter(theTranslator->trExceptions());
1297       break;
1298     case DocParamSect::TemplateParam: 
1299       /* TODO: add this 
1300       filter(theTranslator->trTemplateParam()); break;
1301       */
1302       m_t << "\n\\begin{DoxyTemplParams}{";
1303       filter("Template Parameters");
1304       break;
1305     default:
1306       ASSERT(0);
1307   }
1308   m_t << "}\n";
1309 }
1310
1311 void LatexDocVisitor::visitPost(DocParamSect *s)
1312 {
1313   if (m_hide) return;
1314   switch(s->type())
1315   {
1316     case DocParamSect::Param:
1317       m_t << "\\end{DoxyParams}\n";
1318       break;
1319     case DocParamSect::RetVal:
1320       m_t << "\\end{DoxyRetVals}\n";
1321       break;
1322     case DocParamSect::Exception: 
1323       m_t << "\\end{DoxyExceptions}\n";
1324       break;
1325     case DocParamSect::TemplateParam: 
1326       m_t << "\\end{DoxyTemplParams}\n";
1327       break;
1328     default:
1329       ASSERT(0);
1330   }
1331 }
1332
1333 void LatexDocVisitor::visitPre(DocParamList *pl)
1334 {
1335   if (m_hide) return;
1336   DocParamSect::Type parentType = DocParamSect::Unknown;
1337   DocParamSect *sect = 0;
1338   if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1339   {
1340     parentType = ((DocParamSect*)pl->parent())->type();
1341     sect=(DocParamSect*)pl->parent();
1342   }
1343   bool useTable = parentType==DocParamSect::Param ||
1344                   parentType==DocParamSect::RetVal ||
1345                   parentType==DocParamSect::Exception ||
1346                   parentType==DocParamSect::TemplateParam;
1347   if (!useTable)
1348   {
1349     m_t << "\\item[";
1350   }
1351   if (sect && sect->hasInOutSpecifier())
1352   {
1353     if (pl->direction()!=DocParamSect::Unspecified)
1354     {
1355       m_t << "\\mbox{\\tt ";
1356       if (pl->direction()==DocParamSect::In)
1357       {
1358         m_t << "in";
1359       }
1360       else if (pl->direction()==DocParamSect::Out)
1361       {
1362         m_t << "out";
1363       }
1364       else if (pl->direction()==DocParamSect::InOut)
1365       {
1366         m_t << "in,out";
1367       }
1368       m_t << "} ";
1369     }
1370     if (useTable) m_t << " & ";
1371   }
1372   if (sect && sect->hasTypeSpecifier())
1373   {
1374     QListIterator<DocNode> li(pl->paramTypes());
1375     DocNode *type;
1376     bool first=TRUE;
1377     for (li.toFirst();(type=li.current());++li)
1378     {
1379       if (!first) m_t << " | "; else first=FALSE;
1380       if (type->kind()==DocNode::Kind_Word)
1381       {
1382         visit((DocWord*)type); 
1383       }
1384       else if (type->kind()==DocNode::Kind_LinkedWord)
1385       {
1386         visit((DocLinkedWord*)type); 
1387       }
1388     }
1389     if (useTable) m_t << " & ";
1390   }
1391   m_t << "{\\em ";
1392   //QStrListIterator li(pl->parameters());
1393   //const char *s;
1394   QListIterator<DocNode> li(pl->parameters());
1395   DocNode *param;
1396   bool first=TRUE;
1397   for (li.toFirst();(param=li.current());++li)
1398   {
1399     if (!first) m_t << ","; else first=FALSE;
1400     m_insideItem=TRUE;
1401     if (param->kind()==DocNode::Kind_Word)
1402     {
1403       visit((DocWord*)param); 
1404     }
1405     else if (param->kind()==DocNode::Kind_LinkedWord)
1406     {
1407       visit((DocLinkedWord*)param); 
1408     }
1409     m_insideItem=FALSE;
1410   }
1411   m_t << "}";
1412   if (useTable)
1413   {
1414     m_t << " & ";
1415   }
1416   else
1417   {
1418     m_t << "]";
1419   }
1420 }
1421
1422 void LatexDocVisitor::visitPost(DocParamList *pl)
1423 {
1424   if (m_hide) return;
1425   DocParamSect::Type parentType = DocParamSect::Unknown;
1426   if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1427   {
1428     parentType = ((DocParamSect*)pl->parent())->type();
1429   }
1430   bool useTable = parentType==DocParamSect::Param ||
1431                   parentType==DocParamSect::RetVal ||
1432                   parentType==DocParamSect::Exception ||
1433                   parentType==DocParamSect::TemplateParam;
1434   if (useTable)
1435   {
1436     m_t << "\\\\" << endl
1437         << "\\hline" << endl;
1438   }
1439 }
1440
1441 void LatexDocVisitor::visitPre(DocXRefItem *x)
1442 {
1443   if (m_hide) return;
1444   if (x->title().isEmpty()) return;
1445   m_t << "\\begin{DoxyRefDesc}{";
1446   filter(x->title());
1447   m_t << "}" << endl;
1448   bool anonymousEnum = x->file()=="@";
1449   m_t << "\\item[";
1450   if (Config_getBool("PDF_HYPERLINKS") && !anonymousEnum)
1451   {
1452     m_t << "\\hyperlink{" << stripPath(x->file()) << "_" << x->anchor() << "}{";
1453   }
1454   else
1455   {
1456     m_t << "{\\bf ";
1457   }
1458   m_insideItem=TRUE;
1459   filter(x->title());
1460   m_insideItem=FALSE;
1461   m_t << "}]";
1462 }
1463
1464 void LatexDocVisitor::visitPost(DocXRefItem *x)
1465 {
1466   if (m_hide) return;
1467   if (x->title().isEmpty()) return;
1468   m_t << "\\end{DoxyRefDesc}" << endl;
1469 }
1470
1471 void LatexDocVisitor::visitPre(DocInternalRef *ref)
1472 {
1473   if (m_hide) return;
1474   startLink(0,ref->file(),ref->anchor());
1475 }
1476
1477 void LatexDocVisitor::visitPost(DocInternalRef *ref) 
1478 {
1479   if (m_hide) return;
1480   endLink(0,ref->file(),ref->anchor());
1481 }
1482
1483 void LatexDocVisitor::visitPre(DocCopy *)
1484 {
1485 }
1486
1487 void LatexDocVisitor::visitPost(DocCopy *)
1488 {
1489 }
1490
1491 void LatexDocVisitor::visitPre(DocText *)
1492 {
1493 }
1494
1495 void LatexDocVisitor::visitPost(DocText *)
1496 {
1497 }
1498
1499 void LatexDocVisitor::visitPre(DocHtmlBlockQuote *)
1500 {
1501   if (m_hide) return;
1502   m_t << "\\begin{quote}" << endl;
1503 }
1504
1505 void LatexDocVisitor::visitPost(DocHtmlBlockQuote *)
1506 {
1507   if (m_hide) return;
1508   m_t << "\\end{quote}" << endl;
1509 }
1510
1511 void LatexDocVisitor::visitPre(DocVhdlFlow *)
1512 {
1513   if (m_hide) return;
1514 }
1515
1516 void LatexDocVisitor::visitPost(DocVhdlFlow *)
1517 {
1518   if (m_hide) return;
1519 }
1520
1521 void LatexDocVisitor::visitPre(DocParBlock *)
1522 {
1523   if (m_hide) return;
1524 }
1525
1526 void LatexDocVisitor::visitPost(DocParBlock *)
1527 {
1528   if (m_hide) return;
1529 }
1530
1531 void LatexDocVisitor::filter(const char *str)
1532
1533   filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem);
1534 }
1535
1536 void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
1537 {
1538   if (ref.isEmpty() && Config_getBool("PDF_HYPERLINKS")) // internal PDF link 
1539   {
1540     if (ref.isEmpty()) {
1541       m_t << "\\hyperlink{";
1542       if (!file.isEmpty()) m_t << stripPath(file);
1543       if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
1544       if (!anchor.isEmpty()) m_t << anchor;
1545       m_t << "}{";
1546     }
1547     else
1548     {
1549       QCString *dest;
1550       m_t << "\\href{";
1551       if ((dest=Doxygen::tagDestinationDict[ref])) m_t << *dest << "/";
1552       if (!file.isEmpty()) m_t << file << Doxygen::htmlFileExtension;
1553       if (!anchor.isEmpty()) m_t << "#" << anchor;
1554       m_t << "}{";
1555     }
1556   }
1557   else if (ref.isEmpty()) // internal non-PDF link
1558   {
1559     m_t << "\\doxyref{";
1560   }
1561   else // external link
1562   { 
1563     m_t << "{\\bf ";
1564   }
1565 }
1566
1567 void LatexDocVisitor::endLink(const QCString &ref,const QCString &file,const QCString &anchor)
1568 {
1569   m_t << "}";
1570   if (ref.isEmpty() && !Config_getBool("PDF_HYPERLINKS"))
1571   {
1572     m_t << "{"; 
1573     filter(theTranslator->trPageAbbreviation());
1574     m_t << "}{" << file;
1575     if (!file.isEmpty() && !anchor.isEmpty()) m_t << "_";
1576     m_t << anchor << "}";
1577   }
1578 }
1579
1580 void LatexDocVisitor::pushEnabled()
1581 {
1582   m_enabled.push(new bool(m_hide));
1583 }
1584
1585 void LatexDocVisitor::popEnabled()
1586 {
1587   bool *v=m_enabled.pop();
1588   ASSERT(v!=0);
1589   m_hide = *v;
1590   delete v;
1591 }
1592
1593 void LatexDocVisitor::startDotFile(const QCString &fileName,
1594                                    const QCString &width,
1595                                    const QCString &height,
1596                                    bool hasCaption
1597                                   )
1598 {
1599   QCString baseName=fileName;
1600   int i;
1601   if ((i=baseName.findRev('/'))!=-1)
1602   {
1603     baseName=baseName.right(baseName.length()-i-1);
1604   } 
1605   if ((i=baseName.find('.'))!=-1)
1606   {
1607     baseName=baseName.left(i);
1608   }
1609   baseName.prepend("dot_");
1610   QCString outDir = Config_getString("LATEX_OUTPUT");
1611   QCString name = fileName;
1612   writeDotGraphFromFile(name,outDir,baseName,GOF_EPS);
1613   if (hasCaption)
1614   {
1615     m_t << "\n\\begin{DoxyImage}\n";
1616   }
1617   else
1618   {
1619     m_t << "\n\\begin{DoxyImageNoCaption}\n"
1620            "  \\mbox{";
1621   }
1622   m_t << "\\includegraphics";
1623   if (!width.isEmpty())
1624   {
1625     m_t << "[width=" << width << "]";
1626   }
1627   else if (!height.isEmpty())
1628   {
1629     m_t << "[height=" << height << "]";
1630   }
1631   else
1632   {
1633     m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
1634   }
1635   m_t << "{" << baseName;
1636   //if (Config_getBool("USE_PDFLATEX"))
1637   //{
1638   //  m_t << ".pdf";
1639   //}
1640   //else
1641   //{
1642   //  m_t << ".eps";
1643   //}
1644   m_t << "}";
1645
1646   if (hasCaption)
1647   {
1648     m_t << "\n\\caption{";
1649   }
1650 }
1651
1652 void LatexDocVisitor::endDotFile(bool hasCaption)
1653 {
1654   if (m_hide) return;
1655   m_t << "}\n"; // end caption or mbox
1656   if (hasCaption)
1657   {
1658     m_t << "\\end{DoxyImage}\n";
1659   }
1660   else
1661   {
1662     m_t << "\\end{DoxyImageNoCaption}\n";
1663   }
1664 }
1665
1666 void LatexDocVisitor::startMscFile(const QCString &fileName,
1667                                    const QCString &width,
1668                                    const QCString &height,
1669                                    bool hasCaption
1670                                   )
1671 {
1672   QCString baseName=fileName;
1673   int i;
1674   if ((i=baseName.findRev('/'))!=-1)
1675   {
1676     baseName=baseName.right(baseName.length()-i-1);
1677   } 
1678   if ((i=baseName.find('.'))!=-1)
1679   {
1680     baseName=baseName.left(i);
1681   }
1682   baseName.prepend("msc_");
1683
1684   QCString outDir = Config_getString("LATEX_OUTPUT");
1685   writeMscGraphFromFile(fileName,outDir,baseName,MSC_EPS); 
1686   if (hasCaption)
1687   {
1688     m_t << "\n\\begin{DoxyImage}\n";
1689   }
1690   else
1691   {
1692     m_t << "\n\\begin{DoxyImageNoCaption}\n"
1693            "  \\mbox{";
1694   }
1695   m_t << "\\includegraphics";
1696   if (!width.isEmpty())
1697   {
1698     m_t << "[width=" << width << "]";
1699   }
1700   else if (!height.isEmpty())
1701   {
1702     m_t << "[height=" << height << "]";
1703   }
1704   else
1705   {
1706     m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
1707   }
1708   m_t << "{" << baseName;
1709   //if (Config_getBool("USE_PDFLATEX"))
1710   //{
1711   //  m_t << ".pdf";
1712   //}
1713   //else
1714   //{
1715   //  m_t << ".eps";
1716   //}
1717   m_t << "}";
1718
1719   if (hasCaption)
1720   {
1721     m_t << "\n\\caption{";
1722   }
1723 }
1724
1725 void LatexDocVisitor::endMscFile(bool hasCaption)
1726 {
1727   if (m_hide) return;
1728   m_t << "}\n"; // end caption or mbox
1729   if (hasCaption)
1730   {
1731     m_t << "\\end{DoxyImage}\n";
1732   }
1733   else
1734   {
1735     m_t << "\\end{DoxyImageNoCaption}\n";
1736   }
1737 }
1738
1739
1740 void LatexDocVisitor::writeMscFile(const QCString &baseName)
1741 {
1742   QCString shortName = baseName;
1743   int i;
1744   if ((i=shortName.findRev('/'))!=-1)
1745   {
1746     shortName=shortName.right(shortName.length()-i-1);
1747   } 
1748   QCString outDir = Config_getString("LATEX_OUTPUT");
1749   writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_EPS);
1750   m_t << "\n\\begin{DoxyImageNoCaption}"
1751          "  \\mbox{\\includegraphics";
1752   m_t << "{" << shortName << "}";
1753   m_t << "}\n"; // end mbox
1754   m_t << "\\end{DoxyImageNoCaption}\n";
1755 }
1756
1757
1758 void LatexDocVisitor::startDiaFile(const QCString &fileName,
1759                                    const QCString &width,
1760                                    const QCString &height,
1761                                    bool hasCaption
1762                                   )
1763 {
1764   QCString baseName=fileName;
1765   int i;
1766   if ((i=baseName.findRev('/'))!=-1)
1767   {
1768     baseName=baseName.right(baseName.length()-i-1);
1769   }
1770   if ((i=baseName.find('.'))!=-1)
1771   {
1772     baseName=baseName.left(i);
1773   }
1774   baseName.prepend("dia_");
1775
1776   QCString outDir = Config_getString("LATEX_OUTPUT");
1777   writeDiaGraphFromFile(fileName,outDir,baseName,DIA_EPS);
1778   if (hasCaption)
1779   {
1780     m_t << "\n\\begin{DoxyImage}\n";
1781   }
1782   else
1783   {
1784     m_t << "\n\\begin{DoxyImageNoCaption}\n"
1785            "  \\mbox{";
1786   }
1787   m_t << "\\includegraphics";
1788   if (!width.isEmpty())
1789   {
1790     m_t << "[width=" << width << "]";
1791   }
1792   else if (!height.isEmpty())
1793   {
1794     m_t << "[height=" << height << "]";
1795   }
1796   else
1797   {
1798     m_t << "[width=\\textwidth,height=\\textheight/2,keepaspectratio=true]";
1799   }
1800   m_t << "{" << baseName;
1801   //if (Config_getBool("USE_PDFLATEX"))
1802   //{
1803   //  m_t << ".pdf";
1804   //}
1805   //else
1806   //{
1807   //  m_t << ".eps";
1808   //}
1809   m_t << "}";
1810
1811   if (hasCaption)
1812   {
1813     m_t << "\n\\caption{";
1814   }
1815 }
1816
1817 void LatexDocVisitor::endDiaFile(bool hasCaption)
1818 {
1819   if (m_hide) return;
1820   m_t << "}\n"; // end caption or mbox
1821   if (hasCaption)
1822   {
1823     m_t << "\\end{DoxyImage}\n";
1824   }
1825   else
1826   {
1827     m_t << "\\end{DoxyImageNoCaption}\n";
1828   }
1829 }
1830
1831
1832 void LatexDocVisitor::writeDiaFile(const QCString &baseName)
1833 {
1834   QCString shortName = baseName;
1835   int i;
1836   if ((i=shortName.findRev('/'))!=-1)
1837   {
1838     shortName=shortName.right(shortName.length()-i-1);
1839   }
1840   QCString outDir = Config_getString("LATEX_OUTPUT");
1841   writeDiaGraphFromFile(baseName+".dia",outDir,shortName,DIA_EPS);
1842   m_t << "\n\\begin{DoxyImageNoCaption}"
1843          "  \\mbox{\\includegraphics";
1844   m_t << "{" << shortName << "}";
1845   m_t << "}\n"; // end mbox
1846   m_t << "\\end{DoxyImageNoCaption}\n";
1847 }
1848
1849 void LatexDocVisitor::writePlantUMLFile(const QCString &baseName)
1850 {
1851   QCString shortName = baseName;
1852   int i;
1853   if ((i=shortName.findRev('/'))!=-1)
1854   {
1855     shortName=shortName.right(shortName.length()-i-1);
1856   }
1857   QCString outDir = Config_getString("LATEX_OUTPUT");
1858   generatePlantUMLOutput(baseName,outDir,PUML_EPS);
1859   m_t << "\n\\begin{DoxyImageNoCaption}"
1860          "  \\mbox{\\includegraphics";
1861   m_t << "{" << shortName << "}";
1862   m_t << "}\n"; // end mbox
1863   m_t << "\\end{DoxyImageNoCaption}\n";
1864 }
1865