latexgen.cpp 53.6 KB
Newer Older
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1 2
/******************************************************************************
 *
3
 * 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
4
 *
Dimitri van Heesch's avatar
Dimitri van Heesch committed
5
 * Copyright (C) 1997-2013 by Dimitri van Heesch.
Dimitri van Heesch's avatar
Dimitri van Heesch committed
6 7 8 9 10 11 12
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation under the terms of the GNU General Public License is hereby 
 * granted. No representations are made about the suitability of this software 
 * for any purpose. It is provided "as is" without express or implied warranty.
 * See the GNU General Public License for more details.
 *
Dimitri van Heesch's avatar
Dimitri van Heesch committed
13 14
 * Documents produced by Doxygen are derivative works derived from the
 * input used in their production; they are not affected by this license.
Dimitri van Heesch's avatar
Dimitri van Heesch committed
15 16 17 18
 *
 */

#include <stdlib.h>
19

Dimitri van Heesch's avatar
Dimitri van Heesch committed
20 21 22 23 24 25 26 27
#include <qdir.h>
#include "latexgen.h"
#include "config.h"
#include "message.h"
#include "doxygen.h"
#include "util.h"
#include "diagram.h"
#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 36 37 38
#include "groupdef.h"
#include "classlist.h"
#include "namespacedef.h"
#include "filename.h"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
39

Dimitri van Heesch's avatar
Dimitri van Heesch committed
40 41 42 43
static const char doxygenLatexStyle[] =
#include "doxygen_sty.h"
;

Dimitri van Heesch's avatar
Dimitri van Heesch committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
//static QCString filterTitle(const char *s)
//{
//  QCString tmp=s,result;
//  uint i;for (i=0;i<tmp.length();i++)
//  {
//    char c=tmp.at(i);
//    switch(c)
//    {
//      case '#': result+="\\#";  break;
//      case '"': result+="\\\""; break;
//      case '%': result+="\\%";  break;
//      case '[': result+="{";    break;
//      case ']': result+="}";    break;
//      default:  result+=c;      break;
//    }
//  }
//  return result;  
//}
62

63

Dimitri van Heesch's avatar
Dimitri van Heesch committed
64

65
LatexGenerator::LatexGenerator() : OutputGenerator()
Dimitri van Heesch's avatar
Dimitri van Heesch committed
66
{
67
  dir=Config_getString("LATEX_OUTPUT");
Dimitri van Heesch's avatar
Dimitri van Heesch committed
68
  col=0;
69
  //printf("LatexGenerator::LatexGenerator() insideTabbing=FALSE\n");
70
  insideTabbing=FALSE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
71
  firstDescItem=TRUE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
72
  disableLinks=FALSE;
73
  m_indent=0;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
74
  templateMemberItem = FALSE;
75
  m_prettyCode=Config_getBool("LATEX_SOURCE_CODE");
Dimitri van Heesch's avatar
Dimitri van Heesch committed
76 77 78 79 80 81
}

LatexGenerator::~LatexGenerator()
{
}

82
static void writeLatexMakefile()
Dimitri van Heesch's avatar
Dimitri van Heesch committed
83
{
84
  bool generateBib = !Doxygen::citeDict->isEmpty();
85
  QCString dir=Config_getString("LATEX_OUTPUT");
86
  QCString fileName=dir+"/Makefile";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
87 88 89 90 91 92
  QFile file(fileName);
  if (!file.open(IO_WriteOnly))
  {
    err("Could not open file %s for writing\n",fileName.data());
    exit(1);
  }
93 94 95 96
  // inserted by KONNO Akihisa <konno@researchers.jp> 2002-03-05
  QCString latex_command = Config_getString("LATEX_CMD_NAME");
  QCString mkidx_command = Config_getString("MAKEINDEX_CMD_NAME");
  // end insertion by KONNO Akihisa <konno@researchers.jp> 2002-03-05
97
  FTextStream t(&file);
98 99
  if (!Config_getBool("USE_PDFLATEX")) // use plain old latex
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
100
    t << "all: refman.dvi" << endl
101 102 103 104 105 106 107 108 109 110 111 112 113 114
      << endl
      << "ps: refman.ps" << endl
      << endl
      << "pdf: refman.pdf" << endl
      << endl
      << "ps_2on1: refman_2on1.ps" << endl
      << endl
      << "pdf_2on1: refman_2on1.pdf" << endl
      << endl
      << "refman.ps: refman.dvi" << endl
      << "\tdvips -o refman.ps refman.dvi" << endl
      << endl;
    t << "refman.pdf: refman.ps" << endl;
    t << "\tps2pdf refman.ps refman.pdf" << endl << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
115
    t << "refman.dvi: clean refman.tex doxygen.sty" << endl
116 117 118
      << "\techo \"Running latex...\"" << endl
      << "\t" << latex_command << " refman.tex" << endl
      << "\techo \"Running makeindex...\"" << endl
119 120 121 122 123 124
      << "\t" << mkidx_command << " refman.idx" << endl;
    if (generateBib)
    {
      t << "\techo \"Running bibtex...\"" << endl;
      t << "\tbibtex refman" << endl;
      t << "\techo \"Rerunning latex....\"" << endl;
125
      t << "\t" << latex_command << " refman.tex" << endl;
126 127
    }
    t << "\techo \"Rerunning latex....\"" << endl
128 129 130 131 132 133 134
      << "\t" << latex_command << " refman.tex" << endl
      << "\tlatex_count=5 ; \\" << endl
      << "\twhile egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\\" << endl
      << "\t    do \\" << endl
      << "\t      echo \"Rerunning latex....\" ;\\" << endl
      << "\t      " << latex_command << " refman.tex ;\\" << endl
      << "\t      latex_count=`expr $$latex_count - 1` ;\\" << endl
135 136 137
      << "\t    done" << endl
      << "\t" << mkidx_command << " refman.idx" << endl
      << "\t" << latex_command << " refman.tex" << endl << endl
138 139 140 141 142 143 144 145
      << "refman_2on1.ps: refman.ps" << endl
      << "\tpsnup -2 refman.ps >refman_2on1.ps" << endl
      << endl
      << "refman_2on1.pdf: refman_2on1.ps" << endl
      << "\tps2pdf refman_2on1.ps refman_2on1.pdf" << endl;
  }
  else // use pdflatex for higher quality output
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
146
    t << "all: refman.pdf" << endl << endl
Dimitri van Heesch's avatar
Dimitri van Heesch committed
147
      << "pdf: refman.pdf" << endl << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
148
    t << "refman.pdf: clean refman.tex" << endl;
149
    t << "\tpdflatex refman" << endl;
150
    t << "\t" << mkidx_command << " refman.idx" << endl;
151 152 153 154 155 156
    if (generateBib)
    {
      t << "\tbibtex refman" << endl;
      t << "\tpdflatex refman" << endl;
    }
    t << "\tpdflatex refman" << endl
157 158 159 160
      << "\tlatex_count=5 ; \\" << endl
      << "\twhile egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\\" << endl
      << "\t    do \\" << endl
      << "\t      echo \"Rerunning latex....\" ;\\" << endl
161
      << "\t      pdflatex refman ;\\" << endl
162
      << "\t      latex_count=`expr $$latex_count - 1` ;\\" << endl
163 164 165
      << "\t    done" << endl
      << "\t" << mkidx_command << " refman.idx" << endl
      << "\tpdflatex refman" << endl << endl;
166 167 168
  }

  t << endl
Dimitri van Heesch's avatar
Dimitri van Heesch committed
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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
  QCString dir=Config_getString("LATEX_OUTPUT");
  QCString fileName=dir+"/make.bat";
  QCString latex_command = Config_getString("LATEX_CMD_NAME");
  QCString mkidx_command = Config_getString("MAKEINDEX_CMD_NAME");
  QFile file(fileName);
  bool generateBib = !Doxygen::citeDict->isEmpty();
  if (!file.open(IO_WriteOnly))
  {
    err("Could not open file %s for writing\n",fileName.data());
    exit(1);
  }
  FTextStream t(&file);
  t << "del /s /f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf\n\n";
  if (!Config_getBool("USE_PDFLATEX")) // use plain old latex
  {
    t << latex_command << " refman.tex\n";
    t << "echo ----\n";
    t << mkidx_command << " refman.idx\n";
    if (generateBib)
196
    {
197 198 199
      t << "bibtex refman\n";
      t << "echo ----\n";
      t << latex_command << " refman.tex\n";
200
    }
201 202 203 204 205 206 207 208 209 210 211 212 213 214
    t << "setlocal enabledelayedexpansion\n";
    t << "set count=5\n";
    t << ":repeat\n";
    t << "set content=X\n";
    t << "for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun LaTeX\" refman.log' ) do set content=\"%%~T\"\n";
    t << "if !content! == X for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun to get cross-references right\" refman.log' ) do set content=\"%%~T\"\n";
    t << "if !content! == X goto :skip\n";
    t << "set /a count-=1\n";
    t << "if !count! EQU 0 goto :skip\n\n";
    t << "echo ----\n";
    t << latex_command << " refman.tex\n";
    t << "goto :repeat\n";
    t << ":skip\n";
    t << "endlocal\n";
215 216
    t << mkidx_command << " refman.idx\n";
    t << latex_command << " refman.tex\n";
217 218 219 220 221 222
    t << "dvips -o refman.ps refman.dvi\n";
    t << "gswin32c -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite "
         "-sOutputFile=refman.pdf -c save pop -f refman.ps\n";
  }
  else // use pdflatex
  {
223 224 225 226 227
    t << "pdflatex refman\n";
    t << "echo ----\n";
    t << mkidx_command << " refman.idx\n";
    if (generateBib)
    {
228 229
      t << "bibtex refman" << endl;
      t << "pdflatex refman" << endl;
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    }
    t << "echo ----\n";
    t << "pdflatex refman\n\n";
    t << "setlocal enabledelayedexpansion\n";
    t << "set count=5\n";
    t << ":repeat\n";
    t << "set content=X\n";
    t << "for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun LaTeX\" refman.log' ) do set content=\"%%~T\"\n";
    t << "if !content! == X for /F \"tokens=*\" %%T in ( 'findstr /C:\"Rerun to get cross-references right\" refman.log' ) do set content=\"%%~T\"\n";
    t << "if !content! == X goto :skip\n";
    t << "set /a count-=1\n";
    t << "if !count! EQU 0 goto :skip\n\n";
    t << "echo ----\n";
    t << "pdflatex refman\n";
    t << "goto :repeat\n";
    t << ":skip\n";
    t << "endlocal\n";
247 248
    t << mkidx_command << " refman.idx\n";
    t << "pdflatex refman\n";
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
  }
