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