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