#endif
}

void LatexGenerator::init()
{

  QCString dir=Config_getString("LATEX_OUTPUT");
  QDir d(dir);
  if (!d.exists() && !d.mkdir(dir))
  {
    err("Could not create output directory %s\n",dir.data());
    exit(1);
  }

  writeLatexMakefile();
265
  writeMakeBat();
266 267

  createSubDirs(d);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
268 269
}

270
static void writeDefaultHeaderPart1(FTextStream &t)
271 272 273
{
  // part 1

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
  // Handle batch mode
  if (Config_getBool("LATEX_BATCHMODE"))
    t << "\\batchmode\n";

  // Set document class depending on configuration
  QCString documentClass;
  if (Config_getBool("COMPACT_LATEX"))
    documentClass = "article";
  else
    documentClass = "book";
  t << "\\documentclass[twoside]{" << documentClass << "}\n"
       "\n";

  // Load required packages
  t << "% Packages required by doxygen\n"
       "\\usepackage{calc}\n"
       "\\usepackage{doxygen}\n"
       "\\usepackage{graphicx}\n"
       "\\usepackage[utf8]{inputenc}\n"
       "\\usepackage{makeidx}\n"
       "\\usepackage{multicol}\n"
       "\\usepackage{multirow}\n"
       "\\usepackage{textcomp}\n"
       "\\usepackage[table]{xcolor}\n"
       "\n";

  // Language support
  QCString languageSupport = theTranslator->latexLanguageSupportCommand();
  if (!languageSupport.isEmpty())
  {
    t << "% NLS support packages\n"
      << languageSupport
      << "\n";
  }

  // Define default fonts
  t << "% Font selection\n"
       "\\usepackage[T1]{fontenc}\n"
       "\\usepackage{mathptmx}\n"
       "\\usepackage[scaled=.90]{helvet}\n"
       "\\usepackage{courier}\n"
       "\\usepackage{amssymb}\n"
       "\\usepackage{sectsty}\n"
       "\\renewcommand{\\familydefault}{\\sfdefault}\n"
       "\\allsectionsfont{%\n"
       "  \\fontseries{bc}\\selectfont%\n"
       "  \\color{darkgray}%\n"
       "}\n"
       "\\renewcommand{\\DoxyLabelFont}{%\n"
       "  \\fontseries{bc}\\selectfont%\n"
       "  \\color{darkgray}%\n"
       "}\n"
       "\n";

  // Define page & text layout
329
  QCString paperName;
330
  QCString &paperType=Config_getEnum("PAPER_TYPE");
331 332 333 334
  // "a4wide" package is obsolete (see bug 563698)
  if (paperType=="a4wide")
    paperName="a4";
  else
335
    paperName=paperType;
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
  t << "% Page & text layout\n"
       "\\usepackage{geometry}\n"
       "\\geometry{%\n"
       "  " << paperName << "paper,%\n"
       "  top=2.5cm,%\n"
       "  bottom=2.5cm,%\n"
       "  left=2.5cm,%\n"
       "  right=2.5cm%\n"
       "}\n";
  // \sloppy is obsolete (see bug 563698)
  // Allow a bit of overflow to go unnoticed by other means
  t << "\\tolerance=750\n"
       "\\hfuzz=15pt\n"
       "\\hbadness=750\n"
       "\\setlength{\\emergencystretch}{15pt}\n"
       "\\setlength{\\parindent}{0cm}\n"
       "\\setlength{\\parskip}{0.2cm}\n";
  // Redefine paragraph/subparagraph environments, using sectsty fonts
  t << "\\makeatletter\n"
       "\\renewcommand{\\paragraph}{%\n"
       "  \\@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{%\n"
       "    \\normalfont\\normalsize\\bfseries\\SS@parafont%\n"
       "  }%\n"
       "}\n"
       "\\renewcommand{\\subparagraph}{%\n"
       "  \\@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{%\n"
       "    \\normalfont\\normalsize\\bfseries\\SS@subparafont%\n"
       "  }%\n"
       "}\n"
       "\\makeatother\n"
       "\n";
367

368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
  // Headers & footers
  QCString genString =
        theTranslator->trGeneratedAt(dateToString(TRUE),Config_getString("PROJECT_NAME"));
  t << "% Headers & footers\n"
       "\\usepackage{fancyhdr}\n"
       "\\pagestyle{fancyplain}\n"
       "\\fancyhead[LE]{\\fancyplain{}{\\bfseries\\thepage}}\n"
       "\\fancyhead[CE]{\\fancyplain{}{}}\n"
       "\\fancyhead[RE]{\\fancyplain{}{\\bfseries\\leftmark}}\n"
       "\\fancyhead[LO]{\\fancyplain{}{\\bfseries\\rightmark}}\n"
       "\\fancyhead[CO]{\\fancyplain{}{}}\n"
       "\\fancyhead[RO]{\\fancyplain{}{\\bfseries\\thepage}}\n"
       "\\fancyfoot[LE]{\\fancyplain{}{}}\n"
       "\\fancyfoot[CE]{\\fancyplain{}{}}\n"
       "\\fancyfoot[RE]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n"
       "\\fancyfoot[LO]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n"
       "\\fancyfoot[CO]{\\fancyplain{}{}}\n"
       "\\fancyfoot[RO]{\\fancyplain{}{}}\n"
       "\\renewcommand{\\footrulewidth}{0.4pt}\n";
  if (!Config_getBool("COMPACT_LATEX"))
388
  {
389 390 391
    t << "\\renewcommand{\\chaptermark}[1]{%\n"
         "  \\markboth{#1}{}%\n"
         "}\n";
392
  }
393 394 395 396
  t << "\\renewcommand{\\sectionmark}[1]{%\n"
       "  \\markright{\\thesection\\ #1}%\n"
       "}\n"
       "\n";
397

398 399 400 401 402 403 404 405
  // ToC, LoF, LoT, bibliography, and index
  t << "% Indices & bibliography\n"
       "\\usepackage{natbib}\n"
       "\\usepackage[titles]{tocloft}\n"
       "\\setcounter{tocdepth}{3}\n"
       "\\setcounter{secnumdepth}{5}\n"
       "\\makeindex\n"
       "\n";
406

407
  // User-specified packages
408
  QStrList &extraPackages = Config_getList("EXTRA_PACKAGES");
409 410 411 412 413 414 415 416 417 418 419 420 421 422
  if (!extraPackages.isEmpty()) {
    t << "% Packages requested by user\n";
    const char *pkgName=extraPackages.first();
    while (pkgName)
    {
      t << "\\usepackage{" << pkgName << "}\n";
      pkgName=extraPackages.next();
    }
    t << "\n";
  }

  // Hyperlinks
  bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  if (pdfHyperlinks)
423
  {
424 425 426 427 428 429 430 431 432 433 434 435 436 437
    t << "% Hyperlinks (required, but should be loaded last)\n"
         "\\usepackage{ifpdf}\n"
         "\\ifpdf\n"
         "  \\usepackage[pdftex,pagebackref=true]{hyperref}\n"
         "\\else\n"
         "  \\usepackage[ps2pdf,pagebackref=true]{hyperref}\n"
         "\\fi\n"
         "\\hypersetup{%\n"
         "  colorlinks=true,%\n"
         "  linkcolor=blue,%\n"
         "  citecolor=blue,%\n"
         "  unicode%\n"
         "}\n"
         "\n";
438
  }
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458

  // Custom commands used by the header
  t << "% Custom commands\n"
       "\\newcommand{\\clearemptydoublepage}{%\n"
       "  \\newpage{\\pagestyle{empty}\\cleardoublepage}%\n"
       "}\n"
       "\n"
       "\n";

  // End of preamble, now comes the document contents
  t << "%===== C O N T E N T S =====\n"
       "\n"
       "\\begin{document}\n";
  if (theTranslator->idLanguage()=="greek")
    t << "\\selectlanguage{greek}\n";
  t << "\n";

  // Front matter
  t << "% Titlepage & ToC\n";
  bool usePDFLatex = Config_getBool("USE_PDFLATEX");
459 460
  if (pdfHyperlinks && usePDFLatex)
  {
461
    // To avoid duplicate page anchors due to reuse of same numbers for
462
    // the index (be it as roman numbers)
463
    t << "\\hypersetup{pageanchor=false}\n";
464
  }
465 466 467 468 469
  t << "\\pagenumbering{roman}\n"
       "\\begin{titlepage}\n"
       "\\vspace*{7cm}\n"
       "\\begin{center}%\n"
       "{\\Large ";
470 471
}

