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