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