472
static void writeDefaultHeaderPart2(FTextStream &t)
473 474
{
  // part 2
475 476 477 478
  // Finalize project name
  t << "}\\\\\n"
       "\\vspace*{1cm}\n"
       "{\\large ";
479 480
}

481
static void writeDefaultHeaderPart3(FTextStream &t)
482 483
{
  // part 3
484 485 486 487 488 489 490 491 492 493 494
  // Finalize project number
  t << " Doxygen " << versionString << "}\\\\\n"
       "\\vspace*{0.5cm}\n"
       "{\\small " << dateToString(TRUE) << "}\\\\\n"
       "\\end{center}\n"
       "\\end{titlepage}\n";
  bool compactLatex = Config_getBool("COMPACT_LATEX");
  if (!compactLatex)
    t << "\\clearemptydoublepage\n";

  // ToC
495
  t << "\\tableofcontents\n";
496 497
  if (!compactLatex)
    t << "\\clearemptydoublepage\n";
498
  t << "\\pagenumbering{arabic}\n";
499 500
  bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
501 502
  if (pdfHyperlinks && usePDFLatex)
  {
503 504
    // re-enable anchors again
    t << "\\hypersetup{pageanchor=true}\n";
505
  }
506 507
  t << "\n"
       "%--- Begin generated contents ---\n";
508 509
}

510
static void writeDefaultStyleSheet(FTextStream &t)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
511
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
512
  t << doxygenLatexStyle;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
513 514
}

