Imported Upstream version 1.8.15
[platform/upstream/doxygen.git] / src / latexgen.cpp
1 /******************************************************************************
2  *
3  * 
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 #include <stdlib.h>
19
20 #include <qdir.h>
21 #include "latexgen.h"
22 #include "config.h"
23 #include "message.h"
24 #include "doxygen.h"
25 #include "util.h"
26 #include "diagram.h"
27 #include "language.h"
28 #include "version.h"
29 #include "dot.h"
30 #include "pagedef.h"
31 #include "docparser.h"
32 #include "latexdocvisitor.h"
33 #include "dirdef.h"
34 #include "cite.h"
35 #include "groupdef.h"
36 #include "classlist.h"
37 #include "namespacedef.h"
38 #include "filename.h"
39 #include "resourcemgr.h"
40
41 static bool DoxyCodeOpen = FALSE;
42 static bool DoxyCodeLineOpen = FALSE;
43 //-------------------------------
44
45 LatexCodeGenerator::LatexCodeGenerator(FTextStream &t,const QCString &relPath,const QCString &sourceFileName)
46   : m_relPath(relPath), m_sourceFileName(sourceFileName), m_col(0)
47 {
48   m_prettyCode=Config_getBool(LATEX_SOURCE_CODE);
49   setTextStream(t);
50 }
51
52 LatexCodeGenerator::LatexCodeGenerator() : m_streamSet(FALSE), m_col(0)
53 {
54   m_prettyCode=Config_getBool(LATEX_SOURCE_CODE);
55 }
56
57 void LatexCodeGenerator::setTextStream(FTextStream &t)
58 {
59   m_streamSet = t.device()!=0;
60   m_t.setDevice(t.device());
61 }
62
63 void LatexCodeGenerator::setRelativePath(const QCString &path)
64 {
65   m_relPath = path;
66 }
67
68 void LatexCodeGenerator::setSourceFileName(const QCString &name)
69 {
70   m_sourceFileName = name;
71 }
72
73 void LatexCodeGenerator::codify(const char *str)
74 {
75   if (str)
76   {
77     const char *p=str;
78     char c;
79     //char cs[5];
80     int spacesToNextTabStop;
81     static int tabSize = Config_getInt(TAB_SIZE);
82     static char *result = NULL;
83     static int lresult = 0;
84     int i;
85     while ((c=*p))
86     {
87       switch(c)
88       {
89         case 0x0c: p++;  // remove ^L
90                    break;
91         case ' ':  m_t <<" ";
92                    m_col++;
93                    p++;
94                    break;
95         case '^':  m_t <<"\\string^";
96                    m_col++;
97                    p++;
98                    break;
99         case '\t': spacesToNextTabStop =
100                          tabSize - (m_col%tabSize);
101                    for (i = 0; i < spacesToNextTabStop; i++) m_t <<" ";
102                    m_col+=spacesToNextTabStop;
103                    p++;
104                    break;
105         case '\n': (usedTableLevels()>0 && !DoxyCodeOpen) ? m_t << "\\newline\n" : m_t << '\n'; m_col=0; p++;
106                    break;
107         default:
108                    i=0;
109
110 #undef  COPYCHAR
111 // helper macro to copy a single utf8 character, dealing with multibyte chars.
112 #define COPYCHAR() do {                                           \
113                      if (lresult < (i + 5))                       \
114                      {                                            \
115                        lresult += 512;                            \
116                        result = (char *)realloc(result, lresult); \
117                      }                                            \
118                      result[i++]=c; p++;                          \
119                      if (c<0) /* multibyte utf-8 character */     \
120                      {                                            \
121                        /* 1xxx.xxxx: >=2 byte character */        \
122                        result[i++]=*p++;                          \
123                        if (((uchar)c&0xE0)==0xE0)                 \
124                        {                                          \
125                          /* 111x.xxxx: >=3 byte character */      \
126                          result[i++]=*p++;                        \
127                        }                                          \
128                        if (((uchar)c&0xF0)==0xF0)                 \
129                        {                                          \
130                          /* 1111.xxxx: 4 byte character */        \
131                          result[i++]=*p++;                        \
132                        }                                          \
133                      }                                            \
134                      m_col++;                                     \
135                    } while(0)
136
137                    // gather characters until we find whitespace or another special character
138                    COPYCHAR();
139                    while ((c=*p) &&
140                           c!=0x0c && c!='\t' && c!='\n' && c!=' ' && c!='^'
141                          )
142                    {
143                      COPYCHAR();
144                    }
145                    result[i]=0; // add terminator
146                    //if (m_prettyCode)
147                    //{
148                      filterLatexString(m_t,result,FALSE,TRUE);
149                    //}
150                    //else
151                    //{
152                    //  t << result;
153                    //}
154                    break;
155       }
156     }
157   }
158 }
159
160
161 void LatexCodeGenerator::writeCodeLink(const char *ref,const char *f,
162                                    const char *anchor,const char *name,
163                                    const char *)
164 {
165   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
166   static bool usePDFLatex   = Config_getBool(USE_PDFLATEX);
167   int l = qstrlen(name);
168   if (!ref && usePDFLatex && pdfHyperlinks)
169   {
170     m_t << "\\mbox{\\hyperlink{";
171     if (f) m_t << stripPath(f);
172     if (f && anchor) m_t << "_"; 
173     if (anchor) m_t << anchor; 
174     m_t << "}{";
175     codify(name);
176     m_t << "}}";
177   }
178   else
179   {
180     codify(name);
181   }
182   m_col+=l;
183 }
184
185 void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,const char *anchor,int l)
186 {
187   static bool usePDFLatex = Config_getBool(USE_PDFLATEX);
188   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
189   if (!DoxyCodeLineOpen)
190   {
191     m_t << "\\DoxyCodeLine{";
192     DoxyCodeLineOpen = TRUE;
193   }
194   if (m_prettyCode)
195   {
196     QCString lineNumber;
197     lineNumber.sprintf("%05d",l);
198
199     if (fileName && !m_sourceFileName.isEmpty())
200     {
201       QCString lineAnchor;
202       lineAnchor.sprintf("_l%05d",l);
203       lineAnchor.prepend(stripExtensionGeneral(m_sourceFileName, ".tex"));
204       //if (!m_prettyCode) return;
205       if (usePDFLatex && pdfHyperlinks)
206       {
207         m_t << "\\Hypertarget{" << stripPath(lineAnchor) << "}";
208       }
209       writeCodeLink(ref,fileName,anchor,lineNumber,0);
210     }
211     else
212     {
213       codify(lineNumber);
214     }
215     m_t << " ";
216   }
217   else
218   {
219     m_t << l << " ";
220   }
221 }
222
223
224 void LatexCodeGenerator::startCodeLine(bool)
225 {
226   m_col=0;
227   if (!DoxyCodeLineOpen)
228   {
229     m_t << "\\DoxyCodeLine{";
230     DoxyCodeLineOpen = TRUE;
231   }
232 }
233
234 void LatexCodeGenerator::endCodeLine()
235 {
236   if (DoxyCodeLineOpen)
237   {
238     m_t << "}";
239     DoxyCodeLineOpen = FALSE;
240   }
241   codify("\n");
242 }
243
244 void LatexCodeGenerator::startFontClass(const char *name)
245 {
246   m_t << "\\textcolor{" << name << "}{";
247 }
248
249 void LatexCodeGenerator::endFontClass()
250 {
251   m_t << "}";
252 }
253
254 void LatexCodeGenerator::setDoxyCodeOpen(bool val)
255 {
256   DoxyCodeOpen = val;
257 }
258
259 //-------------------------------
260
261 LatexGenerator::LatexGenerator() : OutputGenerator()
262 {
263   dir=Config_getString(LATEX_OUTPUT);
264   //printf("LatexGenerator::LatexGenerator() insideTabbing=FALSE\n");
265   insideTabbing=FALSE;
266   firstDescItem=TRUE;
267   disableLinks=FALSE;
268   m_indent=0;
269   templateMemberItem = FALSE;
270   m_prettyCode=Config_getBool(LATEX_SOURCE_CODE);
271 }
272
273 LatexGenerator::~LatexGenerator()
274 {
275 }
276
277 static void writeLatexMakefile()
278 {
279   bool generateBib = !Doxygen::citeDict->isEmpty();
280   QCString dir=Config_getString(LATEX_OUTPUT);
281   QCString fileName=dir+"/Makefile";
282   QFile file(fileName);
283   if (!file.open(IO_WriteOnly))
284   {
285     err("Could not open file %s for writing\n",fileName.data());
286     exit(1);
287   }
288   // inserted by KONNO Akihisa <konno@researchers.jp> 2002-03-05
289   QCString latex_command = theTranslator->latexCommandName();
290   QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME);
291   // end insertion by KONNO Akihisa <konno@researchers.jp> 2002-03-05
292   FTextStream t(&file);
293   if (!Config_getBool(USE_PDFLATEX)) // use plain old latex
294   {
295     t << "LATEX_CMD=" << latex_command << endl
296       << endl
297       << "all: refman.dvi" << endl
298       << endl
299       << "ps: refman.ps" << endl
300       << endl
301       << "pdf: refman.pdf" << endl
302       << endl
303       << "ps_2on1: refman_2on1.ps" << endl
304       << endl
305       << "pdf_2on1: refman_2on1.pdf" << endl
306       << endl
307       << "refman.ps: refman.dvi" << endl
308       << "\tdvips -o refman.ps refman.dvi" << endl
309       << endl;
310     t << "refman.pdf: refman.ps" << endl;
311     t << "\tps2pdf refman.ps refman.pdf" << endl << endl;
312     t << "refman.dvi: clean refman.tex doxygen.sty" << endl
313       << "\techo \"Running latex...\"" << endl
314       << "\t$(LATEX_CMD) refman.tex" << endl
315       << "\techo \"Running makeindex...\"" << endl
316       << "\t" << mkidx_command << " refman.idx" << endl;
317     if (generateBib)
318     {
319       t << "\techo \"Running bibtex...\"" << endl;
320       t << "\tbibtex refman" << endl;
321       t << "\techo \"Rerunning latex....\"" << endl;
322       t << "\t$(LATEX_CMD) refman.tex" << endl;
323     }
324     t << "\techo \"Rerunning latex....\"" << endl
325       << "\t$(LATEX_CMD) refman.tex" << endl
326       << "\tlatex_count=8 ; \\" << endl
327       << "\twhile egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\\" << endl
328       << "\t    do \\" << endl
329       << "\t      echo \"Rerunning latex....\" ;\\" << endl
330       << "\t      $(LATEX_CMD) refman.tex ; \\" << endl
331       << "\t      latex_count=`expr $$latex_count - 1` ;\\" << endl
332       << "\t    done" << endl
333       << "\t" << mkidx_command << " refman.idx" << endl
334       << "\t$(LATEX_CMD) refman.tex" << endl << endl
335       << "refman_2on1.ps: refman.ps" << endl
336       << "\tpsnup -2 refman.ps >refman_2on1.ps" << endl
337       << endl
338       << "refman_2on1.pdf: refman_2on1.ps" << endl
339       << "\tps2pdf refman_2on1.ps refman_2on1.pdf" << endl;
340   }
341   else // use pdflatex for higher quality output
342   {
343     t << "LATEX_CMD=" << latex_command << endl
344       << endl;
345     t << "all: refman.pdf" << endl << endl
346       << "pdf: refman.pdf" << endl << endl;
347     t << "refman.pdf: clean refman.tex" << endl;
348     t << "\t$(LATEX_CMD) refman" << endl;
349     t << "\t" << mkidx_command << " refman.idx" << endl;
350     if (generateBib)
351     {
352       t << "\tbibtex refman" << endl;
353       t << "\t$(LATEX_CMD) refman" << endl;
354     }
355     t << "\t$(LATEX_CMD) refman" << endl
356       << "\tlatex_count=8 ; \\" << endl
357       << "\twhile egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\\" << endl
358       << "\t    do \\" << endl
359       << "\t      echo \"Rerunning latex....\" ;\\" << endl
360       << "\t      $(LATEX_CMD) refman ;\\" << endl
361       << "\t      latex_count=`expr $$latex_count - 1` ;\\" << endl
362       << "\t    done" << endl
363       << "\t" << mkidx_command << " refman.idx" << endl
364       << "\t$(LATEX_CMD) refman" << endl << endl;
365   }
366
367   t << endl
368     << "clean:" << endl
369     << "\trm -f " 
370     << "*.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf" << endl;
371 }
372
373 static void writeMakeBat()
374 {
375 #if defined(_MSC_VER)
376   QCString dir=Config_getString(LATEX_OUTPUT);
377   QCString fileName=dir+"/make.bat";
378   QCString latex_command = theTranslator->latexCommandName();
379   QCString mkidx_command = Config_getString(MAKEINDEX_CMD_NAME);
380   QFile file(fileName);
381   bool generateBib = !Doxygen::citeDict->isEmpty();
382   if (!file.open(IO_WriteOnly))
383   {
384     err("Could not open file %s for writing\n",fileName.data());
385     exit(1);
386   }
387   FTextStream t(&file);
388   t << "set Dir_Old=%cd%\n";
389   t << "cd /D %~dp0\n\n";
390   t << "del /s /f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf\n\n";
391   if (!Config_getBool(USE_PDFLATEX)) // use plain old latex
392   {
393     t << "set LATEX_CMD=" << latex_command << "\n";
394     t << "%LATEX_CMD% refman.tex\n";
395     t << "echo ----\n";
396     t << mkidx_command << " refman.idx\n";
397     if (generateBib)
398     {
399       t << "bibtex refman\n";
400       t << "echo ----\n";
401       t << "\t%LATEX_CMD% refman.tex\n";
402     }
403     t << "setlocal enabledelayedexpansion\n";
404     t << "set count=8\n";
405     t << ":repeat\n";
406     t << "set content=X\n";
407     t << "for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun LaTeX\" refman.log' ) do set content=\"%%~T\"\n";
408     t << "if !content! == X for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun to get cross-references right\" refman.log' ) do set content=\"%%~T\"\n";
409     t << "if !content! == X goto :skip\n";
410     t << "set /a count-=1\n";
411     t << "if !count! EQU 0 goto :skip\n\n";
412     t << "echo ----\n";
413     t << "%LATEX_CMD% refman.tex\n";
414     t << "goto :repeat\n";
415     t << ":skip\n";
416     t << "endlocal\n";
417     t << mkidx_command << " refman.idx\n";
418     t << "%LATEX_CMD% refman.tex\n";
419     t << "dvips -o refman.ps refman.dvi\n";
420     t << "gswin32c -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite "
421          "-sOutputFile=refman.pdf -c save pop -f refman.ps\n";
422   }
423   else // use pdflatex
424   {
425     t << "set LATEX_CMD=" << latex_command << "\n";
426     t << "%LATEX_CMD% refman\n";
427     t << "echo ----\n";
428     t << mkidx_command << " refman.idx\n";
429     if (generateBib)
430     {
431       t << "bibtex refman" << endl;
432       t << "%LATEX_CMD% refman" << endl;
433     }
434     t << "echo ----\n";
435     t << "%LATEX_CMD% refman\n\n";
436     t << "setlocal enabledelayedexpansion\n";
437     t << "set count=8\n";
438     t << ":repeat\n";
439     t << "set content=X\n";
440     t << "for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun LaTeX\" refman.log' ) do set content=\"%%~T\"\n";
441     t << "if !content! == X for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun to get cross-references right\" refman.log' ) do set content=\"%%~T\"\n";
442     t << "if !content! == X goto :skip\n";
443     t << "set /a count-=1\n";
444     t << "if !count! EQU 0 goto :skip\n\n";
445     t << "echo ----\n";
446     t << "%LATEX_CMD% refman\n";
447     t << "goto :repeat\n";
448     t << ":skip\n";
449     t << "endlocal\n";
450     t << mkidx_command << " refman.idx\n";
451     t << "%LATEX_CMD% refman\n";
452     t << "cd /D %Dir_Old%\n";
453     t << "set Dir_Old=\n";
454   }
455 #endif
456 }
457
458 void LatexGenerator::init()
459 {
460
461   QCString dir=Config_getString(LATEX_OUTPUT);
462   QDir d(dir);
463   if (!d.exists() && !d.mkdir(dir))
464   {
465     err("Could not create output directory %s\n",dir.data());
466     exit(1);
467   }
468
469   writeLatexMakefile();
470   writeMakeBat();
471
472   createSubDirs(d);
473 }
474
475 static void writeDefaultHeaderPart1(FTextStream &t)
476 {
477   // part 1
478
479   // Handle batch mode
480   if (Config_getBool(LATEX_BATCHMODE))
481     t << "\\batchmode\n";
482
483   // to overcome  problems wit too many open files
484   t << "\\let\\mypdfximage\\pdfximage"
485        "\\def\\pdfximage{\\immediate\\mypdfximage}";
486
487   // Set document class depending on configuration
488   QCString documentClass;
489   if (Config_getBool(COMPACT_LATEX))
490     documentClass = "article";
491   else
492     documentClass = "book";
493   t << "\\documentclass[twoside]{" << documentClass << "}\n"
494        "\n";
495
496   // Load required packages
497   t << "% Packages required by doxygen\n"
498        "\\usepackage{fixltx2e}\n" // for \textsubscript
499        "\\usepackage{calc}\n"
500        "\\usepackage{doxygen}\n";
501   QStrList extraLatexStyle = Config_getList(LATEX_EXTRA_STYLESHEET);
502   for (uint i=0; i<extraLatexStyle.count(); ++i)
503   {
504     QCString fileName(extraLatexStyle.at(i));
505     if (!fileName.isEmpty())
506     {
507       QFileInfo fi(fileName);
508       if (fi.exists())
509       {
510         if (checkExtension(fi.fileName().data(), latexStyleExtension))
511         {
512           // strip the extension, it will be added by the usepackage in the tex conversion process
513           t << "\\usepackage{" << stripExtensionGeneral(fi.fileName().data(), latexStyleExtension) << "}\n";
514         }
515         else
516         {
517           t << "\\usepackage{" << fi.fileName().utf8() << "}\n";
518         }
519       }
520     }
521   }
522   t << "\\usepackage{graphicx}\n"
523        "\\usepackage[utf8]{inputenc}\n"
524        "\\usepackage{makeidx}\n"
525        "\\usepackage{multicol}\n"
526        "\\usepackage{multirow}\n"
527        "\\PassOptionsToPackage{warn}{textcomp}\n"
528        "\\usepackage{textcomp}\n"
529        "\\usepackage[nointegrals]{wasysym}\n"
530        "\\usepackage[table]{xcolor}\n"
531        "\\usepackage{ifpdf,ifxetex}\n"
532        "\n";
533
534   // Language support
535   QCString languageSupport = theTranslator->latexLanguageSupportCommand();
536   if (!languageSupport.isEmpty())
537   {
538     t << "% NLS support packages\n"
539       << languageSupport
540       << "\n";
541   }
542
543   // Define default fonts
544   t << "% Font selection\n";
545   QCString fontenc = theTranslator->latexFontenc();
546   if (!fontenc.isEmpty())
547   {
548     t << "\\usepackage[" << fontenc << "]{fontenc}\n";
549   }
550   t << "\\usepackage[scaled=.90]{helvet}\n"
551        "\\usepackage{courier}\n"
552        "\\usepackage{amssymb}\n"
553        "\\usepackage{sectsty}\n"
554        "\\renewcommand{\\familydefault}{\\sfdefault}\n"
555        "\\allsectionsfont{%\n"
556        "  \\fontseries{bc}\\selectfont%\n"
557        "  \\color{darkgray}%\n"
558        "}\n"
559        "\\renewcommand{\\DoxyLabelFont}{%\n"
560        "  \\fontseries{bc}\\selectfont%\n"
561        "  \\color{darkgray}%\n"
562        "}\n"
563        "\\newcommand{\\+}{\\discretionary{\\mbox{\\scriptsize$\\hookleftarrow$}}{}{}}\n"
564        "\n";
565
566    QCString emojiDir=Config_getString(LATEX_EMOJI_DIRECTORY);
567    if (emojiDir.isEmpty()) emojiDir = ".";
568    emojiDir = substitute(emojiDir,"\\","/");
569    t << "% Arguments of doxygenemoji:\n"
570         "% 1) ':<text>:' form of the emoji, already \"LaTeX\"-escaped\n"
571         "% 2) file with the name of the emoji without the .png extension\n"
572         "% in case image exist use this otherwise use the ':<text>:' form\n";
573    t << "\\newcommand{\\doxygenemoji}[2]{%\n"
574         "  \\IfFileExists{" << emojiDir << "/#2.png}{\\raisebox{-0.1em}{\\includegraphics[height=0.9em]{" << emojiDir << "/#2.png}}}{#1}%\n"
575         "}\n";
576
577   // Define page & text layout
578   QCString paperName=Config_getEnum(PAPER_TYPE);
579   // "a4wide" package is obsolete (see bug 563698)
580   t << "% Page & text layout\n"
581        "\\usepackage{geometry}\n"
582        "\\geometry{%\n"
583        "  " << paperName << "paper,%\n"
584        "  top=2.5cm,%\n"
585        "  bottom=2.5cm,%\n"
586        "  left=2.5cm,%\n"
587        "  right=2.5cm%\n"
588        "}\n";
589   // \sloppy is obsolete (see bug 563698)
590   // Allow a bit of overflow to go unnoticed by other means
591   t << "\\tolerance=750\n"
592        "\\hfuzz=15pt\n"
593        "\\hbadness=750\n"
594        "\\setlength{\\emergencystretch}{15pt}\n"
595        "\\setlength{\\parindent}{0cm}\n"
596        "\\newcommand{\\doxynormalparskip}{\\setlength{\\parskip}{3ex plus 2ex minus 2ex}}\n"
597        "\\newcommand{\\doxytocparskip}{\\setlength{\\parskip}{1ex plus 0ex minus 0ex}}\n"
598        "\\doxynormalparskip\n";
599   // Redefine paragraph/subparagraph environments, using sectsty fonts
600   t << "\\makeatletter\n"
601        "\\renewcommand{\\paragraph}{%\n"
602        "  \\@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{%\n"
603        "    \\normalfont\\normalsize\\bfseries\\SS@parafont%\n"
604        "  }%\n"
605        "}\n"
606        "\\renewcommand{\\subparagraph}{%\n"
607        "  \\@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{%\n"
608        "    \\normalfont\\normalsize\\bfseries\\SS@subparafont%\n"
609        "  }%\n"
610        "}\n"
611        "\\makeatother\n"
612        "\n";
613
614   // Headers & footers
615   QGString genString;
616   QCString generatedBy;
617   static bool timeStamp = Config_getBool(LATEX_TIMESTAMP);
618   FTextStream tg(&genString);
619   if (timeStamp)
620   {
621     generatedBy = theTranslator->trGeneratedAt(dateToString(TRUE), Config_getString(PROJECT_NAME));
622   }
623   else
624   {
625     generatedBy = theTranslator->trGeneratedBy();
626   }
627   filterLatexString(tg, generatedBy, FALSE,FALSE,FALSE);
628   t << "% Headers & footers\n"
629        "\\usepackage{fancyhdr}\n"
630        "\\pagestyle{fancyplain}\n"
631        "\\fancyhead[LE]{\\fancyplain{}{\\bfseries\\thepage}}\n"
632        "\\fancyhead[CE]{\\fancyplain{}{}}\n"
633        "\\fancyhead[RE]{\\fancyplain{}{\\bfseries\\leftmark}}\n"
634        "\\fancyhead[LO]{\\fancyplain{}{\\bfseries\\rightmark}}\n"
635        "\\fancyhead[CO]{\\fancyplain{}{}}\n"
636        "\\fancyhead[RO]{\\fancyplain{}{\\bfseries\\thepage}}\n"
637        "\\fancyfoot[LE]{\\fancyplain{}{}}\n"
638        "\\fancyfoot[CE]{\\fancyplain{}{}}\n"
639        "\\fancyfoot[RE]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n"
640        "\\fancyfoot[LO]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n"
641        "\\fancyfoot[CO]{\\fancyplain{}{}}\n"
642        "\\fancyfoot[RO]{\\fancyplain{}{}}\n"
643        "\\renewcommand{\\footrulewidth}{0.4pt}\n";
644   if (!Config_getBool(COMPACT_LATEX))
645   {
646     t << "\\renewcommand{\\chaptermark}[1]{%\n"
647          "  \\markboth{#1}{}%\n"
648          "}\n";
649   }
650   t << "\\renewcommand{\\sectionmark}[1]{%\n"
651        "  \\markright{\\thesection\\ #1}%\n"
652        "}\n"
653        "\n";
654
655   // ToC, LoF, LoT, bibliography, and index
656   t << "% Indices & bibliography\n"
657        "\\usepackage{natbib}\n"
658        "\\usepackage[titles]{tocloft}\n"
659        "\\setcounter{tocdepth}{3}\n"
660        "\\setcounter{secnumdepth}{5}\n";
661
662   QCString latex_mkidx_command = Config_getString(LATEX_MAKEINDEX_CMD);
663   if (!latex_mkidx_command.isEmpty())
664   {
665     if (latex_mkidx_command[0] == '\\')
666       t << latex_mkidx_command << "\n";
667     else
668       t << '\\' << latex_mkidx_command << "\n";
669   }
670   else
671   {
672     t << "\\makeindex\n";
673   }
674   t << "\n";
675
676   writeExtraLatexPackages(t);
677   writeLatexSpecialFormulaChars(t);
678
679   // Hyperlinks
680   bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
681   if (pdfHyperlinks)
682   {
683     t << "% Hyperlinks (required, but should be loaded last)\n"
684          "\\ifpdf\n"
685          "  \\usepackage[pdftex,pagebackref=true]{hyperref}\n"
686          "\\else\n"
687          "  \\ifxetex\n"
688          "    \\usepackage[pagebackref=true]{hyperref}\n"
689          "  \\else\n"
690          "    \\usepackage[ps2pdf,pagebackref=true]{hyperref}\n"
691          "  \\fi\n"
692          "\\fi\n"
693          "\n"
694          "\\hypersetup{%\n"
695          "  colorlinks=true,%\n"
696          "  linkcolor=blue,%\n"
697          "  citecolor=blue,%\n"
698          "  unicode%\n"
699          "}\n"
700          "\n";
701   }
702
703   // Custom commands used by the header
704   t << "% Custom commands\n"
705        "\\newcommand{\\clearemptydoublepage}{%\n"
706        "  \\newpage{\\pagestyle{empty}\\cleardoublepage}%\n"
707        "}\n"
708        "\n";
709
710   // caption style definition
711   t << "\\usepackage{caption}\n"
712     << "\\captionsetup{labelsep=space,justification=centering,font={bf},singlelinecheck=off,skip=4pt,position=top}\n\n";
713
714
715   // in page table of contents
716   t << "\\usepackage{etoc}\n"
717        "\\etocsettocstyle{\\doxytocparskip}{\\doxynormalparskip}\n";
718
719   // prevent numbers overlap the titles in toc
720   t << "\\renewcommand{\\numberline}[1]{#1~}\n";
721
722   // End of preamble, now comes the document contents
723   t << "%===== C O N T E N T S =====\n"
724        "\n"
725        "\\begin{document}\n";
726   QCString documentPre = theTranslator->latexDocumentPre();
727   if (!documentPre.isEmpty())
728   {
729     t << documentPre;
730   }
731   t << "\n";
732
733   // Front matter
734   t << "% Titlepage & ToC\n";
735   bool usePDFLatex = Config_getBool(USE_PDFLATEX);
736   if (pdfHyperlinks && usePDFLatex)
737   {
738     // To avoid duplicate page anchors due to reuse of same numbers for
739     // the index (be it as roman numbers)
740     t << "\\hypersetup{pageanchor=false,\n"
741     //  << "             bookmarks=true,\n" // commented out to prevent warning
742       << "             bookmarksnumbered=true,\n"
743       << "             pdfencoding=unicode\n"
744       << "            }\n";
745   }
746   t << "\\pagenumbering{alph}\n"
747        "\\begin{titlepage}\n"
748        "\\vspace*{7cm}\n"
749        "\\begin{center}%\n"
750        "{\\Large ";
751 }
752
753 static void writeDefaultHeaderPart2(FTextStream &t)
754 {
755   // part 2
756   // Finalize project name
757   t << "}\\\\\n"
758        "\\vspace*{1cm}\n"
759        "{\\large ";
760 }
761
762 static void writeDefaultHeaderPart3(FTextStream &t)
763 {
764   // part 3
765   // Finalize project number
766   t << " Doxygen " << versionString << "}\\\\\n";
767   if (Config_getBool(LATEX_TIMESTAMP))
768     t << "\\vspace*{0.5cm}\n"
769          "{\\small " << dateToString(TRUE) << "}\\\\\n";
770   t << "\\end{center}\n"
771        "\\end{titlepage}\n";
772   bool compactLatex = Config_getBool(COMPACT_LATEX);
773   if (!compactLatex)
774     t << "\\clearemptydoublepage\n";
775   t << "\\pagenumbering{roman}\n";
776
777   // ToC
778   t << "\\tableofcontents\n";
779   if (!compactLatex)
780     t << "\\clearemptydoublepage\n";
781   t << "\\pagenumbering{arabic}\n";
782   bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
783   bool usePDFLatex   = Config_getBool(USE_PDFLATEX);
784   if (pdfHyperlinks && usePDFLatex)
785   {
786     // re-enable anchors again
787     t << "\\hypersetup{pageanchor=true}\n";
788   }
789   t << "\n"
790        "%--- Begin generated contents ---\n";
791 }
792
793 static void writeDefaultStyleSheet(FTextStream &t)
794 {
795   t << ResourceMgr::instance().getAsString("doxygen.sty");
796 }
797
798 static void writeDefaultFooter(FTextStream &t)
799 {
800   t << "%--- End generated contents ---\n"
801        "\n";
802
803   // Bibliography
804   Doxygen::citeDict->writeLatexBibliography(t);
805
806   // Index
807   t << "% Index\n";
808   QCString unit;
809   if (Config_getBool(COMPACT_LATEX))
810   {
811     unit = "section";
812   }
813   else
814   {
815     unit = "chapter";
816     t << "\\backmatter\n";
817   }
818   t << "\\newpage\n"
819        "\\phantomsection\n"
820        "\\clearemptydoublepage\n"
821        "\\addcontentsline{toc}{" << unit << "}{\\indexname}\n"
822        "\\printindex\n"
823        "\n";
824   QCString documentPost = theTranslator->latexDocumentPost();
825   if (!documentPost.isEmpty())
826   {
827     t << documentPost;
828   }
829   t << "\\end{document}\n";
830 }
831
832 void LatexGenerator::writeHeaderFile(QFile &f)
833 {
834   FTextStream t(&f);
835   t << "% Latex header for doxygen " << versionString << endl;
836   writeDefaultHeaderPart1(t);
837   t << "Your title here";
838   writeDefaultHeaderPart2(t);
839   t << "Generated by";
840   writeDefaultHeaderPart3(t);
841 }
842
843 void LatexGenerator::writeFooterFile(QFile &f)
844 {
845   FTextStream t(&f);
846   t << "% Latex footer for doxygen " << versionString << endl;
847   writeDefaultFooter(t);
848 }
849
850 void LatexGenerator::writeStyleSheetFile(QFile &f)
851 {
852   FTextStream t(&f);
853   t << "% stylesheet for doxygen " << versionString << endl;
854   writeDefaultStyleSheet(t);
855 }
856
857 void LatexGenerator::startFile(const char *name,const char *,const char *)
858 {
859 #if 0
860   setEncoding(Config_getString(LATEX_OUTPUT_ENCODING));
861 #endif
862   QCString fileName=name;
863   relPath = relativePathToRoot(fileName);
864   if (fileName.right(4)!=".tex" && fileName.right(4)!=".sty") fileName+=".tex";
865   startPlainFile(fileName);
866   m_codeGen.setTextStream(t);
867   m_codeGen.setRelativePath(relPath);
868   m_codeGen.setSourceFileName(stripPath(fileName));
869 }
870
871 void LatexGenerator::endFile()
872 {
873   endPlainFile();
874   m_codeGen.setSourceFileName("");
875 }
876
877 //void LatexGenerator::writeIndex()
878 //{
879 //  startFile("refman.tex");
880 //} 
881   
882 void LatexGenerator::startProjectNumber()
883 {
884   t << "\\\\[1ex]\\large "; 
885 }
886
887 void LatexGenerator::startIndexSection(IndexSections is)
888 {
889   bool &compactLatex = Config_getBool(COMPACT_LATEX);
890   QCString &latexHeader = Config_getString(LATEX_HEADER);
891   switch (is)
892   {
893     case isTitlePageStart:
894       {
895         if (latexHeader.isEmpty())
896         {
897           writeDefaultHeaderPart1(t);
898         }
899         else
900         {
901           QCString header = fileToString(latexHeader);
902           t << substituteKeywords(header,"",
903                    convertToLaTeX(Config_getString(PROJECT_NAME)),
904                    convertToLaTeX(Config_getString(PROJECT_NUMBER)),
905                    convertToLaTeX(Config_getString(PROJECT_BRIEF)));
906         }
907       }
908       break;
909     case isTitlePageAuthor:
910       if (latexHeader.isEmpty())
911       {
912         writeDefaultHeaderPart2(t);
913       }
914       break;
915     case isMainPage:
916       if (compactLatex) t << "\\section"; else t << "\\chapter";
917       t << "{"; //Introduction}\n"
918       break;
919     //case isPackageIndex:
920     //  if (compactLatex) t << "\\section"; else t << "\\chapter";
921     //  t << "{"; //Package Index}\n"
922     //  break;
923     case isModuleIndex:
924       if (compactLatex) t << "\\section"; else t << "\\chapter";
925       t << "{"; //Module Index}\n"
926       break;
927     case isDirIndex:
928       if (compactLatex) t << "\\section"; else t << "\\chapter";
929       t << "{"; //Directory Index}\n"
930       break;
931     case isNamespaceIndex:
932       if (compactLatex) t << "\\section"; else t << "\\chapter";
933       t << "{"; //Namespace Index}\"
934       break;
935     case isClassHierarchyIndex:
936       if (compactLatex) t << "\\section"; else t << "\\chapter";
937       t << "{"; //Hierarchical Index}\n"
938       break;
939     case isCompoundIndex:
940       if (compactLatex) t << "\\section"; else t << "\\chapter";
941       t << "{"; //Annotated Compound Index}\n"
942       break;
943     case isFileIndex:
944       if (compactLatex) t << "\\section"; else t << "\\chapter";
945       t << "{"; //Annotated File Index}\n"
946       break;
947     case isPageIndex:
948       if (compactLatex) t << "\\section"; else t << "\\chapter";
949       t << "{"; //Annotated Page Index}\n"
950       break;
951     case isModuleDocumentation:
952       {
953         GroupSDict::Iterator gli(*Doxygen::groupSDict);
954         GroupDef *gd;
955         bool found=FALSE;
956         for (gli.toFirst();(gd=gli.current()) && !found;++gli)
957         {
958           if (!gd->isReference())
959           {
960             if (compactLatex) t << "\\section"; else t << "\\chapter";
961             t << "{"; //Module Documentation}\n";
962             found=TRUE;
963           }
964         }
965       }
966       break;
967     case isDirDocumentation:
968       {
969         SDict<DirDef>::Iterator dli(*Doxygen::directories);
970         DirDef *dd;
971         bool found=FALSE;
972         for (dli.toFirst();(dd=dli.current()) && !found;++dli)
973         {
974           if (dd->isLinkableInProject())
975           {
976             if (compactLatex) t << "\\section"; else t << "\\chapter";
977             t << "{"; //Module Documentation}\n";
978             found=TRUE;
979           }
980         }
981       }
982       break;
983     case isNamespaceDocumentation:
984       {
985         NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
986         NamespaceDef *nd;
987         bool found=FALSE;
988         for (nli.toFirst();(nd=nli.current()) && !found;++nli)
989         {
990           if (nd->isLinkableInProject())
991           {
992             if (compactLatex) t << "\\section"; else t << "\\chapter";
993             t << "{"; // Namespace Documentation}\n":
994             found=TRUE;
995           }
996         } 
997       }
998       break;
999     case isClassDocumentation:
1000       {
1001         ClassSDict::Iterator cli(*Doxygen::classSDict);
1002         ClassDef *cd=0;
1003         bool found=FALSE;
1004         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
1005         {
1006           if (cd->isLinkableInProject() && 
1007               cd->templateMaster()==0 &&
1008               !cd->isEmbeddedInOuterScope()
1009              )
1010           {
1011             if (compactLatex) t << "\\section"; else t << "\\chapter";
1012             t << "{"; //Compound Documentation}\n";
1013             found=TRUE;
1014           }
1015         }
1016       }
1017       break;
1018     case isFileDocumentation:
1019       {
1020         bool isFirst=TRUE;
1021         FileNameListIterator fnli(*Doxygen::inputNameList); 
1022         FileName *fn;
1023         for (fnli.toFirst();(fn=fnli.current());++fnli)
1024         {
1025           FileNameIterator fni(*fn);
1026           FileDef *fd;
1027           for (;(fd=fni.current());++fni)
1028           {
1029             if (fd->isLinkableInProject())
1030             {
1031               if (isFirst)
1032               {
1033                 if (compactLatex) t << "\\section"; else t << "\\chapter";
1034                 t << "{"; //File Documentation}\n";
1035                 isFirst=FALSE;
1036                 break;
1037               }
1038             }
1039           }
1040         }
1041       }
1042       break;
1043     case isExampleDocumentation:
1044       {
1045         if (compactLatex) t << "\\section"; else t << "\\chapter";
1046         t << "{"; //Example Documentation}\n";
1047       }
1048       break;
1049     case isPageDocumentation:
1050       {
1051         if (compactLatex) t << "\\section"; else t << "\\chapter";
1052         t << "{"; //Page Documentation}\n";
1053       }
1054       break;
1055     case isPageDocumentation2:
1056       break;
1057     case isEndIndex:
1058       break;
1059   }
1060 }
1061
1062 void LatexGenerator::endIndexSection(IndexSections is)
1063 {
1064   //static bool compactLatex = Config_getBool(COMPACT_LATEX);
1065   static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1066   static QCString latexHeader = Config_getString(LATEX_HEADER);
1067   static QCString latexFooter = Config_getString(LATEX_FOOTER);
1068   switch (is)
1069   {
1070     case isTitlePageStart:
1071       break;
1072     case isTitlePageAuthor:
1073       if (latexHeader.isEmpty())
1074       {
1075         writeDefaultHeaderPart3(t);
1076       }
1077       break;
1078     case isMainPage:
1079       {
1080         //QCString indexName=Config_getBool(GENERATE_TREEVIEW)?"main":"index";
1081         QCString indexName="index";
1082         t << "}\n\\label{index}";
1083         if (Config_getBool(PDF_HYPERLINKS)) t << "\\hypertarget{index}{}";
1084         t << "\\input{" << indexName << "}\n";
1085       }
1086       break;
1087     case isModuleIndex:
1088       t << "}\n\\input{modules}\n";
1089       break;
1090     case isDirIndex:
1091       t << "}\n\\input{dirs}\n";
1092       break;
1093     case isNamespaceIndex:
1094       t << "}\n\\input{namespaces}\n";
1095       break;
1096     case isClassHierarchyIndex:
1097       t << "}\n\\input{hierarchy}\n";
1098       break;
1099     case isCompoundIndex:
1100       t << "}\n\\input{annotated}\n";
1101       break;
1102     case isFileIndex:
1103       t << "}\n\\input{files}\n";
1104       break;
1105     case isPageIndex:
1106       t << "}\n\\input{pages}\n";
1107       break;
1108     case isModuleDocumentation:
1109       {
1110         GroupSDict::Iterator gli(*Doxygen::groupSDict);
1111         GroupDef *gd;
1112         bool found=FALSE;
1113         for (gli.toFirst();(gd=gli.current()) && !found;++gli)
1114         {
1115           if (!gd->isReference())
1116           {
1117             t << "}\n\\input{" << gd->getOutputFileBase() << "}\n";
1118             found=TRUE;
1119           }
1120         }
1121         for (;(gd=gli.current());++gli)
1122         {
1123           if (!gd->isReference())
1124           {
1125             //if (compactLatex) t << "\\input"; else t << "\\include";
1126             t << "\\include"; 
1127             t << "{" << gd->getOutputFileBase() << "}\n";
1128           }
1129         }
1130       }
1131       break;
1132     case isDirDocumentation:
1133       {
1134         SDict<DirDef>::Iterator dli(*Doxygen::directories);
1135         DirDef *dd;
1136         bool found=FALSE;
1137         for (dli.toFirst();(dd=dli.current()) && !found;++dli)
1138         {
1139           if (dd->isLinkableInProject())
1140           {
1141             t << "}\n\\input{" << dd->getOutputFileBase() << "}\n";
1142             found=TRUE;
1143           }
1144         }
1145         for (;(dd=dli.current());++dli)
1146         {
1147           if (dd->isLinkableInProject())
1148           {
1149             //if (compactLatex) t << "\\input"; else t << "\\include";
1150             t << "\\input"; 
1151             t << "{" << dd->getOutputFileBase() << "}\n";
1152           }
1153         }
1154       }
1155       break;
1156     case isNamespaceDocumentation:
1157       {
1158         NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
1159         NamespaceDef *nd;
1160         bool found=FALSE;
1161         for (nli.toFirst();(nd=nli.current()) && !found;++nli)
1162         {
1163           if (nd->isLinkableInProject())
1164           {
1165             t << "}\n\\input{" << nd->getOutputFileBase() << "}\n";
1166             found=TRUE;
1167           }
1168         }
1169         while ((nd=nli.current()))
1170         {
1171           if (nd->isLinkableInProject())
1172           {
1173             //if (compactLatex) t << "\\input"; else t << "\\include";
1174             t << "\\input"; 
1175             t << "{" << nd->getOutputFileBase() << "}\n";
1176           }
1177           ++nli;
1178         }
1179       }
1180       break;
1181     case isClassDocumentation:
1182       {
1183         ClassSDict::Iterator cli(*Doxygen::classSDict);
1184         ClassDef *cd=0;
1185         bool found=FALSE;
1186         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
1187         {
1188           if (cd->isLinkableInProject() && 
1189               cd->templateMaster()==0 &&
1190              !cd->isEmbeddedInOuterScope()
1191              )
1192           {
1193             t << "}\n\\input{" << cd->getOutputFileBase() << "}\n";
1194             found=TRUE;
1195           }
1196         }
1197         for (;(cd=cli.current());++cli)
1198         {
1199           if (cd->isLinkableInProject() && 
1200               cd->templateMaster()==0 &&
1201              !cd->isEmbeddedInOuterScope()
1202              )
1203           {
1204             //if (compactLatex) t << "\\input"; else t << "\\include";
1205             t << "\\input"; 
1206             t << "{" << cd->getOutputFileBase() << "}\n";
1207           } 
1208         }
1209       }
1210       break;
1211     case isFileDocumentation:
1212       {
1213         bool isFirst=TRUE;
1214         FileNameListIterator fnli(*Doxygen::inputNameList); 
1215         FileName *fn;
1216         for (fnli.toFirst();(fn=fnli.current());++fnli)
1217         {
1218           FileNameIterator fni(*fn);
1219           FileDef *fd;
1220           for (;(fd=fni.current());++fni)
1221           {
1222             if (fd->isLinkableInProject())
1223             {
1224               if (isFirst)
1225               {
1226                 t << "}\n\\input{" << fd->getOutputFileBase() << "}\n";
1227                 if (sourceBrowser && m_prettyCode && fd->generateSourceFile())
1228                 {
1229                   //t << "\\include{" << fd->getSourceFileBase() << "}\n";
1230                   t << "\\input{" << fd->getSourceFileBase() << "}\n";
1231                 }
1232                 isFirst=FALSE;
1233               }
1234               else
1235               {
1236                 //if (compactLatex) t << "\\input" ; else t << "\\include";
1237                 t << "\\input" ; 
1238                 t << "{" << fd->getOutputFileBase() << "}\n";
1239                 if (sourceBrowser && m_prettyCode && fd->generateSourceFile())
1240                 {
1241                   //t << "\\include{" << fd->getSourceFileBase() << "}\n";
1242                   t << "\\input{" << fd->getSourceFileBase() << "}\n";
1243                 }
1244               }
1245             }
1246           }
1247         }
1248       }
1249       break;
1250     case isExampleDocumentation:
1251       {
1252         t << "}\n";
1253         PageSDict::Iterator pdi(*Doxygen::exampleSDict);
1254         PageDef *pd=pdi.toFirst();
1255         if (pd)
1256         {
1257           t << "\\input{" << pd->getOutputFileBase() << "}\n";
1258         }
1259         for (++pdi;(pd=pdi.current());++pdi)
1260         {
1261           //if (compactLatex) t << "\\input" ; else t << "\\include";
1262           t << "\\input"; 
1263           t << "{" << pd->getOutputFileBase() << "}\n";
1264         }
1265       }
1266       break;
1267     case isPageDocumentation:
1268       {
1269         t << "}\n";
1270 #if 0
1271         PageSDict::Iterator pdi(*Doxygen::pageSDict);
1272         PageDef *pd=pdi.toFirst();
1273         bool first=TRUE;
1274         for (pdi.toFirst();(pd=pdi.current());++pdi)
1275         {
1276           if (!pd->getGroupDef() && !pd->isReference())
1277           {
1278              if (compactLatex) t << "\\section"; else t << "\\chapter";
1279              t << "{" << pd->title();
1280              t << "}\n";
1281             
1282             if (compactLatex || first) t << "\\input" ; else t << "\\include";
1283             t << "{" << pd->getOutputFileBase() << "}\n";
1284             first=FALSE;
1285           }
1286         }
1287 #endif
1288       }
1289       break;
1290     case isPageDocumentation2:
1291       break;
1292     case isEndIndex:
1293       if (latexFooter.isEmpty())
1294       {
1295         writeDefaultFooter(t);
1296       }
1297       else
1298       {
1299         QCString footer = fileToString(latexFooter);
1300         t << substituteKeywords(footer,"",
1301                    convertToLaTeX(Config_getString(PROJECT_NAME)),
1302                    convertToLaTeX(Config_getString(PROJECT_NUMBER)),
1303                    convertToLaTeX(Config_getString(PROJECT_BRIEF)));
1304       }
1305       break;
1306   }
1307 }
1308
1309 void LatexGenerator::writePageLink(const char *name, bool /*first*/)
1310 {
1311   //bool &compactLatex = Config_getBool(COMPACT_LATEX);
1312   // next is remove for bug615957
1313   //if (compactLatex || first) t << "\\input" ; else t << "\\include";
1314   t << "\\input" ; 
1315   t << "{" << name << "}\n";
1316 }
1317
1318
1319 void LatexGenerator::writeStyleInfo(int part)
1320 {
1321   if (part > 0)
1322     return;
1323
1324   startPlainFile("doxygen.sty");
1325   writeDefaultStyleSheet(t);
1326   endPlainFile();
1327 }
1328
1329 void LatexGenerator::newParagraph()
1330 {
1331   t << endl << endl;
1332 }
1333
1334 void LatexGenerator::startParagraph(const char *)
1335 {
1336   t << endl << endl;
1337 }
1338
1339 void LatexGenerator::endParagraph()
1340 {
1341   t << endl << endl;
1342 }
1343
1344 void LatexGenerator::writeString(const char *text)
1345 {
1346   t << text;
1347 }
1348
1349 void LatexGenerator::startIndexItem(const char *ref,const char *fn)
1350 {
1351   t << "\\item ";
1352   if (!ref && fn)
1353   {
1354     t << "\\contentsline{section}{";
1355   }
1356 }
1357
1358 void LatexGenerator::endIndexItem(const char *ref,const char *fn)
1359 {
1360   if (!ref && fn)
1361   {
1362     t << "}{\\pageref{" << stripPath(fn) << "}}{}" << endl;
1363   }
1364 }
1365
1366 //void LatexGenerator::writeIndexFileItem(const char *,const char *text)
1367 //{
1368 //  t << "\\item\\contentsline{section}{";
1369 //  docify(text);
1370 //  t << "}{\\pageref{" << stripPath(text) << "}}" << endl;
1371 //}
1372
1373
1374 void LatexGenerator::startHtmlLink(const char *url)
1375 {
1376   if (Config_getBool(PDF_HYPERLINKS))
1377   {
1378     t << "\\href{";
1379     t << url;
1380     t << "}";
1381   }
1382   t << "{\\texttt{ ";
1383 }
1384
1385 void LatexGenerator::endHtmlLink()
1386 {
1387   t << "}}";
1388 }
1389
1390 //void LatexGenerator::writeMailLink(const char *url)
1391 //{
1392 //  if (Config_getBool(PDF_HYPERLINKS))
1393 //  {
1394 //    t << "\\href{mailto:";
1395 //    t << url;
1396 //    t << "}";
1397 //  }
1398 //  t << "\\texttt{ ";
1399 //  docify(url);
1400 //  t << "}";
1401 //}
1402
1403 void LatexGenerator::writeStartAnnoItem(const char *,const char *,
1404                                         const char *path,const char *name)
1405 {
1406   t << "\\item\\contentsline{section}\\textbf{ ";
1407   if (path) docify(path);
1408   docify(name); 
1409   t << "} ";
1410 }
1411
1412 void LatexGenerator::writeEndAnnoItem(const char *name)
1413 {
1414   t << "}{\\pageref{" << stripPath(name) << "}}{}" << endl;
1415 }
1416
1417 void LatexGenerator::startIndexKey()
1418 {
1419   t << "\\item\\contentsline{section}{";
1420 }
1421
1422 void LatexGenerator::endIndexKey()
1423 {
1424 }
1425
1426 void LatexGenerator::startIndexValue(bool hasBrief)
1427 {
1428   t << " ";
1429   if (hasBrief) t << "\\\\*";
1430 }
1431
1432 void LatexGenerator::endIndexValue(const char *name,bool /*hasBrief*/)
1433 {
1434   //if (hasBrief) t << ")";
1435   t << "}{\\pageref{" << stripPath(name) << "}}{}" << endl;
1436 }
1437
1438 //void LatexGenerator::writeClassLink(const char *,const char *,
1439 //                                    const char *,const char *name)
1440 //{
1441 //  t << "\\textbf{ ";
1442 //  docify(name);
1443 //  t << "}"; 
1444 //}
1445
1446 void LatexGenerator::startTextLink(const char *f,const char *anchor)
1447 {
1448   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1449   if (!disableLinks && pdfHyperlinks)
1450   {
1451     t << "\\mbox{\\hyperlink{";
1452     if (f) t << stripPath(f);
1453     if (anchor) t << "_" << anchor; 
1454     t << "}{";
1455   }
1456   else
1457   {
1458     t << "\\textbf{ ";
1459   }
1460 }
1461
1462 void LatexGenerator::endTextLink()
1463 {
1464   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1465   if (!disableLinks && pdfHyperlinks)
1466   {
1467     t << "}";
1468   }
1469   t << "}";
1470 }
1471
1472 void LatexGenerator::writeObjectLink(const char *ref, const char *f,
1473                                      const char *anchor, const char *text)
1474 {
1475   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1476   if (!disableLinks && !ref && pdfHyperlinks)
1477   {
1478     t << "\\mbox{\\hyperlink{";
1479     if (f) t << stripPath(f);
1480     if (f && anchor) t << "_"; 
1481     if (anchor) t << anchor; 
1482     t << "}{";
1483     docify(text);
1484     t << "}}";
1485   }
1486   else
1487   {
1488     t << "\\textbf{ ";
1489     docify(text);
1490     t << "}";
1491   } 
1492 }
1493
1494 void LatexGenerator::startPageRef()
1495 {
1496   t << " \\doxyref{}{";
1497 }
1498
1499 void LatexGenerator::endPageRef(const char *clname, const char *anchor)
1500 {
1501   t << "}{";
1502   if (clname) t << clname; 
1503   if (anchor) t << "_" << anchor;
1504   t << "}";
1505 }
1506
1507
1508 void LatexGenerator::startTitleHead(const char *fileName)
1509 {
1510   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1511   static bool usePDFLatex   = Config_getBool(USE_PDFLATEX);
1512   if (usePDFLatex && pdfHyperlinks && fileName)
1513   {
1514     t << "\\hypertarget{" << stripPath(fileName) << "}{}";
1515   }
1516   if (Config_getBool(COMPACT_LATEX)) 
1517   {
1518     t << "\\subsection{"; 
1519   }
1520   else 
1521   {
1522     t << "\\section{"; 
1523   }
1524 }
1525
1526 void LatexGenerator::endTitleHead(const char *fileName,const char *name)
1527 {
1528   t << "}" << endl;
1529   if (name)
1530   {
1531     t << "\\label{" << stripPath(fileName) << "}\\index{";
1532     t << latexEscapeLabelName(name);
1533     t << "@{";
1534     t << latexEscapeIndexChars(name);
1535     t << "}}" << endl;
1536   }
1537 }
1538
1539 void LatexGenerator::startTitle()
1540 {
1541   if (Config_getBool(COMPACT_LATEX)) 
1542   {
1543     t << "\\subsection{"; 
1544   }
1545   else 
1546   {
1547     t << "\\section{"; 
1548   }
1549 }
1550
1551 void LatexGenerator::startGroupHeader(int extraIndentLevel)
1552 {
1553   if (Config_getBool(COMPACT_LATEX)) 
1554   {
1555     extraIndentLevel++;
1556   }
1557
1558   if (extraIndentLevel==3)
1559   {
1560     t << "\\subparagraph*{"; 
1561   }
1562   else if (extraIndentLevel==2)
1563   {
1564     t << "\\paragraph{";
1565   }
1566   else if (extraIndentLevel==1)
1567   {
1568     t << "\\subsubsection{";
1569   }
1570   else // extraIndentLevel==0
1571   {
1572     t << "\\subsection{";
1573   }
1574   disableLinks=TRUE;
1575 }
1576
1577 void LatexGenerator::endGroupHeader(int)
1578 {
1579   disableLinks=FALSE;
1580   t << "}" << endl;
1581 }
1582
1583 void LatexGenerator::startMemberHeader(const char *,int)
1584 {
1585   if (Config_getBool(COMPACT_LATEX)) 
1586   {
1587     t << "\\subsubsection*{"; 
1588   }
1589   else 
1590   {
1591     t << "\\subsection*{";
1592   }
1593   disableLinks=TRUE;
1594 }
1595
1596 void LatexGenerator::endMemberHeader()
1597 {
1598   disableLinks=FALSE;
1599   t << "}" << endl;
1600 }
1601
1602 void LatexGenerator::startMemberDoc(const char *clname,
1603                                     const char *memname,
1604                                     const char *,
1605                                     const char *title,
1606                                     int memCount,
1607                                     int memTotal,
1608                                     bool showInline)
1609 {
1610   if (memname && memname[0]!='@')
1611   {
1612     t << "\\index{";
1613     if (clname)
1614     {
1615       t << latexEscapeLabelName(clname);
1616       t << "@{";
1617       t << latexEscapeIndexChars(clname);
1618       t << "}!";
1619     }
1620     t << latexEscapeLabelName(memname);
1621     t << "@{";
1622     t << latexEscapeIndexChars(memname);
1623     t << "}}" << endl;
1624
1625     t << "\\index{";
1626     t << latexEscapeLabelName(memname);
1627     t << "@{";
1628     t << latexEscapeIndexChars(memname);
1629     t << "}";
1630     if (clname)
1631     {
1632       t << "!";
1633       t << latexEscapeLabelName(clname);
1634       t << "@{";
1635       t << latexEscapeIndexChars(clname);
1636       t << "}";
1637     }
1638     t << "}" << endl;
1639   }
1640   static const char *levelLab[] = { "subsubsection","paragraph","subparagraph", "subparagraph" };
1641   static bool compactLatex = Config_getBool(COMPACT_LATEX);
1642   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1643   int level=0;
1644   if (showInline) level+=2;
1645   if (compactLatex) level++;
1646   t << "\\" << levelLab[level];
1647
1648   t << "{";
1649   if (pdfHyperlinks)
1650   {
1651     t << "\\texorpdfstring{";
1652   }
1653   t << latexEscapeIndexChars(title);
1654   if (pdfHyperlinks)
1655   {
1656     t << "}{" << latexEscapePDFString(title) << "}";
1657   }
1658   if (memTotal>1)
1659   {
1660     t << "\\hspace{0.1cm}{\\footnotesize\\ttfamily [" << memCount << "/" << memTotal << "]}";
1661   }
1662   t << "}";
1663   t << "\n{\\footnotesize\\ttfamily ";
1664   //disableLinks=TRUE;
1665 }
1666
1667 void LatexGenerator::endMemberDoc(bool)
1668 {
1669   disableLinks=FALSE;
1670   t << "}\n\n";
1671   //if (Config_getBool(COMPACT_LATEX)) t << "\\hfill";
1672 }
1673
1674 void LatexGenerator::startDoxyAnchor(const char *fName,const char *,
1675                                      const char *anchor, const char *,
1676                                      const char *)
1677 {
1678   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1679   static bool usePDFLatex   = Config_getBool(USE_PDFLATEX);
1680   t << "\\mbox{";
1681   if (usePDFLatex && pdfHyperlinks)
1682   {
1683     t << "\\Hypertarget{";
1684     if (fName) t << stripPath(fName);
1685     if (anchor) t << "_" << anchor;
1686     t << "}";
1687   }
1688   t << "\\label{";
1689   if (fName) t << stripPath(fName);
1690   if (anchor) t << "_" << anchor;
1691   t << "}} " << endl;
1692 }
1693
1694 void LatexGenerator::endDoxyAnchor(const char *fName,const char *anchor)
1695 {
1696 }
1697
1698 void LatexGenerator::writeAnchor(const char *fName,const char *name)
1699
1700   //printf("LatexGenerator::writeAnchor(%s,%s)\n",fName,name);
1701   t << "\\label{" << stripPath(name) << "}" << endl; 
1702   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1703   static bool usePDFLatex   = Config_getBool(USE_PDFLATEX);
1704   if (usePDFLatex && pdfHyperlinks)
1705   {
1706     if (fName)
1707     {
1708       t << "\\Hypertarget{" << stripPath(fName) << "_" << stripPath(name) << "}" << endl;
1709     }
1710     else
1711     {
1712       t << "\\Hypertarget{" << stripPath(name) << "}" << endl;
1713     }
1714   }
1715 }
1716
1717
1718 //void LatexGenerator::writeLatexLabel(const char *clName,const char *anchor)
1719 //{
1720 //  writeDoxyAnchor(0,clName,anchor,0);
1721 //}
1722
1723 void LatexGenerator::addIndexItem(const char *s1,const char *s2)
1724 {
1725   if (s1)
1726   {
1727     t << "\\index{";
1728     t << latexEscapeLabelName(s1);
1729     t << "@{";
1730     t << latexEscapeIndexChars(s1);
1731     t << "}";
1732     if (s2)
1733     {
1734       t << "!";
1735       t << latexEscapeLabelName(s2);
1736       t << "@{";
1737       t << latexEscapeIndexChars(s2);
1738       t << "}";
1739     }
1740     t << "}";
1741   }
1742 }
1743
1744
1745 void LatexGenerator::startSection(const char *lab,const char *,SectionInfo::SectionType type)
1746 {
1747   static bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS);
1748   static bool usePDFLatex   = Config_getBool(USE_PDFLATEX);
1749   if (usePDFLatex && pdfHyperlinks)
1750   {
1751     t << "\\hypertarget{" << stripPath(lab) << "}{}";
1752   }
1753   t << "\\";
1754   if (Config_getBool(COMPACT_LATEX))
1755   {
1756     switch(type)
1757     {
1758       case SectionInfo::Page:          t << "subsection"; break;
1759       case SectionInfo::Section:       t << "subsubsection"; break;
1760       case SectionInfo::Subsection:    t << "paragraph"; break;
1761       case SectionInfo::Subsubsection: t << "subparagraph"; break;
1762       case SectionInfo::Paragraph:     t << "subparagraph"; break;
1763       default: ASSERT(0); break;
1764     }
1765     t << "{";
1766   }
1767   else
1768   {
1769     switch(type)
1770     {
1771       case SectionInfo::Page:          t << "section"; break;
1772       case SectionInfo::Section:       t << "subsection"; break;
1773       case SectionInfo::Subsection:    t << "subsubsection"; break;
1774       case SectionInfo::Subsubsection: t << "paragraph"; break;
1775       case SectionInfo::Paragraph:     t << "subparagraph"; break;
1776       default: ASSERT(0); break;
1777     }
1778     t << "{";
1779   }
1780 }
1781
1782 void LatexGenerator::endSection(const char *lab,SectionInfo::SectionType)
1783 {
1784   t << "}\\label{" << lab << "}" << endl;
1785 }
1786
1787
1788 void LatexGenerator::docify(const char *str)
1789 {
1790   filterLatexString(t,str,insideTabbing,FALSE,FALSE);
1791 }
1792
1793 void LatexGenerator::writeChar(char c)
1794 {
1795   char cs[2];
1796   cs[0]=c;
1797   cs[1]=0;
1798   docify(cs);
1799 }
1800
1801 void LatexGenerator::startClassDiagram()
1802 {
1803   //if (Config_getBool(COMPACT_LATEX)) t << "\\subsubsection"; else t << "\\subsection";
1804   //t << "{";
1805 }
1806
1807 void LatexGenerator::endClassDiagram(const ClassDiagram &d,
1808                                        const char *fileName,const char *)
1809 {
1810   d.writeFigure(t,dir,fileName);
1811 }
1812
1813
1814 void LatexGenerator::startAnonTypeScope(int indent)
1815 {
1816   if (indent==0)
1817   {
1818     t << "\\begin{tabbing}" << endl;
1819     t << "xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=\\kill" << endl;
1820     insideTabbing=TRUE;
1821   }
1822   m_indent=indent;
1823 }
1824
1825 void LatexGenerator::endAnonTypeScope(int indent)
1826 {
1827   if (indent==0)
1828   {
1829     t << endl << "\\end{tabbing}";
1830     insideTabbing=FALSE;
1831   }
1832   m_indent=indent;
1833 }
1834
1835 void LatexGenerator::startMemberTemplateParams()
1836 {
1837   if (templateMemberItem)
1838   {
1839     t << "{\\footnotesize ";
1840   }
1841 }
1842
1843 void LatexGenerator::endMemberTemplateParams(const char *,const char *)
1844 {
1845   if (templateMemberItem)
1846   {
1847     t << "}\\\\";
1848   }
1849 }
1850
1851 void LatexGenerator::startMemberItem(const char *,int annoType,const char *) 
1852
1853   //printf("LatexGenerator::startMemberItem(%d)\n",annType);
1854   if (!insideTabbing)
1855   {
1856     t << "\\item " << endl; 
1857     templateMemberItem = (annoType == 3);
1858   }
1859 }
1860
1861 void LatexGenerator::endMemberItem() 
1862 {
1863   if (insideTabbing)
1864   {
1865     t << "\\\\";
1866   } 
1867   templateMemberItem = FALSE;
1868   t << endl; 
1869 }
1870
1871 void LatexGenerator::startMemberDescription(const char *,const char *,bool) 
1872 {
1873   if (!insideTabbing)
1874   { 
1875     t << "\\begin{DoxyCompactList}\\small\\item\\em "; 
1876   }
1877   else
1878   {
1879     for (int i=0;i<m_indent+2;i++) t << "\\>";
1880     t << "{\\em ";
1881   }
1882 }
1883
1884 void LatexGenerator::endMemberDescription() 
1885
1886   if (!insideTabbing)
1887   {
1888     //t << "\\item\\end{DoxyCompactList}"; 
1889     t << "\\end{DoxyCompactList}"; 
1890   }
1891   else
1892   {
1893     t << "}\\\\\n";
1894   }
1895 }
1896
1897
1898 void LatexGenerator::writeNonBreakableSpace(int) 
1899 {
1900   //printf("writeNonBreakbleSpace()\n");
1901   if (insideTabbing)
1902   {
1903     t << "\\>";
1904   }
1905   else
1906   {
1907     t << "~"; 
1908   }
1909 }
1910
1911 // ----------------------------------------------
1912 // nesting of functions below:
1913 // startDescTable()
1914 // - startDescTableRow()
1915 //   - startDescTableTitle()
1916 //   - endDescTabelTitle()
1917 //   - startDescTableData()
1918 //   - endDescTableData()
1919 // - endDescTableRow()
1920 // - startDescTableRow()
1921 //   - ...
1922 // - endDescTableRow()
1923 // endDescTable()
1924
1925 void LatexGenerator::startDescTable(const char *title)
1926 {
1927   incUsedTableLevels();
1928   t << "\\begin{DoxyEnumFields}{" << title << "}" << endl;
1929 }
1930
1931 void LatexGenerator::endDescTable()
1932 {
1933   decUsedTableLevels();
1934   t << "\\end{DoxyEnumFields}" << endl;
1935 }
1936
1937 void LatexGenerator::startDescTableRow()
1938 {
1939   // this is needed to prevent the \hypertarget, \label, and \index commands from messing up
1940   // the row height (based on http://tex.stackexchange.com/a/186102)
1941   t << "\\raisebox{\\heightof{T}}[0pt][0pt]{";
1942 }
1943
1944 void LatexGenerator::endDescTableRow()
1945 {
1946 }
1947
1948 void LatexGenerator::startDescTableTitle()
1949 {
1950   t << "}";
1951 }
1952
1953 void LatexGenerator::endDescTableTitle()
1954 {
1955 }
1956
1957 void LatexGenerator::startDescTableData()
1958 {
1959   t << "&";
1960 }
1961
1962 void LatexGenerator::endDescTableData()
1963 {
1964   t << "\\\\\n\\hline\n" << endl;
1965 }
1966
1967 void LatexGenerator::lastIndexPage() 
1968 {
1969 }
1970
1971
1972 void LatexGenerator::startMemberList()  
1973
1974   if (!insideTabbing)
1975   {
1976     t << "\\begin{DoxyCompactItemize}" << endl; 
1977   }
1978 }
1979
1980 void LatexGenerator::endMemberList()    
1981 {
1982   //printf("LatexGenerator::endMemberList(%d)\n",insideTabbing);
1983   if (!insideTabbing)
1984   {
1985     t << "\\end{DoxyCompactItemize}"   << endl; 
1986   }
1987 }
1988
1989
1990 void LatexGenerator::startMemberGroupHeader(bool hasHeader)
1991 {
1992   if (hasHeader) t << "\\begin{Indent}";
1993   t << "\\textbf{ ";
1994   // changed back to rev 756 due to bug 660501
1995   //if (Config_getBool(COMPACT_LATEX)) 
1996   //{
1997   //  t << "\\subparagraph*{";
1998   //}
1999   //else
2000   //{
2001   //  t << "\\paragraph*{";
2002   //}
2003 }
2004
2005 void LatexGenerator::endMemberGroupHeader()
2006 {
2007   // changed back to rev 756 due to bug 660501
2008   t << "}\\par" << endl;
2009   //t << "}" << endl;
2010 }
2011
2012 void LatexGenerator::startMemberGroupDocs()
2013 {
2014   t << "{\\em ";
2015 }
2016
2017 void LatexGenerator::endMemberGroupDocs()
2018 {
2019   t << "}";
2020 }
2021
2022 void LatexGenerator::startMemberGroup()
2023 {
2024 }
2025
2026 void LatexGenerator::endMemberGroup(bool hasHeader)
2027 {
2028   if (hasHeader)t << "\\end{Indent}"; 
2029   t << endl;
2030 }
2031
2032 void LatexGenerator::startDotGraph() 
2033 {
2034   newParagraph();
2035 }
2036
2037 void LatexGenerator::endDotGraph(const DotClassGraph &g) 
2038 {
2039   g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
2040 }
2041
2042 void LatexGenerator::startInclDepGraph() 
2043 {
2044 }
2045
2046 void LatexGenerator::endInclDepGraph(const DotInclDepGraph &g) 
2047 {
2048   g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
2049 }
2050
2051 void LatexGenerator::startGroupCollaboration() 
2052 {
2053 }
2054
2055 void LatexGenerator::endGroupCollaboration(const DotGroupCollaboration &g) 
2056 {
2057   g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
2058 }
2059
2060 void LatexGenerator::startCallGraph() 
2061 {
2062 }
2063
2064 void LatexGenerator::endCallGraph(const DotCallGraph &g) 
2065 {
2066   g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
2067 }
2068
2069 void LatexGenerator::startDirDepGraph() 
2070 {
2071 }
2072
2073 void LatexGenerator::endDirDepGraph(const DotDirDeps &g) 
2074 {
2075   g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath);
2076 }
2077
2078 void LatexGenerator::startDescription() 
2079
2080   t << "\\begin{description}" << endl; 
2081 }
2082
2083 void LatexGenerator::endDescription()   
2084
2085   t << "\\end{description}" << endl; 
2086   firstDescItem=TRUE;
2087 }
2088
2089 void LatexGenerator::startDescItem()    
2090
2091   firstDescItem=TRUE;
2092   t << "\\item["; 
2093 }
2094
2095 void LatexGenerator::endDescItem()      
2096
2097   if (firstDescItem) 
2098   {
2099     t << "]" << endl;
2100     firstDescItem=FALSE;
2101   } 
2102   else
2103   {
2104     lineBreak();
2105   }
2106 }
2107
2108 void LatexGenerator::startExamples()
2109 {
2110   t << "\\begin{Desc}\n\\item[";
2111   docify(theTranslator->trExamples());
2112   t << "]";
2113 }
2114
2115 void LatexGenerator::endExamples()
2116 {
2117   t << "\\end{Desc}" << endl;
2118 }
2119
2120 void LatexGenerator::startParamList(ParamListTypes,const char *title)
2121 {
2122   t << "\\begin{Desc}\n\\item[";
2123   docify(title);
2124   t << "]";
2125 }
2126
2127 void LatexGenerator::endParamList()
2128 {
2129   t << "\\end{Desc}" << endl;
2130 }
2131
2132 void LatexGenerator::startParameterList(bool openBracket)
2133 {
2134   /* start of ParameterType ParameterName list */
2135   if (openBracket) t << "(";
2136   t << "\\begin{DoxyParamCaption}";
2137 }
2138
2139 void LatexGenerator::endParameterList()
2140 {
2141 }
2142
2143 void LatexGenerator::startParameterType(bool first,const char *key)
2144 {
2145   t << "\\item[{";
2146   if (!first && key) docify(key);
2147 }
2148
2149 void LatexGenerator::endParameterType()
2150 {
2151   t << "}]";
2152 }
2153
2154 void LatexGenerator::startParameterName(bool /*oneArgOnly*/)
2155 {
2156   t << "{";
2157 }
2158
2159 void LatexGenerator::endParameterName(bool last,bool /*emptyList*/,bool closeBracket)
2160 {
2161   t << " }";
2162   if (last)
2163   {
2164     t << "\\end{DoxyParamCaption}";
2165     if (closeBracket) t << ")";
2166   }
2167 }
2168
2169 void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket)
2170 {
2171   if (prefix)
2172       t << " " << prefix << "(";
2173   else if (closeBracket)
2174       t << ")";
2175   t << " ";
2176 }
2177
2178 void LatexGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
2179 {
2180   LatexDocVisitor *visitor =
2181     new LatexDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""),insideTabbing);
2182   n->accept(visitor);
2183   delete visitor;
2184 }
2185
2186 void LatexGenerator::startConstraintList(const char *header)
2187 {
2188   t << "\\begin{Desc}\n\\item[";
2189   docify(header);
2190   t << "]";
2191   t << "\\begin{description}" << endl;
2192 }
2193
2194 void LatexGenerator::startConstraintParam()
2195 {
2196   t << "\\item[{\\em ";
2197 }
2198
2199 void LatexGenerator::endConstraintParam()
2200 {
2201 }
2202
2203 void LatexGenerator::startConstraintType()
2204 {
2205   t << "} : {\\em ";
2206 }
2207
2208 void LatexGenerator::endConstraintType()
2209 {
2210   t << "}]";
2211 }
2212
2213 void LatexGenerator::startConstraintDocs()
2214 {
2215 }
2216
2217 void LatexGenerator::endConstraintDocs()
2218 {
2219 }
2220
2221 void LatexGenerator::endConstraintList()
2222 {
2223   t << "\\end{description}" << endl;
2224   t << "\\end{Desc}" << endl;
2225 }
2226
2227 void LatexGenerator::startCodeFragment()
2228 {
2229   t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n";
2230   DoxyCodeOpen = TRUE;
2231 }
2232
2233 void LatexGenerator::endCodeFragment()
2234 {
2235   //endCodeLine checks is there is still an open code line, if so closes it.
2236   endCodeLine();
2237
2238   t << "\\end{DoxyCode}\n";
2239   DoxyCodeOpen = FALSE;
2240 }
2241
2242 void LatexGenerator::startInlineHeader()
2243 {
2244   if (Config_getBool(COMPACT_LATEX)) 
2245   {
2246     t << "\\paragraph*{"; 
2247   }
2248   else 
2249   {
2250     t << "\\subsubsection*{";
2251   }
2252 }
2253
2254 void LatexGenerator::endInlineHeader()
2255 {
2256   t << "}" << endl;
2257 }
2258
2259 void LatexGenerator::lineBreak(const char *)
2260 {
2261   if (insideTabbing)
2262   {
2263     t << "\\\\\n";
2264   }
2265   else
2266   {
2267     t << "\\newline\n";
2268   }
2269 }
2270
2271 void LatexGenerator::startMemberDocSimple(bool isEnum)
2272 {
2273   incUsedTableLevels();
2274   if (isEnum)
2275   {
2276     t << "\\begin{DoxyEnumFields}{";
2277     docify(theTranslator->trEnumerationValues());
2278   }
2279   else
2280   {
2281     t << "\\begin{DoxyFields}{";
2282     docify(theTranslator->trCompoundMembers());
2283   }
2284   t << "}" << endl;
2285 }
2286
2287 void LatexGenerator::endMemberDocSimple(bool isEnum)
2288 {
2289   decUsedTableLevels();
2290   if (isEnum)
2291   {
2292     t << "\\end{DoxyEnumFields}" << endl;
2293   }
2294   else
2295   {
2296     t << "\\end{DoxyFields}" << endl;
2297   }
2298 }
2299
2300 void LatexGenerator::startInlineMemberType()
2301 {
2302   insideTabbing = TRUE; // to prevent \+ from causing unwanted breaks
2303 }
2304
2305 void LatexGenerator::endInlineMemberType()
2306 {
2307   t << "&" << endl;
2308   insideTabbing = FALSE;
2309 }
2310
2311 void LatexGenerator::startInlineMemberName()
2312 {
2313   insideTabbing = TRUE; // to prevent \+ from causing unwanted breaks
2314 }
2315
2316 void LatexGenerator::endInlineMemberName()
2317 {
2318   t << "&" << endl;
2319   insideTabbing = FALSE;
2320 }
2321
2322 void LatexGenerator::startInlineMemberDoc()
2323 {
2324 }
2325
2326 void LatexGenerator::endInlineMemberDoc()
2327 {
2328   t << "\\\\\n\\hline\n" << endl;
2329 }
2330
2331 void LatexGenerator::startLabels()
2332 {
2333   t << "\\hspace{0.3cm}";
2334 }
2335
2336 void LatexGenerator::writeLabel(const char *l,bool isLast)
2337 {
2338   t << "{\\ttfamily [" << l << "]}";
2339   if (!isLast) t << ", ";
2340 }
2341
2342 void LatexGenerator::endLabels()
2343 {
2344 }
2345
2346