515 516
static void writeDefaultFooter(FTextStream &t)
{
517 518 519 520
  t << "%--- End generated contents ---\n"
       "\n";

  // Bibliography
521
  Doxygen::citeDict->writeLatexBibliography(t);
522 523 524 525 526 527 528 529 530

  // Index
  t << "% Index\n"
       "\\newpage\n"
       "\\phantomsection\n"
       "\\addcontentsline{toc}{part}{" << theTranslator->trRTFGeneralIndex() << "}\n"
       "\\printindex\n"
       "\n"
       "\\end{document}\n";
531 532
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
533
void LatexGenerator::writeHeaderFile(QFile &f)
534
{
535
  FTextStream t(&f);
536
  t << "% Latex header for doxygen " << versionString << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
537
  writeDefaultHeaderPart1(t);
538
  t << "Your title here";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
539
  writeDefaultHeaderPart2(t);
540
  t << "Generated by";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
541
  writeDefaultHeaderPart3(t);
542 543
}

544 545 546
void LatexGenerator::writeFooterFile(QFile &f)
{
  FTextStream t(&f);
547
  t << "% Latex footer for doxygen " << versionString << endl;
548 549 550
  writeDefaultFooter(t);
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
551 552
void LatexGenerator::writeStyleSheetFile(QFile &f)
{
553
  FTextStream t(&f);
554
  t << "% stylesheet for doxygen " << versionString << endl;
555
  writeDefaultStyleSheet(t);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
556
}
557

558
void LatexGenerator::startFile(const char *name,const char *,const char *)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
559
{
560 561 562
#if 0
  setEncoding(Config_getString("LATEX_OUTPUT_ENCODING"));
#endif
563
  QCString fileName=name;
564
  relPath = relativePathToRoot(fileName);
565
  sourceFileName = stripPath(fileName);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
566 567 568 569 570 571 572
  if (fileName.right(4)!=".tex" && fileName.right(4)!=".sty") fileName+=".tex";
  startPlainFile(fileName);
}

void LatexGenerator::endFile()
{
  endPlainFile();
573
  sourceFileName.resize(0);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
574 575 576 577 578 579 580 581 582 583 584 585 586 587
}

//void LatexGenerator::writeIndex()
//{
//  startFile("refman.tex");
//} 
  
void LatexGenerator::startProjectNumber()
{
  t << "\\\\[1ex]\\large "; 
}

void LatexGenerator::startIndexSection(IndexSections is)
{
588 589
  bool &compactLatex = Config_getBool("COMPACT_LATEX");
  QCString &latexHeader = Config_getString("LATEX_HEADER");
Dimitri van Heesch's avatar
Dimitri van Heesch committed
590 591 592 593
  switch (is)
  {
    case isTitlePageStart:
      {
594
        if (latexHeader.isEmpty())
Dimitri van Heesch's avatar
Dimitri van Heesch committed
595
        {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
596
          writeDefaultHeaderPart1(t);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
597
        }
598
        else
Dimitri van Heesch's avatar
Dimitri van Heesch committed
599
        {
600
          QCString header = fileToString(latexHeader);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
601 602 603 604
          t << substituteKeywords(header,0,
              Config_getString("PROJECT_NAME"),
              Config_getString("PROJECT_NUMBER"),
              Config_getString("PROJECT_BRIEF"));
Dimitri van Heesch's avatar
Dimitri van Heesch committed
605 606 607 608
        }
      }
      break;
    case isTitlePageAuthor:
609
      if (latexHeader.isEmpty())
610
      {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
611
        writeDefaultHeaderPart2(t);
612 613 614
      }
      break;
    case isMainPage:
615
      if (compactLatex) t << "\\section"; else t << "\\chapter";
616
      t << "{"; //Introduction}\n"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
617
      break;
618 619 620 621
    //case isPackageIndex:
    //  if (compactLatex) t << "\\section"; else t << "\\chapter";
    //  t << "{"; //Package Index}\n"
    //  break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
622
    case isModuleIndex:
623 624
      if (compactLatex) t << "\\section"; else t << "\\chapter";
      t << "{"; //Module Index}\n"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
625
      break;
626 627 628 629
    case isDirIndex:
      if (compactLatex) t << "\\section"; else t << "\\chapter";
      t << "{"; //Directory Index}\n"
      break;
630
    case isNamespaceIndex:
631 632
      if (compactLatex) t << "\\section"; else t << "\\chapter";
      t << "{"; //Namespace Index}\"
633
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
634
    case isClassHierarchyIndex:
635 636
      if (compactLatex) t << "\\section"; else t << "\\chapter";
      t << "{"; //Hierarchical Index}\n"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
637 638
      break;
    case isCompoundIndex:
639 640
      if (compactLatex) t << "\\section"; else t << "\\chapter";
      t << "{"; //Annotated Compound Index}\n"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
641 642
      break;
    case isFileIndex:
643 644
      if (compactLatex) t << "\\section"; else t << "\\chapter";
      t << "{"; //Annotated File Index}\n"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
645
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
646
    case isPageIndex:
647 648
      if (compactLatex) t << "\\section"; else t << "\\chapter";
      t << "{"; //Annotated Page Index}\n"
Dimitri van Heesch's avatar
Dimitri van Heesch committed
649
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
650 651
    case isModuleDocumentation:
      {
652
        GroupSDict::Iterator gli(*Doxygen::groupSDict);
653
        GroupDef *gd;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
654
        bool found=FALSE;
655
        for (gli.toFirst();(gd=gli.current()) && !found;++gli)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
656
        {
657 658
          if (!gd->isReference())
          {
659
            if (compactLatex) t << "\\section"; else t << "\\chapter";
660 661 662
            t << "{"; //Module Documentation}\n";
            found=TRUE;
          }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
663 664 665
        }
      }
      break;
666 667
    case isDirDocumentation:
      {
668
        SDict<DirDef>::Iterator dli(*Doxygen::directories);
669 670 671 672 673 674 675 676 677 678 679 680 681
        DirDef *dd;
        bool found=FALSE;
        for (dli.toFirst();(dd=dli.current()) && !found;++dli)
        {
          if (dd->isLinkableInProject())
          {
            if (compactLatex) t << "\\section"; else t << "\\chapter";
            t << "{"; //Module Documentation}\n";
            found=TRUE;
          }
        }
      }
      break;
682 683
    case isNamespaceDocumentation:
      {
684
        NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
685
        NamespaceDef *nd;
686
        bool found=FALSE;
687
        for (nli.toFirst();(nd=nli.current()) && !found;++nli)
688
        {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
689
          if (nd->isLinkableInProject())
690
          {
691
            if (compactLatex) t << "\\section"; else t << "\\chapter";
692 693 694 695 696 697
            t << "{"; // Namespace Documentation}\n":
            found=TRUE;
          }
        } 
      }
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
698 699
    case isClassDocumentation:
      {
700
        ClassSDict::Iterator cli(*Doxygen::classSDict);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
701
        ClassDef *cd=0;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
702
        bool found=FALSE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
703
        for (cli.toFirst();(cd=cli.current()) && !found;++cli)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
704
        {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
705 706
          if (cd->isLinkableInProject() && 
              cd->templateMaster()==0 &&
707
              !cd->isEmbeddedInOuterScope()
Dimitri van Heesch's avatar
Dimitri van Heesch committed
708
             )
Dimitri van Heesch's avatar
Dimitri van Heesch committed
709
          {
710
            if (compactLatex) t << "\\section"; else t << "\\chapter";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
711 712 713 714 715 716 717 718 719
            t << "{"; //Compound Documentation}\n";
            found=TRUE;
          }
        }
      }
      break;
    case isFileDocumentation:
      {
        bool isFirst=TRUE;
720
        FileName *fn=Doxygen::inputNameList->first();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
721 722 723 724 725
        while (fn)
        {
          FileDef *fd=fn->first();
          while (fd)
          {
726
            if (fd->isLinkableInProject())
Dimitri van Heesch's avatar
Dimitri van Heesch committed
727 728 729
            {
              if (isFirst)
              {
730
                if (compactLatex) t << "\\section"; else t << "\\chapter";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
731 732 733 734 735 736 737
                t << "{"; //File Documentation}\n";
                isFirst=FALSE;
                break;
              }
            }
            fd=fn->next();
          }
738
          fn=Doxygen::inputNameList->next();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
739 740 741 742 743
        }
      }
      break;
    case isExampleDocumentation:
      {
744
        if (compactLatex) t << "\\section"; else t << "\\chapter";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
745 746 747 748 749
        t << "{"; //Example Documentation}\n";
      }
      break;
    case isPageDocumentation:
      {
750
        if (compactLatex) t << "\\section"; else t << "\\chapter";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
751 752 753
        t << "{"; //Page Documentation}\n";
      }
      break;
754 755
    case isPageDocumentation2:
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
756 757 758 759 760 761 762
    case isEndIndex:
      break;
  }
}

void LatexGenerator::endIndexSection(IndexSections is)
{
763
  //static bool compactLatex = Config_getBool("COMPACT_LATEX");
764 765
  static bool sourceBrowser = Config_getBool("SOURCE_BROWSER");
  static QCString latexHeader = Config_getString("LATEX_HEADER");
766
  static QCString latexFooter = Config_getString("LATEX_FOOTER");
Dimitri van Heesch's avatar
Dimitri van Heesch committed
767 768 769 770 771
  switch (is)
  {
    case isTitlePageStart:
      break;
    case isTitlePageAuthor:
772
      if (latexHeader.isEmpty())
773
      {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
774
        writeDefaultHeaderPart3(t);
775 776 777
      }
      break;
    case isMainPage:
Dimitri van Heesch's avatar
Dimitri van Heesch committed
778
      {
779 780
        //QCString indexName=Config_getBool("GENERATE_TREEVIEW")?"main":"index";
        QCString indexName="index";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
781 782 783 784
        t << "}\n\\label{index}";
        if (Config_getBool("PDF_HYPERLINKS")) t << "\\hypertarget{index}{}";
        t << "\\input{" << indexName << "}\n";
      }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
785 786
      break;
    case isModuleIndex:
787
      t << "}\n\\input{modules}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
788
      break;
789 790 791
    case isDirIndex:
      t << "}\n\\input{dirs}\n";
      break;
792
    case isNamespaceIndex:
793
      t << "}\n\\input{namespaces}\n";
794
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
795
    case isClassHierarchyIndex:
796
      t << "}\n\\input{hierarchy}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
797 798
      break;
    case isCompoundIndex:
799
      t << "}\n\\input{annotated}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
800 801
      break;
    case isFileIndex:
802
      t << "}\n\\input{files}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
803
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
804
    case isPageIndex:
805
      t << "}\n\\input{pages}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
806
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
807 808
    case isModuleDocumentation:
      {
809
        GroupSDict::Iterator gli(*Doxygen::groupSDict);
810
        GroupDef *gd;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
811
        bool found=FALSE;
812
        for (gli.toFirst();(gd=gli.current()) && !found;++gli)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
813
        {
814 815 816 817 818
          if (!gd->isReference())
          {
            t << "}\n\\input{" << gd->getOutputFileBase() << "}\n";
            found=TRUE;
          }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
819
        }
820
        for (;(gd=gli.current());++gli)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
821
        {
822 823
          if (!gd->isReference())
          {
824
            //if (compactLatex) t << "\\input"; else t << "\\include";
825
            t << "\\include"; 
826 827
            t << "{" << gd->getOutputFileBase() << "}\n";
          }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
828 829 830
        }
      }
      break;
831 832
    case isDirDocumentation:
      {
833
        SDict<DirDef>::Iterator dli(*Doxygen::directories);
834 835 836 837 838 839 840 841 842 843 844 845 846 847
        DirDef *dd;
        bool found=FALSE;
        for (dli.toFirst();(dd=dli.current()) && !found;++dli)
        {
          if (dd->isLinkableInProject())
          {
            t << "}\n\\input{" << dd->getOutputFileBase() << "}\n";
            found=TRUE;
          }
        }
        for (;(dd=dli.current());++dli)
        {
          if (dd->isLinkableInProject())
          {
848 849
            //if (compactLatex) t << "\\input"; else t << "\\include";
            t << "\\input"; 
850 851 852 853 854
            t << "{" << dd->getOutputFileBase() << "}\n";
          }
        }
      }
      break;
855 856
    case isNamespaceDocumentation:
      {
857
        NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
858
        NamespaceDef *nd;
859
        bool found=FALSE;
860
        for (nli.toFirst();(nd=nli.current()) && !found;++nli)
861
        {
862
          if (nd->isLinkableInProject())
863 864 865 866 867
          {
            t << "}\n\\input{" << nd->getOutputFileBase() << "}\n";
            found=TRUE;
          }
        }
868
        while ((nd=nli.current()))
869
        {
870
          if (nd->isLinkableInProject())
871
          {
872 873
            //if (compactLatex) t << "\\input"; else t << "\\include";
            t << "\\input"; 
874 875
            t << "{" << nd->getOutputFileBase() << "}\n";
          }
876
          ++nli;
877 878 879
        }
      }
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
880 881
    case isClassDocumentation:
      {
882
        ClassSDict::Iterator cli(*Doxygen::classSDict);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
883
        ClassDef *cd=0;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
884
        bool found=FALSE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
885
        for (cli.toFirst();(cd=cli.current()) && !found;++cli)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
886
        {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
887 888
          if (cd->isLinkableInProject() && 
              cd->templateMaster()==0 &&
889
             !cd->isEmbeddedInOuterScope()
Dimitri van Heesch's avatar
Dimitri van Heesch committed
890
             )
Dimitri van Heesch's avatar
Dimitri van Heesch committed
891
          {
892
            t << "}\n\\input{" << cd->getOutputFileBase() << "}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
893 894 895
            found=TRUE;
          }
        }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
896
        for (;(cd=cli.current());++cli)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
897
        {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
898 899
          if (cd->isLinkableInProject() && 
              cd->templateMaster()==0 &&
900
             !cd->isEmbeddedInOuterScope()
Dimitri van Heesch's avatar
Dimitri van Heesch committed
901
             )
Dimitri van Heesch's avatar
Dimitri van Heesch committed
902
          {
903 904
            //if (compactLatex) t << "\\input"; else t << "\\include";
            t << "\\input"; 
905
            t << "{" << cd->getOutputFileBase() << "}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
906 907 908 909 910 911 912
          } 
        }
      }
      break;
    case isFileDocumentation:
      {
        bool isFirst=TRUE;
913
        FileName *fn=Doxygen::inputNameList->first();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
914 915 916 917 918
        while (fn)
        {
          FileDef *fd=fn->first();
          while (fd)
          {
919
            if (fd->isLinkableInProject())
Dimitri van Heesch's avatar
Dimitri van Heesch committed
920 921 922
            {
              if (isFirst)
              {
923
                t << "}\n\\input{" << fd->getOutputFileBase() << "}\n";
924
                if (sourceBrowser && m_prettyCode && fd->generateSourceFile())
925
                {
926 927
                  //t << "\\include{" << fd->getSourceFileBase() << "}\n";
                  t << "\\input{" << fd->getSourceFileBase() << "}\n";
928
                }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
929 930 931 932
                isFirst=FALSE;
              }
              else
              {
933 934
                //if (compactLatex) t << "\\input" ; else t << "\\include";
                t << "\\input" ; 
935
                t << "{" << fd->getOutputFileBase() << "}\n";
936
                if (sourceBrowser && m_prettyCode && fd->generateSourceFile())
937
                {
938 939
                  //t << "\\include{" << fd->getSourceFileBase() << "}\n";
                  t << "\\input{" << fd->getSourceFileBase() << "}\n";
940
                }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
941 942 943 944
              }
            }
            fd=fn->next();
          }
945
          fn=Doxygen::inputNameList->next();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
946 947 948 949 950 951
        }
      }
      break;
    case isExampleDocumentation:
      {
        t << "}\n";
952
        PageSDict::Iterator pdi(*Doxygen::exampleSDict);
953 954
        PageDef *pd=pdi.toFirst();
        if (pd)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
955
        {
956
          t << "\\input{" << pd->getOutputFileBase() << "}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
957
        }
958
        for (++pdi;(pd=pdi.current());++pdi)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
959
        {
960 961
          //if (compactLatex) t << "\\input" ; else t << "\\include";
          t << "\\input"; 
962
          t << "{" << pd->getOutputFileBase() << "}\n";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
963 964 965 966 967 968
        }
      }
      break;
    case isPageDocumentation:
      {
        t << "}\n";
969
#if 0
970
        PageSDict::Iterator pdi(*Doxygen::pageSDict);
971
        PageDef *pd=pdi.toFirst();
972
        bool first=TRUE;
973
        for (pdi.toFirst();(pd=pdi.current());++pdi)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
974
        {
975
          if (!pd->getGroupDef() && !pd->isReference())
976
          {
977 978 979 980
             if (compactLatex) t << "\\section"; else t << "\\chapter";
             t << "{" << pd->title();
             t << "}\n";
            
981
            if (compactLatex || first) t << "\\input" ; else t << "\\include";
982
            t << "{" << pd->getOutputFileBase() << "}\n";
983 984
            first=FALSE;
          }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
985
        }
986
#endif
Dimitri van Heesch's avatar
Dimitri van Heesch committed
987 988
      }
      break;
989 990
    case isPageDocumentation2:
      break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
991
    case isEndIndex:
992 993 994 995 996 997 998
      if (latexFooter.isEmpty())
      {
        writeDefaultFooter(t);
      }
      else
      {
        QCString footer = fileToString(latexFooter);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
999 1000 1001 1002
        t << substituteKeywords(footer,0,
              Config_getString("PROJECT_NAME"),
              Config_getString("PROJECT_NUMBER"),
              Config_getString("PROJECT_BRIEF"));
1003
      }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1004 1005 1006
      break;
  }
}
1007

1008
void LatexGenerator::writePageLink(const char *name, bool /*first*/)
1009
{
1010
  //bool &compactLatex = Config_getBool("COMPACT_LATEX");
1011 1012 1013
  // next is remove for bug615957
  //if (compactLatex || first) t << "\\input" ; else t << "\\include";
  t << "\\input" ; 
1014 1015 1016 1017
  t << "{" << name << "}\n";
}


Dimitri van Heesch's avatar
Dimitri van Heesch committed
1018 1019
void LatexGenerator::writeStyleInfo(int part)
{
1020 1021 1022 1023 1024 1025
  if (part > 0)
    return;

  startPlainFile("doxygen.sty");
  writeDefaultStyleSheet(t);
  endPlainFile();
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1026 1027 1028 1029 1030 1031 1032
}

void LatexGenerator::newParagraph()
{
  t << endl << endl;
}

1033 1034 1035 1036 1037 1038 1039
void LatexGenerator::startParagraph()
{
  t << endl << endl;
}

void LatexGenerator::endParagraph()
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1040
  t << endl << endl;
1041 1042
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1043 1044 1045 1046 1047
void LatexGenerator::writeString(const char *text)
{
  t << text;
}

1048
void LatexGenerator::startIndexItem(const char *ref,const char *fn)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1049 1050 1051 1052 1053
{
  t << "\\item ";
  if (!ref && fn)
  {
    t << "\\contentsline{section}{";
1054 1055 1056 1057 1058 1059 1060
  }
}

void LatexGenerator::endIndexItem(const char *ref,const char *fn)
{
  if (!ref && fn)
  {
1061
    t << "}{\\pageref{" << fn << "}}{}" << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
  }
}

//void LatexGenerator::writeIndexFileItem(const char *,const char *text)
//{
//  t << "\\item\\contentsline{section}{";
//  docify(text);
//  t << "}{\\pageref{" << text << "}}" << endl;
//}


Dimitri van Heesch's avatar
Dimitri van Heesch committed
1073
void LatexGenerator::startHtmlLink(const char *url)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1074
{
1075
  if (Config_getBool("PDF_HYPERLINKS"))
1076 1077 1078 1079 1080
  {
    t << "\\href{";
    t << url;
    t << "}";
  }
1081
  t << "{\\tt ";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1082 1083 1084 1085
}

void LatexGenerator::endHtmlLink()
{
1086
  t << "}";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1087 1088
}

1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
//void LatexGenerator::writeMailLink(const char *url)
//{
//  if (Config_getBool("PDF_HYPERLINKS"))
//  {
//    t << "\\href{mailto:";
//    t << url;
//    t << "}";
//  }
//  t << "{\\tt "; 
//  docify(url);
//  t << "}";
//}
1101

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1102 1103 1104
void LatexGenerator::writeStartAnnoItem(const char *,const char *,
                                        const char *path,const char *name)
{
1105
  t << "\\item\\contentsline{section}{\\bf ";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1106 1107 1108 1109 1110 1111 1112
  if (path) docify(path);
  docify(name); 
  t << "} ";
}

void LatexGenerator::writeEndAnnoItem(const char *name)
{
1113
  t << "}{\\pageref{" << name << "}}{}" << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1114 1115
}

1116 1117 1118 1119 1120 1121 1122 1123 1124
void LatexGenerator::startIndexKey()
{
  t << "\\item\\contentsline{section}{";
}

void LatexGenerator::endIndexKey()
{
}

1125
void LatexGenerator::startIndexValue(bool hasBrief)
1126
{
1127
  t << " ";
1128
  if (hasBrief) t << "\\\\*";
1129 1130
}

1131
void LatexGenerator::endIndexValue(const char *name,bool /*hasBrief*/)
1132
{
1133
  //if (hasBrief) t << ")";
1134 1135 1136
  t << "}{\\pageref{" << name << "}}{}" << endl;
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1137 1138 1139
//void LatexGenerator::writeClassLink(const char *,const char *,
//                                    const char *,const char *name)
//{
1140
//  t << "{\\bf ";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1141 1142 1143 1144
//  docify(name);
//  t << "}"; 
//}

1145 1146
void LatexGenerator::startTextLink(const char *f,const char *anchor)
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1147
  if (!disableLinks && Config_getBool("PDF_HYPERLINKS"))
1148 1149
  {
    t << "\\hyperlink{";
1150
    if (f) t << stripPath(f);
1151 1152 1153
    if (anchor) t << "_" << anchor; 
    t << "}{";
  }
1154 1155
  else
  {
1156
    t << "{\\bf ";
1157
  }
1158 1159 1160 1161
}

void LatexGenerator::endTextLink()
{
1162
  t << "}";
1163 1164
}

1165 1166
void LatexGenerator::writeObjectLink(const char *ref, const char *f,
                                     const char *anchor, const char *text)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1167
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1168
  if (!disableLinks && !ref && Config_getBool("PDF_HYPERLINKS"))
1169 1170
  {
    t << "\\hyperlink{";
1171
    if (f) t << stripPath(f);
1172 1173
    if (f && anchor) t << "_"; 
    if (anchor) t << anchor; 
1174 1175 1176 1177 1178 1179
    t << "}{";
    docify(text);
    t << "}";
  }
  else
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1180
    t << "{\\bf ";
1181 1182 1183 1184 1185 1186 1187
    docify(text);
    t << "}";
  } 
}

void LatexGenerator::startPageRef()
{
1188
  t << " \\doxyref{}{";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1189 1190
}

1191
void LatexGenerator::endPageRef(const char *clname, const char *anchor)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1192
{
1193
  t << "}{";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1194 1195
  if (clname) t << clname; 
  if (anchor) t << "_" << anchor;
1196
  t << "}";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1197 1198
}

1199 1200
void LatexGenerator::writeCodeLink(const char *ref,const char *f,
                                   const char *anchor,const char *name,
1201
                                   const char *)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1202
{
1203 1204
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1205
  int l = qstrlen(name);
1206 1207 1208 1209 1210
  if (col+l>80)
  {
    t << "\n      ";
    col=0;
  }
1211
  if (/*m_prettyCode &&*/ !disableLinks && !ref && usePDFLatex && pdfHyperlinks)
1212 1213 1214 1215 1216
  {
    t << "\\hyperlink{";
    if (f) t << stripPath(f);
    if (f && anchor) t << "_"; 
    if (anchor) t << anchor; 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1217 1218 1219
    t << "}{";
    codify(name);
    t << "}";
1220 1221 1222 1223 1224 1225
  }
  else
  {
    t << name;
  }
  col+=l;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1226 1227
}

1228 1229
void LatexGenerator::startTitleHead(const char *fileName)
{
1230 1231 1232
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
  if (usePDFLatex && pdfHyperlinks && fileName)
1233
  {
1234
    t << "\\hypertarget{" << stripPath(fileName) << "}{";
1235
  }
1236
  if (Config_getBool("COMPACT_LATEX")) 
1237 1238 1239 1240 1241 1242 1243
  {
    t << "\\subsection{"; 
  }
  else 
  {
    t << "\\section{"; 
  }
1244 1245 1246 1247
}

void LatexGenerator::endTitleHead(const char *fileName,const char *name)
{
1248 1249
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
1250 1251 1252
  t << "}" << endl;
  if (name)
  {
1253
    t << "\\label{" << stripPath(fileName) << "}\\index{";
1254 1255 1256
    escapeLabelName(name);
    t << "@{";
    escapeMakeIndexChars(name);
1257
    t << "}}" << endl;
1258
  }
1259
  if (usePDFLatex && pdfHyperlinks && fileName)
1260 1261
  {
    t << "}" << endl;
1262 1263
  }
}
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1264 1265 1266

void LatexGenerator::startTitle()
{
1267
  if (Config_getBool("COMPACT_LATEX")) 
1268 1269 1270 1271 1272 1273 1274
  {
    t << "\\subsection{"; 
  }
  else 
  {
    t << "\\section{"; 
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1275 1276
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1277
void LatexGenerator::startGroupHeader(int extraIndentLevel)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1278
{
1279
  if (Config_getBool("COMPACT_LATEX")) 
1280
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1281
    extraIndentLevel++;
1282
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296

  if (extraIndentLevel==3)
  {
    t << "\\subparagraph*{"; 
  }
  else if (extraIndentLevel==2)
  {
    t << "\\paragraph{";
  }
  else if (extraIndentLevel==1)
  {
    t << "\\subsubsection{";
  }
  else // extraIndentLevel==0
1297 1298 1299
  {
    t << "\\subsection{";
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1300
  disableLinks=TRUE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1301 1302
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1303
void LatexGenerator::endGroupHeader(int)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1304
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1305
  disableLinks=FALSE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1306 1307 1308
  t << "}" << endl;
}

1309
void LatexGenerator::startMemberHeader(const char *)
1310
{
1311
  if (Config_getBool("COMPACT_LATEX")) 
1312 1313 1314 1315 1316 1317 1318
  {
    t << "\\subsubsection*{"; 
  }
  else 
  {
    t << "\\subsection*{";
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1319
  disableLinks=TRUE;
1320 1321 1322 1323
}

void LatexGenerator::endMemberHeader()
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1324
  disableLinks=FALSE;
1325 1326 1327
  t << "}" << endl;
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1328
void LatexGenerator::startMemberDoc(const char *clname,
1329 1330
                                    const char *memname,
                                    const char *,
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1331 1332
                                    const char *title,
                                    bool showInline)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1333
{ 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1334
  if (memname && memname[0]!='@')
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1335
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1336 1337 1338
    t << "\\index{";
    if (clname)
    {
1339 1340 1341
      escapeLabelName(clname);
      t << "@{";
      escapeMakeIndexChars(clname);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1342 1343
      t << "}!";
    }
1344 1345 1346
    escapeLabelName(memname);
    t << "@{";
    escapeMakeIndexChars(memname);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1347 1348
    t << "}}" << endl;

1349 1350 1351 1352
    t << "\\index{";
    escapeLabelName(memname);
    t << "@{";
    escapeMakeIndexChars(memname);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1353 1354 1355 1356 1357 1358 1359 1360
    t << "}";
    if (clname)
    {
      t << "!" << clname << "@{";
      docify(clname);
      t << "}"; 
    }
    t << "}" << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1361
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1362 1363 1364 1365 1366 1367 1368
  static const char *levelLab[] = { "subsubsection","paragraph","subparagraph", "subparagraph" };
  static bool compactLatex = Config_getBool("COMPACT_LATEX");
  int level=0;
  if (showInline) level+=2;
  if (compactLatex) level++;
  t << "\\" << levelLab[level]; 

1369 1370 1371 1372 1373 1374
  //if (Config_getBool("PDF_HYPERLINKS") && memname) 
  //{
  //  t << "["; 
  //  escapeMakeIndexChars(this,t,memname);
  //  t << "]";
  //}
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1375
  t << "[{";
1376
  escapeMakeIndexChars(title);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1377
  t << "}]";
1378
  t << "{\\setlength{\\rightskip}{0pt plus 5cm}";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1379
  disableLinks=TRUE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1380 1381
}

1382
void LatexGenerator::endMemberDoc(bool) 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1383
{ 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1384
  disableLinks=FALSE;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1385
  t << "}";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1386
  //if (Config_getBool("COMPACT_LATEX")) t << "\\hfill";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1387 1388
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1389
void LatexGenerator::startDoxyAnchor(const char *fName,const char *,
1390 1391
                                     const char *anchor, const char *,
                                     const char *)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1392
{
1393 1394 1395
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
  if (usePDFLatex && pdfHyperlinks)
1396 1397
  {
    t << "\\hypertarget{";
1398
    if (fName) t << stripPath(fName);
1399
    if (anchor) t << "_" << anchor;
1400
    t << "}{";
1401
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1402 1403
}

1404
void LatexGenerator::endDoxyAnchor(const char *fName,const char *anchor)
1405
{
1406 1407 1408
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
  if (usePDFLatex && pdfHyperlinks)
1409
  {
1410
    t << "}";
1411
  }
1412
  t << "\\label{";
1413
  if (fName) t << stripPath(fName);
1414 1415
  if (anchor) t << "_" << anchor;
  t << "}" << endl;
1416 1417
}

1418 1419
void LatexGenerator::writeAnchor(const char *fName,const char *name)
{ 
1420
  //printf("LatexGenerator::writeAnchor(%s,%s)\n",fName,name);
1421
  t << "\\label{" << name << "}" << endl; 
1422 1423 1424
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
  if (usePDFLatex && pdfHyperlinks)
1425
  {
1426 1427 1428 1429 1430 1431 1432 1433
    if (fName)
    {
      t << "\\hypertarget{" << stripPath(fName) << "_" << name << "}{}" << endl;
    }
    else
    {
      t << "\\hypertarget{" << name << "}{}" << endl;
    }
1434 1435 1436
  }
}

1437 1438 1439 1440 1441 1442

//void LatexGenerator::writeLatexLabel(const char *clName,const char *anchor)
//{
//  writeDoxyAnchor(0,clName,anchor,0);
//}

1443
void LatexGenerator::addIndexItem(const char *s1,const char *s2)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1444 1445 1446
{
  if (s1)
  {
1447 1448 1449 1450
    t << "\\index{";
    escapeLabelName(s1);
    t << "@{";
    escapeMakeIndexChars(s1);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1451 1452 1453
    t << "}";
    if (s2)
    {
1454 1455 1456 1457
      t << "!";
      escapeLabelName(s2);
      t << "@{";
      escapeMakeIndexChars(s2);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1458 1459 1460 1461 1462 1463
      t << "}";
    }
    t << "}";
  }
}

1464

1465
void LatexGenerator::startSection(const char *lab,const char *,SectionInfo::SectionType type)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1466
{
1467 1468 1469
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
  static bool usePDFLatex   = Config_getBool("USE_PDFLATEX");
  if (usePDFLatex && pdfHyperlinks)
1470
  {
1471
    t << "\\hypertarget{" << stripPath(lab) << "}{}";
1472
  }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1473
  t << "\\";
1474
  if (Config_getBool("COMPACT_LATEX"))
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1475
  {
1476 1477
    switch(type)
    {
1478 1479 1480 1481 1482
      case SectionInfo::Page:          t << "subsection"; break;
      case SectionInfo::Section:       t << "subsubsection"; break;
      case SectionInfo::Subsection:    t << "paragraph"; break;
      case SectionInfo::Subsubsection: t << "subparagraph"; break;
      case SectionInfo::Paragraph:     t << "subparagraph"; break;
1483 1484 1485
      default: ASSERT(0); break;
    }
    t << "{";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1486 1487 1488
  }
  else
  {
1489 1490
    switch(type)
    {
1491 1492 1493 1494 1495
      case SectionInfo::Page:          t << "section"; break;
      case SectionInfo::Section:       t << "subsection"; break;
      case SectionInfo::Subsection:    t << "subsubsection"; break;
      case SectionInfo::Subsubsection: t << "paragraph"; break;
      case SectionInfo::Paragraph:     t << "subparagraph"; break;
1496 1497 1498
      default: ASSERT(0); break;
    }
    t << "{";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1499
  }
1500 1501
}

1502
void LatexGenerator::endSection(const char *lab,SectionInfo::SectionType)
1503
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1504
  t << "}\\label{" << lab << "}" << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1505 1506
}

1507

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1508 1509
void LatexGenerator::docify(const char *str)
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1510
  filterLatexString(t,str,insideTabbing,FALSE,FALSE);
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1511 1512 1513 1514 1515 1516 1517 1518
}

void LatexGenerator::codify(const char *str)
{
  if (str)
  { 
    const char *p=str;
    char c;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1519
    //char cs[5];
1520
    int spacesToNextTabStop;
1521
    static int tabSize = Config_getInt("TAB_SIZE");
1522
    const int maxLineLen = 108;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1523 1524 1525
    QCString result(4*maxLineLen+1); // worst case for 1 line of 4-byte chars
    int i;
    while ((c=*p))
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1526 1527 1528
    {
      switch(c)
      {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1529 1530
        case 0x0c: p++;  // remove ^L
                   break;
1531
        case '\t': spacesToNextTabStop =
1532
                         tabSize - (col%tabSize);
1533
                   t << Doxygen::spaces.left(spacesToNextTabStop); 
1534
                   col+=spacesToNextTabStop;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1535
                   p++;
1536
                   break; 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572
        case '\n': t << '\n'; col=0; p++;
                   break;
        default:   
                   i=0;

#undef  COPYCHAR
// helper macro to copy a single utf8 character, dealing with multibyte chars.
#define COPYCHAR() do {                                           \
                     result[i++]=c; p++;                          \
                     if (c<0) /* multibyte utf-8 character */     \
                     {                                            \
                       /* 1xxx.xxxx: >=2 byte character */        \
                       result[i++]=*p++;                          \
                       if (((uchar)c&0xE0)==0xE0)                 \
                       {                                          \
                         /* 111x.xxxx: >=3 byte character */      \
                         result[i++]=*p++;                        \
                       }                                          \
                       if (((uchar)c&0xF0)==0xF0)                 \
                       {                                          \
                         /* 1111.xxxx: 4 byte character */        \
                         result[i++]=*p++;                        \
                       }                                          \
                     }                                            \
                     col++;                                       \
                   } while(0)

                   // gather characters until we find whitespace or are at
                   // the end of a line
                   COPYCHAR();
                   if (col>=maxLineLen) // force line break
                   {
                     t << "\n      ";
                     col=0;
                   }
                   else // copy more characters
1573
                   {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1574 1575 1576
                     while (col<maxLineLen && (c=*p) && 
                            c!=0x0c && c!='\t' && c!='\n' && c!=' '
                           )
1577
                     {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1578
                       COPYCHAR();
1579
                     }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1580
                     if (col>=maxLineLen) // force line break
1581
                     {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1582 1583
                       t << "\n      ";
                       col=0;
1584 1585
                     }
                   }
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1586
                   result[i]=0; // add terminator
1587 1588
                   //if (m_prettyCode)
                   //{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1589
                     filterLatexString(t,result,insideTabbing,TRUE);
1590 1591 1592 1593 1594
                   //}
                   //else
                   //{
                   //  t << result;
                   //}
1595
                   break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
      }
    }
  }
}

void LatexGenerator::writeChar(char c)
{
  char cs[2];
  cs[0]=c;
  cs[1]=0;
  docify(cs);
}

void LatexGenerator::startClassDiagram()
{
1611
  //if (Config_getBool("COMPACT_LATEX")) t << "\\subsubsection"; else t << "\\subsection";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1612
  //t << "{";
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1613 1614
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1615
void LatexGenerator::endClassDiagram(const ClassDiagram &d,
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1616 1617 1618 1619 1620
                                       const char *fileName,const char *)
{
  d.writeFigure(t,dir,fileName);
}

1621

1622 1623 1624
void LatexGenerator::startAnonTypeScope(int indent)
{
  if (indent==0)
1625
  {
1626 1627 1628
    t << "\\begin{tabbing}" << endl;
    t << "xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=xx\\=\\kill" << endl;
    insideTabbing=TRUE;
1629
  }
1630
  m_indent=indent;
1631 1632
}

1633
void LatexGenerator::endAnonTypeScope(int indent)
1634
{
1635
  if (indent==0)
1636 1637 1638 1639
  {
    t << endl << "\\end{tabbing}";
    insideTabbing=FALSE;
  }
1640
  m_indent=indent;
1641 1642
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1643 1644 1645 1646 1647 1648 1649 1650
void LatexGenerator::startMemberTemplateParams()
{
  if (templateMemberItem)
  {
    t << "{\\footnotesize ";
  }
}

1651
void LatexGenerator::endMemberTemplateParams(const char *,const char *)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1652 1653 1654 1655 1656 1657 1658
{
  if (templateMemberItem)
  {
    t << "}\\\\";
  }
}

1659
void LatexGenerator::startMemberItem(const char *,int annoType,const char *) 
1660 1661 1662 1663 1664
{ 
  //printf("LatexGenerator::startMemberItem(%d)\n",annType);
  if (!insideTabbing)
  {
    t << "\\item " << endl; 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1665
    templateMemberItem = (annoType == 3);
1666 1667 1668 1669 1670
  }
}

void LatexGenerator::endMemberItem() 
{
1671 1672 1673
  if (insideTabbing)
  {
    t << "\\\\";
1674
  } 
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1675
  templateMemberItem = FALSE;
1676 1677 1678
  t << endl; 
}

1679
void LatexGenerator::startMemberDescription(const char *,const char *) 
1680 1681 1682
{
  if (!insideTabbing)
  { 
1683
    t << "\\begin{DoxyCompactList}\\small\\item\\em "; 
1684 1685 1686
  }
  else
  {
1687
    for (int i=0;i<m_indent+2;i++) t << "\\>";
1688 1689 1690 1691 1692 1693 1694 1695
    t << "{\\em ";
  }
}

void LatexGenerator::endMemberDescription() 
{ 
  if (!insideTabbing)
  {
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1696 1697
    //t << "\\item\\end{DoxyCompactList}"; 
    t << "\\end{DoxyCompactList}"; 
1698 1699 1700
  }
  else
  {
1701
    t << "}\\\\\n";
1702 1703 1704 1705
  }
}


1706
void LatexGenerator::writeNonBreakableSpace(int) 
1707
{
1708
  //printf("writeNonBreakbleSpace()\n");
1709
  if (insideTabbing)
1710
  {
1711
    t << "\\>";
1712
  }
1713
  else
1714
  {
1715
    t << "~"; 
1716
  }
1717 1718 1719 1720 1721
}

void LatexGenerator::startMemberList()  
{ 
  if (!insideTabbing)
1722
  {
1723
    t << "\\begin{DoxyCompactItemize}" << endl; 
1724
  }
1725 1726 1727 1728
}

void LatexGenerator::endMemberList()    
{
1729
  //printf("LatexGenerator::endMemberList(%d)\n",insideTabbing);
1730
  if (!insideTabbing)
1731
  {
1732
    t << "\\end{DoxyCompactItemize}"   << endl; 
1733
  }
1734 1735
}

1736

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1737
void LatexGenerator::startMemberGroupHeader(bool hasHeader)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1738
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1739
  if (hasHeader) t << "\\begin{Indent}";
1740 1741 1742 1743 1744 1745 1746 1747 1748 1749
  t << "{\\bf ";
  // changed back to rev 756 due to bug 660501
  //if (Config_getBool("COMPACT_LATEX")) 
  //{
  //  t << "\\subparagraph*{";
  //}
  //else
  //{
  //  t << "\\paragraph*{";
  //}
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1750 1751 1752 1753
}

void LatexGenerator::endMemberGroupHeader()
{
1754 1755 1756
  // changed back to rev 756 due to bug 660501
  t << "}\\par" << endl;
  //t << "}" << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772
}

void LatexGenerator::startMemberGroupDocs()
{
  t << "{\\em ";
}

void LatexGenerator::endMemberGroupDocs()
{
  t << "}";
}

void LatexGenerator::startMemberGroup()
{
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1773
void LatexGenerator::endMemberGroup(bool hasHeader)
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1774
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1775 1776
  if (hasHeader)t << "\\end{Indent}"; 
  t << endl;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1777
}
1778 1779 1780

void LatexGenerator::startDotGraph() 
{
1781
  newParagraph();
1782 1783
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1784
void LatexGenerator::endDotGraph(const DotClassGraph &g) 
1785
{
1786
  g.writeGraph(t,EPS,Config_getString("LATEX_OUTPUT"),fileName,relPath);
1787 1788 1789 1790 1791 1792
}

void LatexGenerator::startInclDepGraph() 
{
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1793
void LatexGenerator::endInclDepGraph(const DotInclDepGraph &g) 
1794
{
1795
  g.writeGraph(t,EPS,Config_getString("LATEX_OUTPUT"),fileName,relPath);
1796 1797
}

1798 1799 1800 1801
void LatexGenerator::startGroupCollaboration() 
{
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1802
void LatexGenerator::endGroupCollaboration(const DotGroupCollaboration &g) 
1803
{
1804
  g.writeGraph(t,EPS,Config_getString("LATEX_OUTPUT"),fileName,relPath);
1805 1806
}

1807 1808 1809 1810
void LatexGenerator::startCallGraph() 
{
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1811
void LatexGenerator::endCallGraph(const DotCallGraph &g) 
1812
{
1813
  g.writeGraph(t,EPS,Config_getString("LATEX_OUTPUT"),fileName,relPath);
1814 1815
}

1816 1817 1818 1819
void LatexGenerator::startDirDepGraph() 
{
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1820
void LatexGenerator::endDirDepGraph(const DotDirDeps &g) 
1821
{
1822
  g.writeGraph(t,EPS,Config_getString("LATEX_OUTPUT"),fileName,relPath);
1823 1824
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853
void LatexGenerator::startDescription() 
{ 
  t << "\\begin{description}" << endl; 
}

void LatexGenerator::endDescription()   
{ 
  t << "\\end{description}" << endl; 
  firstDescItem=TRUE;
}

void LatexGenerator::startDescItem()    
{ 
  firstDescItem=TRUE;
  t << "\\item["; 
}

void LatexGenerator::endDescItem()      
{ 
  if (firstDescItem) 
  {
    t << "]" << endl;
    firstDescItem=FALSE;
  } 
  else
  {
    lineBreak();
  }
}
1854

1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
void LatexGenerator::startSimpleSect(SectionTypes,const char *file,
                                     const char *anchor,const char *title)
{
  t << "\\begin{Desc}\n\\item[";
  if (file)
  {
    writeObjectLink(0,file,anchor,title);
  }
  else
  {
    docify(title);
  }
  t << "]";
}

void LatexGenerator::endSimpleSect()
{
  t << "\\end{Desc}" << endl;
}

void LatexGenerator::startParamList(ParamListTypes,const char *title)
{
  t << "\\begin{Desc}\n\\item[";
  docify(title);
  t << "]";
}

void LatexGenerator::endParamList()
{
  t << "\\end{Desc}" << endl;
}

1887 1888 1889 1890 1891 1892 1893
void LatexGenerator::startParameterList(bool openBracket)
{
  /* start of ParameterType ParameterName list */
  if (openBracket) t << "(";
  t << endl << "\\begin{DoxyParamCaption}" << endl;
}

1894 1895 1896 1897
void LatexGenerator::endParameterList()
{
}

1898
void LatexGenerator::startParameterType(bool first,const char *key)
1899 1900
{
  t << "\\item[{";
1901
  if (!first && key) t << key;
1902 1903 1904
}

void LatexGenerator::endParameterType()
1905
{
1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
  t << "}]";
}

void LatexGenerator::startParameterName(bool /*oneArgOnly*/)
{
  t << "{";
}

void LatexGenerator::endParameterName(bool last,bool /* emptyList */,bool closeBracket)
{
  t << "}" << endl;

  if (last)
1919
  {
1920 1921
    t << "\\end{DoxyParamCaption}" << endl;
    if (closeBracket) t << ")";
1922 1923
  }
}
1924

1925 1926 1927 1928 1929 1930 1931 1932
void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket)
{
  if (prefix)
      t << " " << prefix;
  else if (closeBracket)
      t << ")";
  t << " ";
}
1933

Dimitri van Heesch's avatar
Dimitri van Heesch committed
1934
void LatexGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *)
1935
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1936 1937
  LatexDocVisitor *visitor = 
    new LatexDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""),insideTabbing);
1938 1939 1940 1941
  n->accept(visitor);
  delete visitor; 
}

1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982
void LatexGenerator::startConstraintList(const char *header)
{
  t << "\\begin{Desc}\n\\item[";
  docify(header);
  t << "]";
  t << "\\begin{description}" << endl;
}

void LatexGenerator::startConstraintParam()
{
  t << "\\item[{\\em ";
}

void LatexGenerator::endConstraintParam()
{
}

void LatexGenerator::startConstraintType()
{
  t << "} : {\\em ";
}

void LatexGenerator::endConstraintType()
{
  t << "}]";
}

void LatexGenerator::startConstraintDocs()
{
}

void LatexGenerator::endConstraintDocs()
{
}

void LatexGenerator::endConstraintList()
{
  t << "\\end{description}" << endl;
  t << "\\end{Desc}" << endl;
}

1983 1984
void LatexGenerator::escapeLabelName(const char *s)
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1985
  if (s==0) return;
1986 1987
  const char *p=s;
  char c;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1988
  QCString result(qstrlen(s)+1); // worst case allocation
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1989
  int i;
1990 1991 1992 1993 1994
  while ((c=*p++))
  {
    switch (c)
    {
      case '%': t << "\\%";       break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007
      // NOTE: adding a case here, means adding it to while below as well!
      default:  
        i=0;
        // collect as long string as possible, before handing it to docify
        result[i++]=c;
        while ((c=*p) && c!='%')
        {
          result[i++]=c;
          p++;
        }
        result[i]=0;
        docify(result); 
        break;
2008 2009 2010 2011 2012 2013
    }
  }
}

void LatexGenerator::escapeMakeIndexChars(const char *s)
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
2014
  if (s==0) return;
2015 2016
  const char *p=s;
  char c;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
2017
  QCString result(qstrlen(s)+1); // worst case allocation
Dimitri van Heesch's avatar
Dimitri van Heesch committed
2018
  int i;
2019 2020 2021 2022 2023 2024 2025 2026
  while ((c=*p++))
  {
    switch (c)
    {
      case '"': t << "\"\""; break;
      case '@': t << "\"@"; break;
      case '[': t << "["; break;
      case ']': t << "]"; break;
Dimitri van Heesch's avatar
Dimitri van Heesch committed
2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039
      // NOTE: adding a case here, means adding it to while below as well!
      default:  
        i=0;
        // collect as long string as possible, before handing it to docify
        result[i++]=c;
        while ((c=*p) && c!='"' && c!='@' && c!='[' && c!=']')
        {
          result[i++]=c;
          p++;
        }
        result[i]=0;
        docify(result); 
        break;
2040 2041 2042
    }
  }
}
2043

2044 2045
void LatexGenerator::startCodeFragment()
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
2046
  t << "\n\\begin{DoxyCode}\n";
2047 2048 2049 2050
}

void LatexGenerator::endCodeFragment()
{
Dimitri van Heesch's avatar
Dimitri van Heesch committed
2051
  t << "\\end{DoxyCode}\n";
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
}

void LatexGenerator::writeLineNumber(const char *ref,const char *fileName,const char *anchor,int l)
{
  if (m_prettyCode)
  {
    QCString lineNumber;
    lineNumber.sprintf("%05d",l);

    if (fileName && !sourceFileName.isEmpty())
    {
      QCString lineAnchor;
      lineAnchor.sprintf("_l%05d",l);
      lineAnchor.prepend(sourceFileName);
      startCodeAnchor(lineAnchor);
      writeCodeLink(ref,fileName,anchor,lineNumber,0);
      endCodeAnchor();
    }
    else
    { 
      codify(lineNumber);
    }
    t << " ";
  }
  else
  {
    t << l << " ";
  }
}

Dimitri van Heesch's avatar
Dimitri van Heesch committed
2082
void LatexGenerator::startCodeLine(bool)
2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093
{
  col=0;
}

void LatexGenerator::endCodeLine()
{
  codify("\n");
}

void LatexGenerator::startFontClass(const char *name)
{
2094
  //if (!m_prettyCode) return;
2095 2096 2097 2098 2099
  t << "\\textcolor{" << name << "}{";
}

void LatexGenerator::endFontClass()
{
2100
  //if (!m_prettyCode) return;
2101 2102 2103 2104 2105 2106 2107
  t << "}";
}

void LatexGenerator::startCodeAnchor(const char *name) 
{
  static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
  static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
2108
  //if (!m_prettyCode) return;
2109 2110 2111 2112 2113 2114 2115 2116 2117
  if (usePDFLatex && pdfHyperlinks)
  {
    t << "\\hypertarget{" << stripPath(name) << "}{}";
  }
}

void LatexGenerator::endCodeAnchor() 
{
}
2118

Dimitri van Heesch's avatar
Dimitri van Heesch committed
2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135
void LatexGenerator::startInlineHeader()
{
  if (Config_getBool("COMPACT_LATEX")) 
  {
    t << "\\paragraph*{"; 
  }
  else 
  {
    t << "\\subsubsection*{";
  }
}

void LatexGenerator::endInlineHeader()
{
  t << "}" << endl;
}

2136 2137 2138 2139 2140 2141 2142 2143
void LatexGenerator::lineBreak(const char *)
{
  if (insideTabbing)
  {
    t << "\\\\\n";
  }
  else
  {
2144
    t << "\\\\*\n";
2145 2146 2147
  }
}

2148 2149
void LatexGenerator::startMemberDocSimple()
{
2150
  t << "\\begin{DoxyFields}{";
2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186
  docify(theTranslator->trCompoundMembers());
  t << "}" << endl;
}

void LatexGenerator::endMemberDocSimple()
{
  t << "\\end{DoxyFields}" << endl;
}

void LatexGenerator::startInlineMemberType()
{
}

void LatexGenerator::endInlineMemberType()
{
  t << "&" << endl;
}

void LatexGenerator::startInlineMemberName()
{
}

void LatexGenerator::endInlineMemberName()
{
  t << "&" << endl;
}

void LatexGenerator::startInlineMemberDoc()
{
}

void LatexGenerator::endInlineMemberDoc()
{
  t << "\\\\\n\\hline\n" << endl;
}

2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201
void LatexGenerator::startLabels()
{
  t << "\\hspace{0.3cm}";
}

void LatexGenerator::writeLabel(const char *l,bool isLast)
{
  t << "{\\ttfamily [" << l << "]}";
  if (!isLast) t << ", ";
}

void LatexGenerator::endLabels()
{
}