summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri van Heesch <dimitri@stack.nl>2015-01-01 20:04:54 (GMT)
committerDimitri van Heesch <dimitri@stack.nl>2015-08-27 13:45:02 (GMT)
commit02a0c353a8947290a3191aead59db08dc84766ce (patch)
treef367cb6bf3f91c2b92160144f37eed33decdc4a0
parent56987af3987f40ac77e70cd39ebbdac3702c1ce2 (diff)
downloadDoxygen-02a0c353a8947290a3191aead59db08dc84766ce.zip
Doxygen-02a0c353a8947290a3191aead59db08dc84766ce.tar.gz
Doxygen-02a0c353a8947290a3191aead59db08dc84766ce.tar.bz2
Started with generating LaTeX output via the template engine
-rw-r--r--src/classdef.cpp3
-rw-r--r--src/config.l5
-rw-r--r--src/context.cpp638
-rw-r--r--src/latexgen.cpp441
-rw-r--r--src/latexgen.h88
-rw-r--r--src/template.cpp241
-rw-r--r--src/template.h14
-rw-r--r--src/util.cpp90
-rw-r--r--src/util.h8
-rw-r--r--templates/html/htmlbase.tpl4
-rw-r--r--templates/html/htmltypeconstraints.tpl2
-rw-r--r--templates/latex/doxygen.sty6
-rw-r--r--templates/latex/latexannotated.tpl9
-rw-r--r--templates/latex/latexclass.tpl114
-rw-r--r--templates/latex/latexfiles.tpl0
-rw-r--r--templates/latex/latexinclude.tpl32
-rw-r--r--templates/latex/latexlayout.tpl35
-rw-r--r--templates/latex/latexmakefile.tpl64
-rw-r--r--templates/latex/latexmodules.tpl0
-rw-r--r--templates/latex/latexnamespaces.tpl0
-rw-r--r--templates/latex/latexobjlink.tpl6
-rw-r--r--templates/latex/latexrefman.tpl227
-rw-r--r--templates/latex/latextypeconstraints.tpl12
23 files changed, 1629 insertions, 410 deletions
diff --git a/src/classdef.cpp b/src/classdef.cpp
index 1584094..fa555ac 100644
--- a/src/classdef.cpp
+++ b/src/classdef.cpp
@@ -925,10 +925,7 @@ static void writeTemplateSpec(OutputList &ol,Definition *d,
if (a) ol.docify(", ");
}
ol.docify(">");
- ol.pushGeneratorState();
- ol.disableAllBut(OutputGenerator::Html);
ol.lineBreak();
- ol.popGeneratorState();
}
ol.docify(type.lower()+" "+name);
ol.endSubsubsection();
diff --git a/src/config.l b/src/config.l
index b158e5c..63a5b30 100644
--- a/src/config.l
+++ b/src/config.l
@@ -1119,14 +1119,15 @@ void Config::check()
QCString &paperType = Config_getEnum("PAPER_TYPE");
paperType=paperType.lower().stripWhiteSpace();
- if (paperType.isEmpty())
+ if (paperType.isEmpty() || paperType=="a4wide")
{
paperType = "a4";
}
- if (paperType!="a4" && paperType!="a4wide" && paperType!="letter" &&
+ if (paperType!="a4" && paperType!="letter" &&
paperType!="legal" && paperType!="executive")
{
config_err("Unknown page type specified\n");
+ paperType="a4";
}
QCString &outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
diff --git a/src/context.cpp b/src/context.cpp
index f7e6ae2..c4822e7 100644
--- a/src/context.cpp
+++ b/src/context.cpp
@@ -35,6 +35,8 @@
#include "docparser.h"
#include "htmlgen.h"
#include "htmldocvisitor.h"
+#include "latexgen.h"
+#include "latexdocvisitor.h"
#include "dot.h"
#include "diagram.h"
#include "example.h"
@@ -50,21 +52,23 @@
#define ADD_PROPERTY(name) addProperty(#name,this,&Private::name);
+enum ContextOutputFormat
+{
+ ContextOutputFormat_Unspecified=0,
+ ContextOutputFormat_Html,
+ ContextOutputFormat_Latex,
+ ContextOutputFormat_Rtf,
+ ContextOutputFormat_ManPage,
+ ContextOutputFormat_DocBook,
+ ContextOutputFormat_Xml,
+ ContextOutputFormat_TagFile
+};
+
struct ContextGlobals
{
- enum OutputFormat
- {
- Html,
- LateX,
- Rtf,
- ManPage,
- DocBook,
- Xml,
- TagFile
- };
- int dynSectionId;
- QCString outputDir;
- OutputFormat outputFormat;
+ int dynSectionId;
+ QCString outputDir;
+ ContextOutputFormat outputFormat;
} g_globals;
/** @brief Scoped smart pointer */
@@ -368,7 +372,7 @@ class DoxygenContext::Private : public PropertyMapper
}
TemplateVariant date() const
{
- return TemplateVariant(dateToString(TRUE));
+ return dateToString(TRUE);
}
TemplateVariant maxJaxCodeFile() const
{
@@ -380,7 +384,7 @@ class DoxygenContext::Private : public PropertyMapper
addProperty("version",this,&Private::version); //makeProperty(this,&Private::version));
//%% string date
addProperty("date", this,&Private::date);
- //%% string
+ //%% string maxJaxCodeFile
addProperty("mathJaxCodeFile", this,&Private::maxJaxCodeFile);
}
private:
@@ -593,6 +597,10 @@ class TranslateContext::Private : public PropertyMapper
{
return theTranslator->trCompoundIndex();
}
+ TemplateVariant namespaceIndex() const
+ {
+ return theTranslator->trNamespaceIndex();
+ }
TemplateVariant classHierarchy() const
{
return theTranslator->trClassHierarchy();
@@ -605,6 +613,10 @@ class TranslateContext::Private : public PropertyMapper
{
return theTranslator->trModules();
}
+ TemplateVariant moduleIndex() const
+ {
+ return theTranslator->trModuleIndex();
+ }
TemplateVariant namespaces() const
{
if (m_javaOpt || m_vhdlOpt)
@@ -624,6 +636,10 @@ class TranslateContext::Private : public PropertyMapper
{
return theTranslator->trFile(TRUE,FALSE);
}
+ TemplateVariant fileIndex() const
+ {
+ return theTranslator->trFileIndex();
+ }
TemplateVariant pages() const
{
return theTranslator->trRelatedPages();
@@ -662,6 +678,14 @@ class TranslateContext::Private : public PropertyMapper
return theTranslator->trNamespaceMembers();
}
}
+ TemplateVariant moduleDocumentation() const
+ {
+ return theTranslator->trModuleDocumentation();
+ }
+ TemplateVariant fileDocumentation() const
+ {
+ return theTranslator->trFileDocumentation();
+ }
TemplateVariant fileList() const
{
return theTranslator->trFileList();
@@ -829,6 +853,10 @@ class TranslateContext::Private : public PropertyMapper
{
return theTranslator->trClassDocumentation();
}
+ TemplateVariant namespaceDocumentation() const
+ {
+ return theTranslator->trNamespaceDocumentation();
+ }
TemplateVariant compoundMembers() const
{
return theTranslator->trCompoundMembers();
@@ -916,10 +944,18 @@ class TranslateContext::Private : public PropertyMapper
{
return theTranslator->trEnumValue();
}
+ TemplateVariant referenceManual() const
+ {
+ return theTranslator->trReferenceManual();
+ }
+ TemplateVariant index() const
+ {
+ return theTranslator->trRTFGeneralIndex();
+ }
Private()
{
//%% string generatedBy
- addProperty("generatedby", this,&Private::generatedBy);
+ addProperty("generatedBy", this,&Private::generatedBy);
//%% string generatedAt
addProperty("generatedAt", this,&Private::generatedAt);
//%% string search
@@ -934,6 +970,8 @@ class TranslateContext::Private : public PropertyMapper
addProperty("classListDescription", this,&Private::classListDescription);
//%% string classIndex
addProperty("classIndex", this,&Private::classIndex);
+ //%% string namespaceIndex
+ addProperty("namespaceIndex", this,&Private::namespaceIndex);
//%% string classHierarchy
addProperty("classHierarchy", this,&Private::classHierarchy);
//%% string classMembers
@@ -942,8 +980,12 @@ class TranslateContext::Private : public PropertyMapper
addProperty("classMembersDescription",this,&Private::classMembersDescription);
//%% string modules
addProperty("modules", this,&Private::modules);
+ //%% string moduleIndex
+ addProperty("moduleIndex", this,&Private::moduleIndex);
//%% string namespaces
addProperty("namespaces", this,&Private::namespaces);
+ //%% string fileIndex
+ addProperty("fileIndex", this,&Private::fileIndex);
//%% string files
addProperty("files", this,&Private::files);
//%% string pages
@@ -1024,6 +1066,12 @@ class TranslateContext::Private : public PropertyMapper
addProperty("constantgroups", this,&Private::constantgroups);
//%% string classDocumentation
addProperty("classDocumentation", this,&Private::classDocumentation);
+ //%% string namespaceDocumentation
+ addProperty("namespaceDocumentation", this,&Private::namespaceDocumentation);
+ //%% string moduleDocumentation
+ addProperty("moduleDocumentation",this,&Private::moduleDocumentation);
+ //%% string fileDocumentation
+ addProperty("fileDocumentation", this,&Private::fileDocumentation);
//%% string compoundMembers
addProperty("compoundMembers", this,&Private::compoundMembers);
//%% string detailLevel
@@ -1034,7 +1082,7 @@ class TranslateContext::Private : public PropertyMapper
addProperty("namespaceListDescription",this,&Private::namespaceListDescription);
//%% string directories
addProperty("directories", this,&Private::directories);
- //%% string moduleDescript
+ //%% string moduleDescription
addProperty("modulesDescription", this,&Private::modulesDescription);
//%% string all
addProperty("all", this,&Private::all);
@@ -1074,6 +1122,10 @@ class TranslateContext::Private : public PropertyMapper
addProperty("enumValue", this,&Private::enumValue);
//%% string enumName
addProperty("enumName", this,&Private::enumName);
+ //%% string referenceManual
+ addProperty("referenceManual", this,&Private::referenceManual);
+ //%% string index
+ addProperty("index", this,&Private::index);
m_javaOpt = Config_getBool("OPTIMIZE_OUTPUT_JAVA");
m_fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
@@ -1109,10 +1161,27 @@ static TemplateVariant parseDoc(Definition *def,const QCString &file,int line,
QGString docs;
{
FTextStream ts(&docs);
- // TODO: support other generators
- HtmlCodeGenerator codeGen(ts,relPath);
- HtmlDocVisitor visitor(ts,codeGen,def);
- root->accept(&visitor);
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ HtmlCodeGenerator codeGen(ts,relPath);
+ HtmlDocVisitor visitor(ts,codeGen,def);
+ root->accept(&visitor);
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ LatexCodeGenerator codeGen(ts,relPath,file);
+ LatexDocVisitor visitor(ts,codeGen,def->getDefFileExtension(),FALSE);
+ root->accept(&visitor);
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
}
bool isEmpty = root->isEmpty();
if (isEmpty)
@@ -1130,9 +1199,27 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q
pIntf->resetCodeParserState();
QGString s;
FTextStream t(&s);
- HtmlCodeGenerator codeGen(t,relPath);
- pIntf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(),
- startLine,endLine,TRUE,md,showLineNumbers,md);
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ HtmlCodeGenerator codeGen(t,relPath);
+ pIntf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(),
+ startLine,endLine,TRUE,md,showLineNumbers,md);
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ LatexCodeGenerator codeGen(t,relPath,md->docFile());
+ pIntf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(),
+ startLine,endLine,TRUE,md,showLineNumbers,md);
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
return TemplateVariant(s.data(),TRUE);
}
@@ -1143,21 +1230,51 @@ static TemplateVariant parseCode(FileDef *fd,const QCString &relPath)
pIntf->resetCodeParserState();
QGString s;
FTextStream t(&s);
- HtmlCodeGenerator codeGen(t,relPath);
- pIntf->parseCode(codeGen,0,
- fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
- fd->getLanguage(), // lang
- FALSE, // isExampleBlock
- 0, // exampleName
- fd, // fileDef
- -1, // startLine
- -1, // endLine
- FALSE, // inlineFragment
- 0, // memberDef
- TRUE, // showLineNumbers
- 0, // searchCtx
- TRUE // collectXRefs, TODO: should become FALSE
- );
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ HtmlCodeGenerator codeGen(t,relPath);
+ pIntf->parseCode(codeGen,0,
+ fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
+ fd->getLanguage(), // lang
+ FALSE, // isExampleBlock
+ 0, // exampleName
+ fd, // fileDef
+ -1, // startLine
+ -1, // endLine
+ FALSE, // inlineFragment
+ 0, // memberDef
+ TRUE, // showLineNumbers
+ 0, // searchCtx
+ TRUE // collectXRefs, TODO: should become FALSE
+ );
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ LatexCodeGenerator codeGen(t,relPath,fd->docFile());
+ pIntf->parseCode(codeGen,0,
+ fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources
+ fd->getLanguage(), // lang
+ FALSE, // isExampleBlock
+ 0, // exampleName
+ fd, // fileDef
+ -1, // startLine
+ -1, // endLine
+ FALSE, // inlineFragment
+ 0, // memberDef
+ TRUE, // showLineNumbers
+ 0, // searchCtx
+ TRUE // collectXRefs, TODO: should become FALSE
+ );
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
return TemplateVariant(s.data(),TRUE);
}
@@ -1271,21 +1388,23 @@ class DefinitionContext : public PropertyMapper
}
TemplateVariant details() const
{
- if (!m_cache.details)
+ if (!m_cache.details || g_globals.outputFormat!=m_cache.detailsOutputFormat)
{
m_cache.details.reset(new TemplateVariant(parseDoc(m_def,m_def->docFile(),m_def->docLine(),
relPathAsString(),m_def->documentation(),FALSE)));
+ m_cache.detailsOutputFormat = g_globals.outputFormat;
}
return *m_cache.details;
}
TemplateVariant brief() const
{
- if (!m_cache.brief)
+ if (!m_cache.brief || g_globals.outputFormat!=m_cache.briefOutputFormat)
{
if (m_def->hasBriefDescription())
{
m_cache.brief.reset(new TemplateVariant(parseDoc(m_def,m_def->briefFile(),m_def->briefLine(),
relPathAsString(),m_def->briefDescription(),TRUE)));
+ m_cache.briefOutputFormat = g_globals.outputFormat;
}
else
{
@@ -1296,12 +1415,13 @@ class DefinitionContext : public PropertyMapper
}
TemplateVariant inbodyDocs() const
{
- if (!m_cache.inbodyDocs)
+ if (!m_cache.inbodyDocs || g_globals.outputFormat!=m_cache.inbodyDocsOutputFormat)
{
if (!m_def->inbodyDocumentation().isEmpty())
{
m_cache.inbodyDocs.reset(new TemplateVariant(parseDoc(m_def,m_def->inbodyFile(),m_def->inbodyLine(),
relPathAsString(),m_def->inbodyDocumentation(),FALSE)));
+ m_cache.inbodyDocsOutputFormat = g_globals.outputFormat;
}
else
{
@@ -1387,8 +1507,11 @@ class DefinitionContext : public PropertyMapper
{
Cachable() { }
ScopedPtr<TemplateVariant> details;
+ ContextOutputFormat detailsOutputFormat;
ScopedPtr<TemplateVariant> brief;
+ ContextOutputFormat briefOutputFormat;
ScopedPtr<TemplateVariant> inbodyDocs;
+ ContextOutputFormat inbodyDocsOutputFormat;
SharedPtr<TemplateList> navPath;
SharedPtr<TemplateList> sourceDef;
SharedPtr<TemplateStruct> fileLink;
@@ -1659,26 +1782,62 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{
DotClassGraph *cg = getClassGraph();
FTextStream t(&result);
- cg->writeGraph(t,GOF_BITMAP,EOF_Html,
- g_globals.outputDir,
- g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
- relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
- );
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+ relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+".tex",
+ relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
}
else if (classDiagrams)
{
ClassDiagram d(m_classDef);
FTextStream t(&result);
- QCString name = convertToHtml(m_classDef->displayName());
- t << "<div class=\"center\">" << endl;
- t << "<img src=\"";
- t << relPathAsString() << m_classDef->getOutputFileBase();
- t << ".png\" usemap=\"#" << name << "_map\" alt=\"\"/>" << endl;
- t << "<map id=\"" << name << "_map\" name=\"" << name << "_map\">" << endl;
- d.writeImage(t,g_globals.outputDir,
- relPathAsString(),
- m_classDef->getOutputFileBase());
- t << "</div>";
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ QCString name = convertToHtml(m_classDef->displayName());
+ t << "<div class=\"center\">" << endl;
+ t << "<img src=\"";
+ t << relPathAsString() << m_classDef->getOutputFileBase();
+ t << ".png\" usemap=\"#" << name << "_map\" alt=\"\"/>" << endl;
+ t << "<map id=\"" << name << "_map\" name=\"" << name << "_map\">" << endl;
+ d.writeImage(t,g_globals.outputDir,
+ relPathAsString(),
+ m_classDef->getOutputFileBase());
+ t << "</div>";
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ d.writeFigure(t,g_globals.outputDir,m_classDef->getOutputFileBase());
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
}
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
@@ -1704,11 +1863,31 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
{
DotClassGraph *cg = getCollaborationGraph();
FTextStream t(&result);
- cg->writeGraph(t,GOF_BITMAP,EOF_Html,
- g_globals.outputDir,
- g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
- relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
- );
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+ relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_classDef->getOutputFileBase()+".tex",
+ relPathAsString(),TRUE,TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
}
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
@@ -2002,15 +2181,15 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private>
}
TemplateVariant typeConstraints() const
{
- if (!m_cache.typeConstraints && m_classDef->typeConstraints())
+ if (m_classDef->typeConstraints())
{
- m_cache.typeConstraints.reset(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString()));
- }
- else
- {
- m_cache.typeConstraints.reset(ArgumentListContext::alloc());
+ if (!m_cache.typeConstraints && m_classDef->typeConstraints())
+ {
+ m_cache.typeConstraints.reset(ArgumentListContext::alloc(m_classDef->typeConstraints(),m_classDef,relPathAsString()));
+ }
+ return m_cache.typeConstraints.get();
}
- return m_cache.typeConstraints.get();
+ return FALSE;
}
TemplateVariant examples() const
{
@@ -2578,11 +2757,31 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
{
DotInclDepGraph *cg = getIncludeGraph();
FTextStream t(&result);
- cg->writeGraph(t,GOF_BITMAP,EOF_Html,
- g_globals.outputDir,
- g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
- relPathAsString(),TRUE,g_globals.dynSectionId
- );
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+".tex",
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
}
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
@@ -2609,11 +2808,31 @@ class FileContext::Private : public DefinitionContext<FileContext::Private>
{
DotInclDepGraph *cg = getIncludedByGraph();
FTextStream t(&result);
- cg->writeGraph(t,GOF_BITMAP,EOF_Html,
- g_globals.outputDir,
- g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
- relPathAsString(),TRUE,g_globals.dynSectionId
- );
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_fileDef->getOutputFileBase()+".tex",
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
}
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
@@ -3063,7 +3282,6 @@ class TextGeneratorHtml : public TextGeneratorIntf
void writeString(const char *s,bool keepSpaces) const
{
if (s==0) return;
- //printf("TextGeneratorOlImpl::writeString('%s',%d)\n",s,keepSpaces);
if (keepSpaces)
{
const char *p=s;
@@ -3123,6 +3341,54 @@ class TextGeneratorHtml : public TextGeneratorIntf
QCString m_relPath;
};
+//------------------------------------------------------------------------
+
+class TextGeneratorLatex : public TextGeneratorIntf
+{
+ public:
+ TextGeneratorLatex(FTextStream &ts) : m_ts(ts) {}
+ void writeString(const char *s,bool keepSpaces) const
+ {
+ if (s==0) return;
+ m_ts << convertToLaTeX(s,FALSE,keepSpaces);
+ }
+ void writeBreak(int indent) const
+ {
+ m_ts << "\\\\*\n";
+ for (int i=0;i<indent;i++)
+ {
+ m_ts << "~";
+ }
+ }
+ void writeLink(const char *ref,const char *f,
+ const char *anchor,const char *text
+ ) const
+ {
+ static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
+ if (!ref && pdfHyperlinks)
+ {
+ m_ts << "\\hyperlink{";
+ if (f) m_ts << stripPath(f);
+ if (f && anchor) m_ts << "_";
+ if (anchor) m_ts << anchor;
+ m_ts << "}{";
+ filterLatexString(m_ts,text);
+ m_ts << "}";
+ }
+ else
+ {
+ m_ts << "{\\bf ";
+ filterLatexString(m_ts,text);
+ m_ts << "}";
+ }
+ }
+
+ private:
+ FTextStream &m_ts;
+};
+
+//------------------------------------------------------------------------
+
class TextGeneratorFactory
{
public:
@@ -3136,9 +3402,10 @@ class TextGeneratorFactory
{
switch (g_globals.outputFormat)
{
- case ContextGlobals::Html:
+ case ContextOutputFormat_Html:
return new TextGeneratorHtml(ts,relPath);
- break;
+ case ContextOutputFormat_Latex:
+ return new TextGeneratorLatex(ts);
default:
break;
}
@@ -4132,11 +4399,31 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
DotCallGraph *cg = getCallGraph();
QGString result;
FTextStream t(&result);
- cg->writeGraph(t,GOF_BITMAP,EOF_Html,
- g_globals.outputDir,
- g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
- relPathAsString(),TRUE,g_globals.dynSectionId
- );
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
}
@@ -4171,11 +4458,31 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private>
DotCallGraph *cg = getCallerGraph();
QGString result;
FTextStream t(&result);
- cg->writeGraph(t,GOF_BITMAP,EOF_Html,
- g_globals.outputDir,
- g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
- relPathAsString(),TRUE,g_globals.dynSectionId
- );
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ cg->writeGraph(t,GOF_BITMAP,EOF_Html,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ cg->writeGraph(t,GOF_EPS,EOF_LaTeX,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_memberDef->getOutputFileBase()+".tex",
+ relPathAsString(),TRUE,g_globals.dynSectionId
+ );
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
}
@@ -4339,13 +4646,35 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private>
{
DotGroupCollaboration *graph = getGroupGraph();
FTextStream t(&result);
- graph->writeGraph(t,GOF_BITMAP,
- EOF_Html,
- g_globals.outputDir,
- g_globals.outputDir+portable_pathSeparator()+m_groupDef->getOutputFileBase()+Doxygen::htmlFileExtension,
- relPathAsString(),
- TRUE,
- g_globals.dynSectionId);
+ switch (g_globals.outputFormat)
+ {
+ case ContextOutputFormat_Html:
+ {
+ graph->writeGraph(t,GOF_BITMAP,
+ EOF_Html,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_groupDef->getOutputFileBase()+Doxygen::htmlFileExtension,
+ relPathAsString(),
+ TRUE,
+ g_globals.dynSectionId);
+ }
+ break;
+ case ContextOutputFormat_Latex:
+ {
+ graph->writeGraph(t,GOF_EPS,
+ EOF_LaTeX,
+ g_globals.outputDir,
+ g_globals.outputDir+portable_pathSeparator()+m_groupDef->getOutputFileBase()+".tex",
+ relPathAsString(),
+ TRUE,
+ g_globals.dynSectionId);
+ }
+ break;
+ // TODO: support other generators
+ default:
+ err("context.cpp: output format not yet supported");
+ break;
+ }
}
g_globals.dynSectionId++;
return TemplateVariant(result.data(),TRUE);
@@ -8619,6 +8948,36 @@ class HtmlEscaper : public TemplateEscapeIntf
{
return convertToHtml(s,TRUE);
}
+ void enableTabbing(bool) {}
+};
+
+//------------------------------------------------------------------------
+
+class LatexSpaceless : public TemplateSpacelessIntf
+{
+ public:
+ LatexSpaceless() { reset(); }
+ void reset() { }
+ QCString remove(const QCString &s)
+ {
+ QGString result;
+ const char *p = s.data();
+ char c;
+ while ((c=*p++))
+ {
+ switch(c)
+ {
+ case '\t': case ' ': case '\n':
+ break;
+ default:
+ result+=c;
+ break;
+ }
+ }
+ result+='\0';
+ return result.data();
+ }
+ private:
};
//------------------------------------------------------------------------
@@ -8698,6 +9057,22 @@ class HtmlSpaceless : public TemplateSpacelessIntf
//------------------------------------------------------------------------
+class LatexEscaper : public TemplateEscapeIntf
+{
+ public:
+ LatexEscaper() : m_tabbing(FALSE) {}
+ QCString escape(const QCString &s)
+ {
+ return convertToLaTeX(s,m_tabbing);
+ }
+ void enableTabbing(bool b) { m_tabbing=b; }
+ private:
+ bool m_tabbing;
+};
+
+
+//------------------------------------------------------------------------
+
#if DEBUG_REF
int RefCountedContext::s_totalCount;
#endif
@@ -8787,27 +9162,52 @@ void generateOutputViaTemplate()
ctx->set("namespaceMembersIndex",namespaceMembersIndex.get());
//%% SearchIndicaes searchindicaes
ctx->set("searchIndices",searchIndices.get());
+ //%% string space
+ ctx->set("space"," ");
+
+ if (Config_getBool("GENERATE_HTML"))
+ { // render HTML output
+ Template *tpl = e.loadByName("htmllayout.tpl",1);
+ if (tpl)
+ {
+ g_globals.outputFormat = ContextOutputFormat_Html;
+ g_globals.dynSectionId = 0;
+ g_globals.outputDir = Config_getString("HTML_OUTPUT");
+ QDir dir(g_globals.outputDir);
+ createSubDirs(dir);
+ HtmlEscaper htmlEsc;
+ ctx->setEscapeIntf(Config_getString("HTML_FILE_EXTENSION"),&htmlEsc);
+ HtmlSpaceless spl;
+ ctx->setSpacelessIntf(&spl);
+ ctx->setOutputDirectory(g_globals.outputDir);
+ FTextStream ts;
+ tpl->render(ts,ctx);
+ e.unload(tpl);
+ }
+ }
+
+ // TODO: clean index before each run...
- // render HTML output
- Template *tpl = e.loadByName("htmllayout.tpl",1);
- if (tpl)
- {
- g_globals.outputFormat = ContextGlobals::Html;
- g_globals.dynSectionId = 0;
- g_globals.outputDir = Config_getString("HTML_OUTPUT");
- QDir dir(g_globals.outputDir);
- createSubDirs(dir);
- HtmlEscaper htmlEsc;
- ctx->setEscapeIntf(Config_getString("HTML_FILE_EXTENSION"),&htmlEsc);
- HtmlSpaceless spl;
- ctx->setSpacelessIntf(&spl);
- ctx->setOutputDirectory(g_globals.outputDir);
- FTextStream ts;
- tpl->render(ts,ctx);
- e.unload(tpl);
- }
-
- // TODO: render other outputs
+ if (Config_getBool("GENERATE_LATEX"))
+ { // render LaTeX output
+ Template *tpl = e.loadByName("latexlayout.tpl",1);
+ if (tpl)
+ {
+ g_globals.outputFormat = ContextOutputFormat_Latex;
+ g_globals.dynSectionId = 0;
+ g_globals.outputDir = Config_getString("LATEX_OUTPUT");
+ QDir dir(g_globals.outputDir);
+ createSubDirs(dir);
+ LatexEscaper latexEsc;
+ ctx->setEscapeIntf(".tex",&latexEsc);
+ LatexSpaceless spl;
+ ctx->setSpacelessIntf(&spl);
+ ctx->setOutputDirectory(g_globals.outputDir);
+ FTextStream ts;
+ tpl->render(ts,ctx);
+ e.unload(tpl);
+ }
+ }
e.destroyContext(ctx);
}
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
index 2ed30e9..c524d2e 100644
--- a/src/latexgen.cpp
+++ b/src/latexgen.cpp
@@ -38,11 +38,214 @@
#include "filename.h"
#include "resourcemgr.h"
+//-------------------------------
+
+LatexCodeGenerator::LatexCodeGenerator(FTextStream &t,const QCString &relPath,const QCString &sourceFileName)
+ : m_relPath(relPath), m_sourceFileName(sourceFileName), m_col(0)
+{
+ m_prettyCode=Config_getBool("LATEX_SOURCE_CODE");
+ setTextStream(t);
+}
+
+LatexCodeGenerator::LatexCodeGenerator() : m_col(0)
+{
+ m_prettyCode=Config_getBool("LATEX_SOURCE_CODE");
+}
+
+void LatexCodeGenerator::setTextStream(FTextStream &t)
+{
+ m_streamSet = t.device()!=0;
+ m_t.setDevice(t.device());
+}
+
+void LatexCodeGenerator::setRelativePath(const QCString &path)
+{
+ m_relPath = path;
+}
+
+void LatexCodeGenerator::setSourceFileName(const QCString &name)
+{
+ m_sourceFileName = name;
+}
+
+void LatexCodeGenerator::codify(const char *str)
+{
+ if (str)
+ {
+ const char *p=str;
+ char c;
+ //char cs[5];
+ int spacesToNextTabStop;
+ static int tabSize = Config_getInt("TAB_SIZE");
+ const int maxLineLen = 108;
+ QCString result(4*maxLineLen+1); // worst case for 1 line of 4-byte chars
+ int i;
+ while ((c=*p))
+ {
+ switch(c)
+ {
+ case 0x0c: p++; // remove ^L
+ break;
+ case '\t': spacesToNextTabStop =
+ tabSize - (m_col%tabSize);
+ m_t << Doxygen::spaces.left(spacesToNextTabStop);
+ m_col+=spacesToNextTabStop;
+ p++;
+ break;
+ case '\n': m_t << '\n'; m_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++; \
+ } \
+ } \
+ m_col++; \
+ } while(0)
+
+ // gather characters until we find whitespace or are at
+ // the end of a line
+ COPYCHAR();
+ if (m_col>=maxLineLen) // force line break
+ {
+ m_t << "\n ";
+ m_col=0;
+ }
+ else // copy more characters
+ {
+ while (m_col<maxLineLen && (c=*p) &&
+ c!=0x0c && c!='\t' && c!='\n' && c!=' '
+ )
+ {
+ COPYCHAR();
+ }
+ if (m_col>=maxLineLen) // force line break
+ {
+ m_t << "\n ";
+ m_col=0;
+ }
+ }
+ result[i]=0; // add terminator
+ //if (m_prettyCode)
+ //{
+ filterLatexString(m_t,result,FALSE,TRUE);
+ //}
+ //else
+ //{
+ // t << result;
+ //}
+ break;
+ }
+ }
+ }
+}
+
+
+void LatexCodeGenerator::writeCodeLink(const char *ref,const char *f,
+ const char *anchor,const char *name,
+ const char *)
+{
+ static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
+ static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
+ int l = qstrlen(name);
+ if (m_col+l>80)
+ {
+ m_t << "\n ";
+ m_col=0;
+ }
+ if (!ref && usePDFLatex && pdfHyperlinks)
+ {
+ m_t << "\\hyperlink{";
+ if (f) m_t << stripPath(f);
+ if (f && anchor) m_t << "_";
+ if (anchor) m_t << anchor;
+ m_t << "}{";
+ codify(name);
+ m_t << "}";
+ }
+ else
+ {
+ m_t << name;
+ }
+ m_col+=l;
+}
+
+void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,const char *anchor,int l)
+{
+ static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
+ static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
+ if (m_prettyCode)
+ {
+ QCString lineNumber;
+ lineNumber.sprintf("%05d",l);
+
+ if (fileName && !m_sourceFileName.isEmpty())
+ {
+ QCString lineAnchor;
+ lineAnchor.sprintf("_l%05d",l);
+ lineAnchor.prepend(m_sourceFileName);
+ //if (!m_prettyCode) return;
+ if (usePDFLatex && pdfHyperlinks)
+ {
+ m_t << "\\hypertarget{" << stripPath(lineAnchor) << "}{}";
+ }
+ writeCodeLink(ref,fileName,anchor,lineNumber,0);
+ }
+ else
+ {
+ codify(lineNumber);
+ }
+ m_t << " ";
+ }
+ else
+ {
+ m_t << l << " ";
+ }
+}
+
+
+void LatexCodeGenerator::startCodeLine(bool)
+{
+ m_col=0;
+}
+
+void LatexCodeGenerator::endCodeLine()
+{
+ codify("\n");
+}
+
+void LatexCodeGenerator::startFontClass(const char *name)
+{
+ m_t << "\\textcolor{" << name << "}{";
+}
+
+void LatexCodeGenerator::endFontClass()
+{
+ m_t << "}";
+}
+
+
+//-------------------------------
LatexGenerator::LatexGenerator() : OutputGenerator()
{
dir=Config_getString("LATEX_OUTPUT");
- col=0;
//printf("LatexGenerator::LatexGenerator() insideTabbing=FALSE\n");
insideTabbing=FALSE;
firstDescItem=TRUE;
@@ -332,13 +535,8 @@ static void writeDefaultHeaderPart1(FTextStream &t)
"\n";
// Define page & text layout
- QCString paperName;
- QCString &paperType=Config_getEnum("PAPER_TYPE");
+ QCString paperName=Config_getEnum("PAPER_TYPE");
// "a4wide" package is obsolete (see bug 563698)
- if (paperType=="a4wide")
- paperName="a4";
- else
- paperName=paperType;
t << "% Page & text layout\n"
"\\usepackage{geometry}\n"
"\\geometry{%\n"
@@ -593,7 +791,7 @@ void LatexGenerator::startFile(const char *name,const char *,const char *)
#endif
QCString fileName=name;
relPath = relativePathToRoot(fileName);
- sourceFileName = stripPath(fileName);
+ m_codeGen.setSourceFileName(stripPath(fileName));
if (fileName.right(4)!=".tex" && fileName.right(4)!=".sty") fileName+=".tex";
startPlainFile(fileName);
}
@@ -601,7 +799,7 @@ void LatexGenerator::startFile(const char *name,const char *,const char *)
void LatexGenerator::endFile()
{
endPlainFile();
- sourceFileName.resize(0);
+ m_codeGen.setSourceFileName("");
}
//void LatexGenerator::writeIndex()
@@ -614,14 +812,6 @@ void LatexGenerator::startProjectNumber()
t << "\\\\[1ex]\\large ";
}
-static QCString convertToLaTeX(const QCString &s)
-{
- QGString result;
- FTextStream t(&result);
- filterLatexString(t,s,FALSE,FALSE,FALSE);
- return result.data();
-}
-
void LatexGenerator::startIndexSection(IndexSections is)
{
bool &compactLatex = Config_getBool("COMPACT_LATEX");
@@ -1204,7 +1394,8 @@ void LatexGenerator::endTextLink()
void LatexGenerator::writeObjectLink(const char *ref, const char *f,
const char *anchor, const char *text)
{
- if (!disableLinks && !ref && Config_getBool("PDF_HYPERLINKS"))
+ static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
+ if (!disableLinks && !ref && pdfHyperlinks)
{
t << "\\hyperlink{";
if (f) t << stripPath(f);
@@ -1235,34 +1426,6 @@ void LatexGenerator::endPageRef(const char *clname, const char *anchor)
t << "}";
}
-void LatexGenerator::writeCodeLink(const char *ref,const char *f,
- const char *anchor,const char *name,
- const char *)
-{
- static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
- static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
- int l = qstrlen(name);
- if (col+l>80)
- {
- t << "\n ";
- col=0;
- }
- if (/*m_prettyCode &&*/ !disableLinks && !ref && usePDFLatex && pdfHyperlinks)
- {
- t << "\\hyperlink{";
- if (f) t << stripPath(f);
- if (f && anchor) t << "_";
- if (anchor) t << anchor;
- t << "}{";
- codify(name);
- t << "}";
- }
- else
- {
- t << name;
- }
- col+=l;
-}
void LatexGenerator::startTitleHead(const char *fileName)
{
@@ -1288,9 +1451,9 @@ void LatexGenerator::endTitleHead(const char *fileName,const char *name)
if (name)
{
t << "\\label{" << stripPath(fileName) << "}\\index{";
- escapeLabelName(name);
+ t << latexEscapeLabelName(name,insideTabbing);
t << "@{";
- escapeMakeIndexChars(name);
+ t << latexEscapeIndexChars(name,insideTabbing);
t << "}}" << endl;
}
}
@@ -1369,27 +1532,27 @@ void LatexGenerator::startMemberDoc(const char *clname,
t << "\\index{";
if (clname)
{
- escapeLabelName(clname);
+ t << latexEscapeLabelName(clname,insideTabbing);
t << "@{";
- escapeMakeIndexChars(clname);
+ t << latexEscapeIndexChars(clname,insideTabbing);
t << "}!";
}
- escapeLabelName(memname);
+ t << latexEscapeLabelName(memname,insideTabbing);
t << "@{";
- escapeMakeIndexChars(memname);
+ t << latexEscapeIndexChars(memname,insideTabbing);
t << "}}" << endl;
t << "\\index{";
- escapeLabelName(memname);
+ t << latexEscapeLabelName(memname,insideTabbing);
t << "@{";
- escapeMakeIndexChars(memname);
+ t << latexEscapeIndexChars(memname,insideTabbing);
t << "}";
if (clname)
{
t << "!";
- escapeLabelName(clname);
+ t << latexEscapeLabelName(clname,insideTabbing);
t << "@{";
- escapeMakeIndexChars(clname);
+ t << latexEscapeIndexChars(clname,insideTabbing);
t << "}";
}
t << "}" << endl;
@@ -1401,21 +1564,15 @@ void LatexGenerator::startMemberDoc(const char *clname,
if (compactLatex) level++;
t << "\\" << levelLab[level];
- //if (Config_getBool("PDF_HYPERLINKS") && memname)
- //{
- // t << "[";
- // escapeMakeIndexChars(this,t,memname);
- // t << "]";
- //}
t << "[{";
- escapeMakeIndexChars(title);
+ t << latexEscapeIndexChars(title,insideTabbing);
t << "}]";
t << "{\\setlength{\\rightskip}{0pt plus 5cm}";
disableLinks=TRUE;
}
-void LatexGenerator::endMemberDoc(bool)
-{
+void LatexGenerator::endMemberDoc(bool)
+{
disableLinks=FALSE;
t << "}";
//if (Config_getBool("COMPACT_LATEX")) t << "\\hfill";
@@ -1474,16 +1631,16 @@ void LatexGenerator::addIndexItem(const char *s1,const char *s2)
if (s1)
{
t << "\\index{";
- escapeLabelName(s1);
+ t << latexEscapeLabelName(s1,insideTabbing);
t << "@{";
- escapeMakeIndexChars(s1);
+ t << latexEscapeIndexChars(s1,insideTabbing);
t << "}";
if (s2)
{
t << "!";
- escapeLabelName(s2);
+ t << latexEscapeLabelName(s2,insideTabbing);
t << "@{";
- escapeMakeIndexChars(s2);
+ t << latexEscapeIndexChars(s2,insideTabbing);
t << "}";
}
t << "}";
@@ -1539,94 +1696,6 @@ void LatexGenerator::docify(const char *str)
filterLatexString(t,str,insideTabbing,FALSE,FALSE);
}
-void LatexGenerator::codify(const char *str)
-{
- if (str)
- {
- const char *p=str;
- char c;
- //char cs[5];
- int spacesToNextTabStop;
- static int tabSize = Config_getInt("TAB_SIZE");
- const int maxLineLen = 108;
- QCString result(4*maxLineLen+1); // worst case for 1 line of 4-byte chars
- int i;
- while ((c=*p))
- {
- switch(c)
- {
- case 0x0c: p++; // remove ^L
- break;
- case '\t': spacesToNextTabStop =
- tabSize - (col%tabSize);
- t << Doxygen::spaces.left(spacesToNextTabStop);
- col+=spacesToNextTabStop;
- p++;
- break;
- 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
- {
- while (col<maxLineLen && (c=*p) &&
- c!=0x0c && c!='\t' && c!='\n' && c!=' '
- )
- {
- COPYCHAR();
- }
- if (col>=maxLineLen) // force line break
- {
- t << "\n ";
- col=0;
- }
- }
- result[i]=0; // add terminator
- //if (m_prettyCode)
- //{
- filterLatexString(t,result,insideTabbing,TRUE);
- //}
- //else
- //{
- // t << result;
- //}
- break;
- }
- }
- }
-}
-
void LatexGenerator::writeChar(char c)
{
char cs[2];
@@ -2009,6 +2078,7 @@ void LatexGenerator::endConstraintList()
t << "\\end{Desc}" << endl;
}
+#if 0
void LatexGenerator::escapeLabelName(const char *s)
{
if (s==0) return;
@@ -2078,6 +2148,7 @@ void LatexGenerator::escapeMakeIndexChars(const char *s)
}
}
}
+#endif
void LatexGenerator::startCodeFragment()
{
@@ -2089,61 +2160,6 @@ void LatexGenerator::endCodeFragment()
t << "\\end{DoxyCode}\n";
}
-void LatexGenerator::writeLineNumber(const char *ref,const char *fileName,const char *anchor,int l)
-{
- static bool usePDFLatex = Config_getBool("USE_PDFLATEX");
- static bool pdfHyperlinks = Config_getBool("PDF_HYPERLINKS");
- if (m_prettyCode)
- {
- QCString lineNumber;
- lineNumber.sprintf("%05d",l);
-
- if (fileName && !sourceFileName.isEmpty())
- {
- QCString lineAnchor;
- lineAnchor.sprintf("_l%05d",l);
- lineAnchor.prepend(sourceFileName);
- //if (!m_prettyCode) return;
- if (usePDFLatex && pdfHyperlinks)
- {
- t << "\\hypertarget{" << stripPath(lineAnchor) << "}{}";
- }
- writeCodeLink(ref,fileName,anchor,lineNumber,0);
- }
- else
- {
- codify(lineNumber);
- }
- t << " ";
- }
- else
- {
- t << l << " ";
- }
-}
-
-void LatexGenerator::startCodeLine(bool)
-{
- col=0;
-}
-
-void LatexGenerator::endCodeLine()
-{
- codify("\n");
-}
-
-void LatexGenerator::startFontClass(const char *name)
-{
- //if (!m_prettyCode) return;
- t << "\\textcolor{" << name << "}{";
-}
-
-void LatexGenerator::endFontClass()
-{
- //if (!m_prettyCode) return;
- t << "}";
-}
-
void LatexGenerator::startInlineHeader()
{
if (Config_getBool("COMPACT_LATEX"))
@@ -2227,3 +2243,4 @@ void LatexGenerator::endLabels()
{
}
+
diff --git a/src/latexgen.h b/src/latexgen.h
index ee67803..84382a7 100644
--- a/src/latexgen.h
+++ b/src/latexgen.h
@@ -24,6 +24,48 @@ class QFile;
static const char *latexStyleExtension = ".sty";
+class LatexCodeGenerator : public CodeOutputInterface
+{
+ public:
+ LatexCodeGenerator(FTextStream &t,const QCString &relPath,const QCString &sourceFile);
+ LatexCodeGenerator();
+ void setTextStream(FTextStream &t);
+ void setRelativePath(const QCString &path);
+ void setSourceFileName(const QCString &sourceFileName);
+ void codify(const char *text);
+ void writeCodeLink(const char *ref,const char *file,
+ const char *anchor,const char *name,
+ const char *tooltip);
+ void writeTooltip(const char *,
+ const DocLinkInfo &,
+ const char *,
+ const char *,
+ const SourceLinkInfo &,
+ const SourceLinkInfo &
+ ) {}
+ void writeLineNumber(const char *,const char *,const char *,int);
+ void startCodeLine(bool);
+ void endCodeLine();
+ void startFontClass(const char *);
+ void endFontClass();
+ void writeCodeAnchor(const char *) {}
+ void setCurrentDoc(Definition *,const char *,bool) {}
+ void addWord(const char *,bool) {}
+
+ private:
+ void _writeCodeLink(const char *className,
+ const char *ref,const char *file,
+ const char *anchor,const char *name,
+ const char *tooltip);
+ void docify(const char *str);
+ bool m_streamSet;
+ FTextStream m_t;
+ QCString m_relPath;
+ QCString m_sourceFileName;
+ int m_col;
+ bool m_prettyCode;
+};
+
/** Generator for LaTeX output. */
class LatexGenerator : public OutputGenerator
{
@@ -47,6 +89,32 @@ class LatexGenerator : public OutputGenerator
bool isEnabled(OutputType o) { return (o==Latex && active); }
OutputGenerator *get(OutputType o) { return (o==Latex) ? this : 0; }
+ // --- CodeOutputInterface
+ void codify(const char *text)
+ { m_codeGen.codify(text); }
+ void writeCodeLink(const char *ref, const char *file,
+ const char *anchor,const char *name,
+ const char *tooltip)
+ { m_codeGen.writeCodeLink(ref,file,anchor,name,tooltip); }
+ void writeLineNumber(const char *ref,const char *file,const char *anchor,int lineNumber)
+ { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); }
+ void writeTooltip(const char *id, const DocLinkInfo &docInfo, const char *decl,
+ const char *desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo
+ )
+ { m_codeGen.writeTooltip(id,docInfo,decl,desc,defInfo,declInfo); }
+ void startCodeLine(bool hasLineNumbers)
+ { m_codeGen.startCodeLine(hasLineNumbers); }
+ void endCodeLine()
+ { m_codeGen.endCodeLine(); }
+ void startFontClass(const char *s)
+ { m_codeGen.startFontClass(s); }
+ void endFontClass()
+ { m_codeGen.endFontClass(); }
+ void writeCodeAnchor(const char *anchor)
+ { m_codeGen.writeCodeAnchor(anchor); }
+ // ---------------------------
+
+
void writeDoc(DocNode *,Definition *ctx,MemberDef *);
void startFile(const char *name,const char *manName,const char *title);
@@ -83,15 +151,9 @@ class LatexGenerator : public OutputGenerator
void startIndexItem(const char *ref,const char *file);
void endIndexItem(const char *ref,const char *file);
void docify(const char *text);
- void codify(const char *text);
void writeObjectLink(const char *ref,const char *file,
const char *anchor,const char *name);
- void writeCodeLink(const char *ref, const char *file,
- const char *anchor,const char *name,
- const char *tooltip);
- void writeTooltip(const char *, const DocLinkInfo &, const char *,
- const char *, const SourceLinkInfo &, const SourceLinkInfo &
- ) {}
+
void startTextLink(const char *,const char *);
void endTextLink();
void startHtmlLink(const char *url);
@@ -137,9 +199,6 @@ class LatexGenerator : public OutputGenerator
void writeAnchor(const char *fileName,const char *name);
void startCodeFragment();
void endCodeFragment();
- void writeLineNumber(const char *,const char *,const char *,int l);
- void startCodeLine(bool hasLineNumbers);
- void endCodeLine();
void startEmphasis() { t << "{\\em "; }
void endEmphasis() { t << "}"; }
void startBold() { t << "{\\bfseries "; }
@@ -267,10 +326,6 @@ class LatexGenerator : public OutputGenerator
void writeLabel(const char *l,bool isLast);
void endLabels();
- void startFontClass(const char *); // {}
- void endFontClass(); // {}
-
- void writeCodeAnchor(const char *) {}
void setCurrentDoc(Definition *,const char *,bool) {}
void addWord(const char *,bool) {}
@@ -278,17 +333,14 @@ class LatexGenerator : public OutputGenerator
private:
LatexGenerator(const LatexGenerator &);
LatexGenerator &operator=(const LatexGenerator &);
- void escapeLabelName(const char *s);
- void escapeMakeIndexChars(const char *s);
- int col;
bool insideTabbing;
bool firstDescItem;
bool disableLinks;
QCString relPath;
- QCString sourceFileName;
int m_indent;
bool templateMemberItem;
bool m_prettyCode;
+ LatexCodeGenerator m_codeGen;
};
#endif
diff --git a/src/template.cpp b/src/template.cpp
index e81ed17..f75d13e 100644
--- a/src/template.cpp
+++ b/src/template.cpp
@@ -101,10 +101,11 @@ static QValueList<QCString> split(const QCString &str,const QCString &sep,
/** Strips spaces surrounding `=` from string \a in, so
* `foo = 10 bar=5 baz= 'hello'` will become `foo=10 bar=5 baz='hello'`
*/
-static void removeSpacesAroundEquals(QCString &in)
+static QCString removeSpacesAroundEquals(const char *s)
{
- const char *p=in.data();
- char *q = in.data();
+ QCString result(s);
+ const char *p=result.data();
+ char *q = result.rawData();
char c;
while ((c=*p++))
{
@@ -121,7 +122,8 @@ static void removeSpacesAroundEquals(QCString &in)
}
*q++=c;
}
- if (q<p) in.resize(q-in.data()+1);
+ if (q<p) result.resize(q-result.data()+1);
+ return result;
}
//----------------------------------------------------------------------------
@@ -727,6 +729,10 @@ class TemplateContextImpl : public TemplateContext
m_spacelessEnabled=b;
}
bool spacelessEnabled() const { return m_spacelessEnabled && m_spacelessIntf; }
+ void enableTabbing(bool b) { m_tabbingEnabled=b;
+ if (m_activeEscapeIntf) m_activeEscapeIntf->enableTabbing(b);
+ }
+ bool tabbingEnabled() const { return m_tabbingEnabled; }
void warn(const char *fileName,int line,const char *fmt,...) const;
// index related functions
@@ -745,6 +751,7 @@ class TemplateContextImpl : public TemplateContext
TemplateEscapeIntf *m_activeEscapeIntf;
TemplateSpacelessIntf *m_spacelessIntf;
bool m_spacelessEnabled;
+ bool m_tabbingEnabled;
TemplateAutoRef<TemplateStruct> m_indices;
QDict< QStack<TemplateVariant> > m_indexStacks;
};
@@ -811,6 +818,62 @@ class FilterGet
}
};
+//-----------------------------------------------------------------------------
+
+/** @brief The implementation of the "raw" filter */
+class FilterRaw
+{
+ public:
+ static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &)
+ {
+ if (v.isValid() && (v.type()==TemplateVariant::String || v.type()==TemplateVariant::Integer))
+ {
+ return TemplateVariant(v.toString(),TRUE);
+ }
+ else
+ {
+ return v;
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+/** @brief The implementation of the "texlabel" filter */
+class FilterTexLabel
+{
+ public:
+ static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &)
+ {
+ if (v.isValid() && (v.type()==TemplateVariant::String))
+ {
+ return TemplateVariant(latexEscapeLabelName(v.toString(),FALSE),TRUE);
+ }
+ else
+ {
+ return v;
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+/** @brief The implementation of the "texindex" filter */
+class FilterTexIndex
+{
+ public:
+ static TemplateVariant apply(const TemplateVariant &v,const TemplateVariant &)
+ {
+ if (v.isValid() && (v.type()==TemplateVariant::String))
+ {
+ return TemplateVariant(latexEscapeIndexChars(v.toString(),FALSE),TRUE);
+ }
+ else
+ {
+ return v;
+ }
+ }
+};
//-----------------------------------------------------------------------------
@@ -1428,6 +1491,7 @@ class TemplateFilterFactory
// register a handlers for each filter we support
static TemplateFilterFactory::AutoRegister<FilterAdd> fAdd("add");
static TemplateFilterFactory::AutoRegister<FilterGet> fGet("get");
+static TemplateFilterFactory::AutoRegister<FilterRaw> fRaw("raw");
static TemplateFilterFactory::AutoRegister<FilterAppend> fAppend("append");
static TemplateFilterFactory::AutoRegister<FilterLength> fLength("length");
static TemplateFilterFactory::AutoRegister<FilterNoWrap> fNoWrap("nowrap");
@@ -1437,6 +1501,8 @@ static TemplateFilterFactory::AutoRegister<FilterPrepend> fPrepend("prepend"
static TemplateFilterFactory::AutoRegister<FilterGroupBy> fGroupBy("groupBy");
static TemplateFilterFactory::AutoRegister<FilterRelative> fRelative("relative");
static TemplateFilterFactory::AutoRegister<FilterListSort> fListSort("listsort");
+static TemplateFilterFactory::AutoRegister<FilterTexLabel> fTexLabel("texLabel");
+static TemplateFilterFactory::AutoRegister<FilterTexIndex> fTexIndex("texIndex");
static TemplateFilterFactory::AutoRegister<FilterPaginate> fPaginate("paginate");
static TemplateFilterFactory::AutoRegister<FilterStripPath> fStripPath("stripPath");
static TemplateFilterFactory::AutoRegister<FilterAlphaIndex> fAlphaIndex("alphaIndex");
@@ -2344,7 +2410,8 @@ class TemplateNodeList : public QList<TemplateNode>
class TemplateImpl : public TemplateNode, public Template
{
public:
- TemplateImpl(TemplateEngine *e,const QCString &name,const char *data,int size);
+ TemplateImpl(TemplateEngine *e,const QCString &name,const char *data,int size,
+ const QCString &extension);
void render(FTextStream &ts, TemplateContext *c);
TemplateEngine *engine() const { return m_engine; }
@@ -2698,7 +2765,6 @@ class TemplateNodeVariable : public TemplateNode
{
v = v.call(QValueList<TemplateVariant>());
}
- //printf("TemplateNodeVariable::render(%s) raw=%d\n",value.data(),v.raw());
if (ci->escapeIntf() && !v.raw())
{
ts << ci->escapeIntf()->escape(v.toString());
@@ -3519,6 +3585,24 @@ class TemplateNodeInclude : public TemplateNodeCreator<TemplateNodeInclude>
//----------------------------------------------------------
+static void stripLeadingWhiteSpace(QGString &s)
+{
+ const char *src = s.data();
+ if (src)
+ {
+ char *dst = s.data();
+ char c;
+ bool skipSpaces=TRUE;
+ while ((c=*src++))
+ {
+ if (c=='\n') { *dst++=c; skipSpaces=TRUE; }
+ else if (c==' ' && skipSpaces) {}
+ else { *dst++=c; skipSpaces=FALSE; }
+ }
+ *dst='\0';
+ }
+}
+
/** @brief Class representing an 'create' tag in a template */
class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
{
@@ -3582,17 +3666,18 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
TemplateImpl *t = getTemplate();
if (t)
{
+ QCString extension=outputFile;
+ int i=extension.findRev('.');
+ if (i!=-1)
+ {
+ extension=extension.right(extension.length()-i-1);
+ }
+ t->engine()->setOutputExtension(extension);
Template *ct = t->engine()->loadByName(templateFile,m_line);
TemplateImpl *createTemplate = ct ? dynamic_cast<TemplateImpl*>(ct) : 0;
if (createTemplate)
{
mkpath(ci,outputFile);
- QCString extension=outputFile;
- int i=extension.findRev('.');
- if (i!=-1)
- {
- extension=extension.right(extension.length()-i-1);
- }
if (!ci->outputDirectory().isEmpty())
{
outputFile.prepend(ci->outputDirectory()+"/");
@@ -3604,7 +3689,11 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
TemplateEscapeIntf *escIntf = ci->escapeIntf();
ci->selectEscapeIntf(extension);
FTextStream ts(&f);
- createTemplate->render(ts,c);
+ QGString out;
+ FTextStream os(&out);
+ createTemplate->render(os,c);
+ stripLeadingWhiteSpace(out);
+ ts << out;
t->engine()->unload(t);
ci->setActiveEscapeIntf(escIntf);
}
@@ -3617,6 +3706,7 @@ class TemplateNodeCreate : public TemplateNodeCreator<TemplateNodeCreate>
{
ci->warn(m_templateName,m_line,"failed to load template '%s' for include",templateFile.data());
}
+ t->engine()->setOutputExtension("");
}
}
}
@@ -3905,8 +3995,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
TRACE(("{TemplateNodeWith(%s)\n",data.data()));
m_args.setAutoDelete(TRUE);
ExpressionParser expParser(parser,line);
- QCString filteredData = data;
- removeSpacesAroundEquals(filteredData);
+ QCString filteredData = removeSpacesAroundEquals(data);
QValueList<QCString> args = split(filteredData," ");
QValueListIterator<QCString> it = args.begin();
while (it!=args.end())
@@ -3959,7 +4048,7 @@ class TemplateNodeWith : public TemplateNodeCreator<TemplateNodeWith>
//----------------------------------------------------------
-/** @brief Class representing an 'set' tag in a template */
+/** @brief Class representing an 'cycle' tag in a template */
class TemplateNodeCycle : public TemplateNodeCreator<TemplateNodeCycle>
{
public:
@@ -4194,6 +4283,36 @@ class TemplateNodeMarkers : public TemplateNodeCreator<TemplateNodeMarkers>
//----------------------------------------------------------
+/** @brief Class representing an 'tabbing' tag in a template */
+class TemplateNodeTabbing : public TemplateNodeCreator<TemplateNodeTabbing>
+{
+ public:
+ TemplateNodeTabbing(TemplateParser *parser,TemplateNode *parent,int line,const QCString &)
+ : TemplateNodeCreator<TemplateNodeTabbing>(parser,parent,line)
+ {
+ TRACE(("{TemplateNodeTabbing()\n"));
+ QStrList stopAt;
+ stopAt.append("endtabbing");
+ parser->parse(this,line,stopAt,m_nodes);
+ parser->removeNextToken(); // skip over endtabbing
+ TRACE(("}TemplateNodeTabbing()\n"));
+ }
+ void render(FTextStream &ts, TemplateContext *c)
+ {
+ TemplateContextImpl *ci = dynamic_cast<TemplateContextImpl*>(c);
+ if (ci==0) return; // should not happen
+ ci->setLocation(m_templateName,m_line);
+ bool wasTabbing = ci->tabbingEnabled();
+ ci->enableTabbing(TRUE);
+ m_nodes.render(ts,c);
+ ci->enableTabbing(wasTabbing);
+ }
+ private:
+ TemplateNodeList m_nodes;
+};
+
+//----------------------------------------------------------
+
/** @brief Class representing an 'markers' tag in a template */
class TemplateNodeResource : public TemplateNodeCreator<TemplateNodeResource>
{
@@ -4329,6 +4448,7 @@ static TemplateNodeFactory::AutoRegister<TemplateNodeCreate> autoRefCreat
static TemplateNodeFactory::AutoRegister<TemplateNodeRepeat> autoRefRepeat("repeat");
static TemplateNodeFactory::AutoRegister<TemplateNodeInclude> autoRefInclude("include");
static TemplateNodeFactory::AutoRegister<TemplateNodeMarkers> autoRefMarkers("markers");
+static TemplateNodeFactory::AutoRegister<TemplateNodeTabbing> autoRefTabbing("tabbing");
static TemplateNodeFactory::AutoRegister<TemplateNodeResource> autoRefResource("resource");
static TemplateNodeFactory::AutoRegister<TemplateNodeSpaceless> autoRefSpaceless("spaceless");
static TemplateNodeFactory::AutoRegister<TemplateNodeIndexEntry> autoRefIndexEntry("indexentry");
@@ -4419,6 +4539,8 @@ class TemplateLexer
public:
TemplateLexer(const TemplateEngine *engine,const QCString &fileName,const char *data,int size);
void tokenize(QList<TemplateToken> &tokens);
+ void setOpenCloseCharacters(char openChar,char closeChar)
+ { m_openChar=openChar; m_closeChar=closeChar; }
private:
void addToken(QList<TemplateToken> &tokens,
const char *data,int line,int startPos,int endPos,
@@ -4427,6 +4549,8 @@ class TemplateLexer
const TemplateEngine *m_engine;
QCString m_fileName;
QCString m_data;
+ char m_openChar;
+ char m_closeChar;
};
TemplateLexer::TemplateLexer(const TemplateEngine *engine,const QCString &fileName,const char *data,int size) :
@@ -4435,6 +4559,8 @@ TemplateLexer::TemplateLexer(const TemplateEngine *engine,const QCString &fileNa
m_data.resize(size+1);
memcpy(m_data.rawData(),data,size);
m_data[size]=0;
+ m_openChar='{';
+ m_closeChar='}';
}
void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
@@ -4453,6 +4579,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
};
const char *p=m_data.data();
+ if (p==0) return;
int state=StateText;
int pos=0;
int lastTokenPos=0;
@@ -4466,7 +4593,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
switch (state)
{
case StateText:
- if (c=='{') // {{ or {% or {# or something else
+ if (c==m_openChar) // {{ or {% or {# or something else
{
state=StateBeginTemplate;
}
@@ -4487,7 +4614,14 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
markStartPos=pos-1;
break;
case '{': // {{
- state=StateMaybeVar;
+ if (m_openChar=='{')
+ {
+ state=StateMaybeVar;
+ }
+ else
+ {
+ state=StateVariable;
+ }
markStartPos=pos-1;
break;
default:
@@ -4499,7 +4633,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
case StateTag:
if (c=='\n')
{
- warn(m_fileName,line,"unexpected new line inside {%%...%%} block");
+ warn(m_fileName,line,"unexpected new line inside %c%%...%%%c block",m_openChar,m_closeChar);
m_engine->printIncludeContext(m_fileName,line);
}
else if (c=='%') // %} or something else
@@ -4508,7 +4642,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
}
break;
case StateEndTag:
- if (c=='}') // %}
+ if (c==m_closeChar) // %}
{
// found tag!
state=StateText;
@@ -4523,7 +4657,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
{
if (c=='\n')
{
- warn(m_fileName,line,"unexpected new line inside {%%...%%} block");
+ warn(m_fileName,line,"unexpected new line inside %c%%...%%%c block",m_openChar,m_closeChar);
m_engine->printIncludeContext(m_fileName,line);
}
state=StateTag;
@@ -4532,7 +4666,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
case StateComment:
if (c=='\n')
{
- warn(m_fileName,line,"unexpected new line inside {#...#} block");
+ warn(m_fileName,line,"unexpected new line inside %c#...#%c block",m_openChar,m_closeChar);
m_engine->printIncludeContext(m_fileName,line);
}
else if (c=='#') // #} or something else
@@ -4541,7 +4675,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
}
break;
case StateEndComment:
- if (c=='}') // #}
+ if (c==m_closeChar) // #}
{
// found comment tag!
state=StateText;
@@ -4554,7 +4688,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
{
if (c=='\n')
{
- warn(m_fileName,line,"unexpected new line inside {#...#} block");
+ warn(m_fileName,line,"unexpected new line inside %c#...#%c block",m_openChar,m_closeChar);
m_engine->printIncludeContext(m_fileName,line);
}
state=StateComment;
@@ -4577,9 +4711,10 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
}
break;
case StateVariable:
+ emptyOutputLine=FALSE; // assume a variable expands to content
if (c=='\n')
{
- warn(m_fileName,line,"unexpected new line inside {{...}} block");
+ warn(m_fileName,line,"unexpected new line inside %c{...}%c block",m_openChar,m_closeChar);
m_engine->printIncludeContext(m_fileName,line);
}
else if (c=='}') // }} or something else
@@ -4588,7 +4723,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
}
break;
case StateEndVariable:
- if (c=='}') // }}
+ if (c==m_closeChar) // }}
{
// found variable tag!
state=StateText;
@@ -4603,7 +4738,7 @@ void TemplateLexer::tokenize(QList<TemplateToken> &tokens)
{
if (c=='\n')
{
- warn(m_fileName,line,"unexpected new line inside {{...}} block");
+ warn(m_fileName,line,"unexpected new line inside %c{...}%c block",m_openChar,m_closeChar);
m_engine->printIncludeContext(m_fileName,line);
}
state=StateVariable;
@@ -4705,7 +4840,7 @@ void TemplateParser::parse(
command=="endrecursetree" || command=="endspaceless" ||
command=="endmarkers" || command=="endmsg" ||
command=="endrepeat" || command=="elif" ||
- command=="endrange")
+ command=="endrange" || command=="endtabbing")
{
warn(m_templateName,tok->line,"Found tag '%s' without matching start tag",command.data());
}
@@ -4773,12 +4908,17 @@ void TemplateParser::warn(const char *fileName,int line,const char *fmt,...) con
//----------------------------------------------------------
-TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const char *data,int size)
+TemplateImpl::TemplateImpl(TemplateEngine *engine,const QCString &name,const char *data,int size,
+ const QCString &extension)
: TemplateNode(0)
{
m_name = name;
m_engine = engine;
TemplateLexer lexer(engine,name,data,size);
+ if (extension=="tex")
+ {
+ lexer.setOpenCloseCharacters('<','>');
+ }
QList<TemplateToken> tokens;
tokens.setAutoDelete(TRUE);
lexer.tokenize(tokens);
@@ -4851,27 +4991,9 @@ class TemplateEngine::Private
const Resource *res = ResourceMgr::instance().get(fileName);
if (res)
{
- templ = new TemplateImpl(m_engine,fileName,(const char *)res->data,res->size);
+ templ = new TemplateImpl(m_engine,fileName,(const char *)res->data,res->size,m_extension);
m_templateCache.insert(fileName,templ);
}
-#if 0
- QFile f(fileName);
- if (f.open(IO_ReadOnly))
- {
- uint size=f.size();
- char *data = new char[size+1];
- if (data)
- {
- data[size]=0;
- if (f.readBlock(data,f.size()))
- {
- templ = new TemplateImpl(m_engine,fileName,data);
- m_templateCache.insert(fileName,templ);
- }
- delete[] data;
- }
- }
-#endif
else
{
err("Cound not open template file %s\n",fileName.data());
@@ -4928,11 +5050,22 @@ class TemplateEngine::Private
}
}
+ void setOutputExtension(const char *extension)
+ {
+ m_extension = extension;
+ }
+
+ QCString outputExtension() const
+ {
+ return m_extension;
+ }
+
private:
QDict<Template> m_templateCache;
//mutable int m_indent;
TemplateEngine *m_engine;
QList<IncludeEntry> m_includeStack;
+ QCString m_extension;
};
TemplateEngine::TemplateEngine()
@@ -4980,3 +5113,15 @@ void TemplateEngine::printIncludeContext(const char *fileName,int line) const
p->printIncludeContext(fileName,line);
}
+void TemplateEngine::setOutputExtension(const char *extension)
+{
+ p->setOutputExtension(extension);
+}
+
+QCString TemplateEngine::outputExtension() const
+{
+ return p->outputExtension();
+}
+
+
+
diff --git a/src/template.h b/src/template.h
index c6c918c..d1501ce 100644
--- a/src/template.h
+++ b/src/template.h
@@ -396,6 +396,8 @@ class TemplateEscapeIntf
public:
/** Returns the \a input after escaping certain characters */
virtual QCString escape(const QCString &input) = 0;
+ /** Setting tabbing mode on or off (for LaTeX) */
+ virtual void enableTabbing(bool b) = 0;
};
//------------------------------------------------------------------------
@@ -523,13 +525,25 @@ class TemplateEngine
*/
void unload(Template *t);
+ /** Prints the current template file include stack */
void printIncludeContext(const char *fileName,int line) const;
private:
friend class TemplateNodeBlock;
+ friend class TemplateNodeCreate;
+
void enterBlock(const QCString &fileName,const QCString &blockName,int line);
void leaveBlock();
+ /** Sets the extension of the output file. This is used to control the
+ * format of 'special' tags in the template
+ */
+ void setOutputExtension(const char *extension);
+
+ /** Returns the output extension, set via setOutputExtension() */
+ QCString outputExtension() const;
+
+
class Private;
Private *p;
};
diff --git a/src/util.cpp b/src/util.cpp
index 0467953..946e2af 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -5773,6 +5773,15 @@ QCString convertToJSString(const char *s)
return convertCharEntitiesToUTF8(growBuf.get());
}
+QCString convertToLaTeX(const QCString &s,bool insideTabbing,bool keepSpaces)
+{
+ QGString result;
+ FTextStream t(&result);
+ filterLatexString(t,s,insideTabbing,FALSE,FALSE,keepSpaces);
+ return result.data();
+}
+
+
QCString convertCharEntitiesToUTF8(const QCString &s)
{
@@ -6488,7 +6497,7 @@ void addGroupListToTitle(OutputList &ol,Definition *d)
}
void filterLatexString(FTextStream &t,const char *str,
- bool insideTabbing,bool insidePre,bool insideItem)
+ bool insideTabbing,bool insidePre,bool insideItem,bool keepSpaces)
{
if (str==0) return;
//if (strlen(str)<2) stackTrace();
@@ -6509,6 +6518,7 @@ void filterLatexString(FTextStream &t,const char *str,
case '{': t << "\\{"; break;
case '}': t << "\\}"; break;
case '_': t << "\\_"; break;
+ case ' ': if (keepSpaces) t << "~"; else t << ' ';
default:
t << (char)c;
}
@@ -6580,6 +6590,8 @@ void filterLatexString(FTextStream &t,const char *str,
break;
case '\'': t << "\\textquotesingle{}";
break;
+ case ' ': if (keepSpaces) { if (insideTabbing) t << "\\>"; else t << '~'; } else t << ' ';
+ break;
default:
//if (!insideTabbing && forceBreaks && c!=' ' && *p!=' ')
@@ -6596,6 +6608,79 @@ void filterLatexString(FTextStream &t,const char *str,
}
}
+QCString latexEscapeLabelName(const char *s,bool insideTabbing)
+{
+ QGString result;
+ QCString tmp(qstrlen(s)+1);
+ FTextStream t(&result);
+ const char *p=s;
+ char c;
+ int i;
+ while ((c=*p++))
+ {
+ switch (c)
+ {
+ case '|': t << "\\texttt{\"|}"; break;
+ case '!': t << "\"!"; break;
+ case '%': t << "\\%"; break;
+ case '{': t << "\\lcurly{}"; break;
+ case '}': t << "\\rcurly{}"; break;
+ case '~': t << "````~"; break; // to get it a bit better in index together with other special characters
+ // 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
+ tmp[i++]=c;
+ while ((c=*p) && c!='|' && c!='!' && c!='%' && c!='{' && c!='}' && c!='~')
+ {
+ tmp[i++]=c;
+ p++;
+ }
+ tmp[i]=0;
+ filterLatexString(t,tmp.data(),insideTabbing);
+ break;
+ }
+ }
+ return result.data();
+}
+
+QCString latexEscapeIndexChars(const char *s,bool insideTabbing)
+{
+ QGString result;
+ QCString tmp(qstrlen(s)+1);
+ FTextStream t(&result);
+ const char *p=s;
+ char c;
+ int i;
+ while ((c=*p++))
+ {
+ switch (c)
+ {
+ case '!': t << "\"!"; break;
+ case '"': t << "\"\""; break;
+ case '@': t << "\"@"; break;
+ case '|': t << "\\texttt{\"|}"; break;
+ case '[': t << "["; break;
+ case ']': t << "]"; break;
+ case '{': t << "\\lcurly{}"; break;
+ case '}': t << "\\rcurly{}"; break;
+ // 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
+ tmp[i++]=c;
+ while ((c=*p) && c!='"' && c!='@' && c!='[' && c!=']' && c!='!' && c!='{' && c!='}' && c!='|')
+ {
+ tmp[i++]=c;
+ p++;
+ }
+ tmp[i]=0;
+ filterLatexString(t,tmp.data(),insideTabbing);
+ break;
+ }
+ }
+ return result.data();
+}
QCString rtfFormatBmkStr(const char *name)
{
@@ -8419,3 +8504,6 @@ QCString getDotImageExtension(void)
imgExt = imgExt.replace( QRegExp(":.*"), "" );
return imgExt;
}
+
+
+
diff --git a/src/util.h b/src/util.h
index 43d8752..a1a1bba 100644
--- a/src/util.h
+++ b/src/util.h
@@ -276,6 +276,8 @@ QCString stripScope(const char *name);
QCString convertToHtml(const char *s,bool keepEntities=TRUE);
+QCString convertToLaTeX(const QCString &s,bool insideTabbing=FALSE,bool keepSpaces=FALSE);
+
QCString convertToXML(const char *s);
QCString convertToJSString(const char *s);
@@ -334,7 +336,11 @@ void addGroupListToTitle(OutputList &ol,Definition *d);
void filterLatexString(FTextStream &t,const char *str,
bool insideTabbing=FALSE,
bool insidePre=FALSE,
- bool insideItem=FALSE);
+ bool insideItem=FALSE,
+ bool keepSpaces=FALSE);
+
+QCString latexEscapeLabelName(const char *s,bool insideTabbing);
+QCString latexEscapeIndexChars(const char *s,bool insideTabbing);
QCString rtfFormatBmkStr(const char *name);
diff --git a/templates/html/htmlbase.tpl b/templates/html/htmlbase.tpl
index 5ee7f3e..84807ec 100644
--- a/templates/html/htmlbase.tpl
+++ b/templates/html/htmlbase.tpl
@@ -196,7 +196,7 @@ $(document).ready(function(){initNavTree('{{ page.fileName }}{% if page_postfix
{% if config.HTML_TIMESTAMP %}
{{ tr.generatedAt:doxygen.date,config.PROJECT_NAME }}
{% else %}
-{{ tr.generatedby }}
+{{ tr.generatedBy }}
{% endif %}
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="{{ page.relPath }}doxygen.png" alt="doxygen"/></a> {{ doxygen.version }} </li>
@@ -207,7 +207,7 @@ $(document).ready(function(){initNavTree('{{ page.fileName }}{% if page_postfix
{% if config.HTML_TIMESTAMP %}
{{ tr.generatedAt:doxygen.date,config.PROJECT_NAME }}
{% else %}
-{{ tr.generatedby }}
+{{ tr.generatedBy }}
{% endif %}
&#160;<a href="http://www.doxygen.org/index.html"><img class="footer" src="{{ page.relPath }}doxygen.png" alt="doxygen"/></a>
{{ doxygen.version }}
diff --git a/templates/html/htmltypeconstraints.tpl b/templates/html/htmltypeconstraints.tpl
index 12c9581..b5a8cd0 100644
--- a/templates/html/htmltypeconstraints.tpl
+++ b/templates/html/htmltypeconstraints.tpl
@@ -1,5 +1,5 @@
{# obj should be a class or member #}
-{% if obj.typeConstraints|length>0 %}
+{% if obj.typeConstraints %}
<div class="typecontraint">
<dl><dt><b>{{ tr.typeConstraints }}</b></dt>
<dd><table border="0" cellspacing="2" cellpadding="0">
diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty
index 53d198f..948acf7 100644
--- a/templates/latex/doxygen.sty
+++ b/templates/latex/doxygen.sty
@@ -409,10 +409,10 @@
% Used by parameter lists and simple sections
\newenvironment{Desc}
{\begin{list}{}{%
- \settowidth{\labelwidth}{40pt}%
- \setlength{\leftmargin}{\labelwidth}%
+ \settowidth{\labelwidth}{20pt}%
\setlength{\parsep}{0pt}%
- \setlength{\itemsep}{-4pt}%
+ \setlength{\itemsep}{0pt}%
+ \setlength{\leftmargin}{\labelwidth+\labelsep}%
\renewcommand{\makelabel}{\entrylabel}%
}
}{%
diff --git a/templates/latex/latexannotated.tpl b/templates/latex/latexannotated.tpl
new file mode 100644
index 0000000..0b6ecb5
--- /dev/null
+++ b/templates/latex/latexannotated.tpl
@@ -0,0 +1,9 @@
+\section{<{ tr.classList }>}
+<{ tr.classListDescription }>
+\begin{DoxyCompactList}
+<% for cls in classList %>
+\item\contentsline{section}
+{<% with obj=cls text=cls.name %><% include 'latexobjlink.tpl' %><% endwith %><% if cls.brief %>\\*<{ cls.brief }><% endif %>}
+{\pageref{<{ cls.fileName|raw }>}}{}
+<% endfor %>
+\end{DoxyCompactList}
diff --git a/templates/latex/latexclass.tpl b/templates/latex/latexclass.tpl
new file mode 100644
index 0000000..7671de0
--- /dev/null
+++ b/templates/latex/latexclass.tpl
@@ -0,0 +1,114 @@
+<# input: compound #>
+<% msg %>Generating LaTeX output for class <{ compound.name }><% endmsg %>
+\hypertarget{<{ compound.fileName|raw }>}{}\section{<{ compound.title }>}
+\label{<{ compound.fileName|raw }>}\index{<{ compound.name|texLabel }>@{<{ compound.name|texIndex }>}}
+<# brief description #>
+<% if compound.brief %>
+ <{ compound.brief }>
+
+<% endif %>
+<# compound includes #>
+<% if compound.includeInfo %>
+ <% with ii=compound.includeInfo %>
+ <% include 'latexinclude.tpl' %>
+ <% endwith %>
+
+
+<% endif %>
+<# inheritance graph #>
+ <% if compound.hasInheritanceDiagram %>
+ <{ tr.inheritanceDiagramFor:compound.name }>
+ <{ compound.inheritanceDiagram }>
+ <% else %>
+ <# textual inheritance list #>
+ <% if compound.inherits|length>0 %>
+ <% markers c in compound.inherits with tr.inheritsList:compound.inherits|length %>
+ <% with obj=c.class text=c.name %>
+ <% include 'latexobjlink.tpl' %>
+ <% endwith %>
+ <% endmarkers %>
+
+
+ <% endif %>
+ <% if compound.inheritedBy|length>0 %>
+ <% markers c in compound.inheritedBy with tr.inheritedByList:compound.inheritedBy|length %>
+ <% with obj=c.class text=c.name %>
+ <% include 'latexobjlink.tpl' %>
+ <% endwith %>
+ <% endmarkers %>
+
+
+ <% endif %>
+ <% endif %>
+<# collaboration graph #>
+ <% if compound.hasCollaborationDiagram %>
+ <{ tr.collaborationDiagramFor:compound.name }>
+ <{ compound.collaborationDiagram }>
+
+
+ <% endif %>
+<# member declarations #>
+<% if compound.hasDetails %>
+ <% if compound.anchor %>
+ \label{<{ compound.anchor|raw }>}
+ <% if config.PDF_HYPERLINKS and config.USE_PDFLATEX %>
+ \hypertarget{<% if compound.fileName %><{ compound.fileName|raw }>_<% endif %><{ compound.anchor|raw }>}{}
+ <% endif %>
+ <% endif %>
+ <% if config.COMPACT_LATEX %>\subsubsection<% else %>\subsection<% endif %>{<{ tr.detailedDesc }>}
+ <# template specifier #>
+ <% if compound.language=='cpp' and compound.templateDecls %>
+ <% spaceless %>
+ \subsubsection*{
+ <% for targList in compound.templateDecls %>
+ template$<$
+ <% for targ in targList %>
+ <{ targ.type }><% if targ.name %><{ space }><{ targ.name }><% endif %><% if targ.defVal %><{ space }>= <{ targ.defVal }><% endif %><% if not forloop.last %>, <% endif %>
+ <% endfor %>
+ $>$\\*
+ <% endfor %>
+ <{ compound.compoundType }><{ space }><{ compound.name }>
+ }
+ <% endspaceless %>
+
+
+ <% endif %>
+ <% if compound.brief and config.REPEAT_BRIEF %>
+ <{ compound.brief }>
+
+
+ <% endif %>
+ <{ compound.details }>
+
+
+ <# type constraints #>
+ <% with obj=compound %>
+ <% include 'latextypeconstraints.tpl' %>
+ <% endwith %>
+
+
+<% endif %>
+<% msg %>
+ <# examples #>
+ <% if compound.examples %>
+ <dl><dt><b><{ tr.examples }></b><dd>
+ <% markers obj in compound.examples with tr.exampleList:compound.examples|length %>
+ <% with text=obj.text %>
+ <% include 'htmlobjlink.tpl' %>
+ <% endwith %>
+ <% endmarkers %>
+ </dd></dl>
+ <% endif %>
+ <# source definition #>
+ <% if compound.sourceDef %>
+ <% markers obj in compound.sourceDef with tr.definedAtLineInSourceFile %>
+ <% with text=obj.text %>
+ <% include 'htmlobjlink.tpl' %>
+ <% endwith %>
+ <% endmarkers %>
+ <% endif %>
+<% endmsg %>
+<# detailed description #>
+<# member definitions #>
+<# used files #>
+<# separate member pages #>
diff --git a/templates/latex/latexfiles.tpl b/templates/latex/latexfiles.tpl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/templates/latex/latexfiles.tpl
diff --git a/templates/latex/latexinclude.tpl b/templates/latex/latexinclude.tpl
new file mode 100644
index 0000000..c333056
--- /dev/null
+++ b/templates/latex/latexinclude.tpl
@@ -0,0 +1,32 @@
+<# input: ii with attributes (file,name,isImport,isLocal), compound with attribute language #>
+<% spaceless %>
+<% if ii.file or ii.name %>
+{\ttfamily<{ space }>
+ <% if compound.language=='java' or compound.language=='idl' %>
+ import
+ <% else %>
+ <% if ii.isImport %>
+ \#import
+ <% else %>
+ \#include
+ <% endif %>
+ <% endif %>
+ <{ space }>
+ <% if ii.isLocal %>
+ \char`\"{}
+ <% else %>
+ $<$
+ <% endif %>
+ <% if ii.name %>
+ <{ ii.name }>
+ <% else %>
+ <{ ii.file.name }>
+ <% endif %>
+ <% if ii.isLocal %>
+ \char`\"{}
+ <% else %>
+ $>$
+ <% endif %>
+}
+<% endif %>
+<% endspaceless %>
diff --git a/templates/latex/latexlayout.tpl b/templates/latex/latexlayout.tpl
new file mode 100644
index 0000000..290a4d5
--- /dev/null
+++ b/templates/latex/latexlayout.tpl
@@ -0,0 +1,35 @@
+{% msg %}----- Start generating LaTeX output for {{ config.PROJECT_NAME }} from template ----{% endmsg %}
+
+{% create 'refman.tex' from 'latexrefman.tpl' %}
+{% create 'Makefile' from 'latexmakefile.tpl' %}
+
+{# module index #}
+{% if moduleTree.tree %}
+ {% create 'modules.tex' from 'latexmodules.tpl' %}
+{% endif %}
+
+{# namespace index #}
+{% if namespaceTree.tree %}
+ {% create 'namespaces.tex' from 'latexnamespaces.tpl' %}
+{% endif %}
+
+{# class index #}
+{% if classTree.tree %}
+ {% create 'annotated.tex' from 'latexannotated.tpl' %}
+{% endif %}
+
+{# file index #}
+{% if fileTree.tree %}
+ {% create 'files.tex' from 'latexfiles.tpl' %}
+{% endif %}
+
+{# TODO: pages #}
+{# TODO: examples #}
+{# TODO: directories #}
+
+{# write class documentation pages #}
+{% for compound in classList %}
+ {% create compound.fileName|append:'.tex' from 'latexclass.tpl' %}
+{% endfor %}
+
+{% msg %}----- End generating LaTeX output for {{ config.PROJECT_NAME }} from template ----{% endmsg %}
diff --git a/templates/latex/latexmakefile.tpl b/templates/latex/latexmakefile.tpl
new file mode 100644
index 0000000..ba1eb76
--- /dev/null
+++ b/templates/latex/latexmakefile.tpl
@@ -0,0 +1,64 @@
+{% if config.USE_PDFLATEX %}
+all: refman.pdf
+
+pdf: refman.pdf
+
+refman.pdf: clean refman.tex
+ pdflatex refman
+ {{ config.MAKEINDEX_CMD_NAME }} refman.idx
+{# TODO: generateBib #}
+ pdflatex refman
+ latex_count=8 ; \
+ while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\
+ do \
+ echo "Rerunning latex...." ;\
+ pdflatex refman ;\
+ latex_count=`expr $$latex_count - 1` ;\
+ done
+ {{ config.MAKEINDEX_CMD_NAME }} refman.idx
+ pdflatex refman
+{% else %}
+all: refman.dvi
+
+ps: refman.ps
+
+pdf: refman.pdf
+
+ps_2on1: refman_2on1.ps
+
+pdf_2on1: refman_2on1.pdf
+
+refman.ps: refman.dvi
+ dvips -o refman.ps refman.dvi
+
+refman.pdf: refman.ps
+ ps2pdf refman.ps refman.pdf
+
+refman.dvi: clean refman.tex doxygen.sty
+ echo "Running latex..."
+ {{ config.LATEX_CMD_NAME }} refman.tex
+ echo "Running makeindex..."
+ {{ config.MAKEINDEX_CMD_NAME }} refman.idx
+{# TODO: generateBib #}
+ echo "Rerunning latex...."
+ {{ config.LATEX_CMD_NAME }} refman.tex
+ latex_count=8 ; \
+ while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\
+ do \
+ echo "Rerunning latex...." ;\
+ {{ config.LATEX_CMD_NAME }} refman.tex ;\
+ latex_count=`expr $$latex_count - 1` ;\
+ done
+ {{ config.MAKEINDEX_CMD_NAME }} refman.idx
+ {{ config.LATEX_CMD_NAME }} refman.tex
+
+refman_2on1.ps: refman.ps
+ psnup -2 refman.ps >refman_2on1.ps
+
+refman_2on1.pdf: refman_2on1.ps
+ ps2pdf refman_2on1.ps refman_2on1.pdf
+{% endif %}
+
+clean:
+ rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out *.brf *.blg *.bbl refman.pdf
+
diff --git a/templates/latex/latexmodules.tpl b/templates/latex/latexmodules.tpl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/templates/latex/latexmodules.tpl
diff --git a/templates/latex/latexnamespaces.tpl b/templates/latex/latexnamespaces.tpl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/templates/latex/latexnamespaces.tpl
diff --git a/templates/latex/latexobjlink.tpl b/templates/latex/latexobjlink.tpl
new file mode 100644
index 0000000..89ecc2e
--- /dev/null
+++ b/templates/latex/latexobjlink.tpl
@@ -0,0 +1,6 @@
+<# inputs: obj, text #>
+<% if config.PDF_HYPERLINKS %>
+\hyperlink{<{ obj.fileName|raw }><% if obj.anchor %>_<{ obj.anchor }><% endif %>}{<{ text }>}
+<% else %>
+{\bf <{ text }>}
+<% endif %>
diff --git a/templates/latex/latexrefman.tpl b/templates/latex/latexrefman.tpl
new file mode 100644
index 0000000..27b7ea0
--- /dev/null
+++ b/templates/latex/latexrefman.tpl
@@ -0,0 +1,227 @@
+\documentclass[twoside]{<% if config.COMPACT_LATEX %>article<% else %>book<% endif %>}
+
+% Packages required by doxygen
+\usepackage{fixltx2e}
+\usepackage{calc}
+\usepackage{doxygen}
+\usepackage[export]{adjustbox} % also loads graphicx
+<% for package in config.LATEX_EXTRA_STYLESHEET %>
+\usepackage{<{package|stripExtension:'.sty'}>}
+<% endfor %>
+\usepackage{graphicx}
+\usepackage[utf8]{inputenc}
+\usepackage{makeidx}
+\usepackage{multicol}
+\usepackage{multirow}
+\PassOptionsToPackage{warn}{textcomp}
+\usepackage{textcomp}
+\usepackage[nointegrals]{wasysym}
+\usepackage[table]{xcolor}
+
+<# TODO: languageSupportCommand #>
+
+% Font selection
+\usepackage[T1]{fontenc}
+\usepackage[scaled=.90]{helvet}
+\usepackage{courier}
+\usepackage{amssymb}
+\usepackage{sectsty}
+\renewcommand{\familydefault}{\sfdefault}
+\allsectionsfont{
+ \fontseries{bc}\selectfont
+ \color{darkgray}
+}
+\renewcommand{\DoxyLabelFont}{
+ \fontseries{bc}\selectfont
+ \color{darkgray}
+}
+\newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}}
+
+% Page & text layout
+\usepackage{geometry}
+\geometry{
+ <{ config.PAPER_TYPE }>paper,
+ top=2.5cm,
+ bottom=2.5cm,
+ left=2.5cm,
+ right=2.5cm
+}
+\tolerance=750
+\hfuzz=15pt
+\hbadness=750
+\setlength{\emergencystretch}{15pt}
+\setlength{\parindent}{0cm}
+\setlength{\parskip}{0.2cm}
+\makeatletter
+\renewcommand{\paragraph}{
+ \@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{
+ \normalfont\normalsize\bfseries\SS@parafont
+ }
+}
+\renewcommand{\subparagraph}{
+ \@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{
+ \normalfont\normalsize\bfseries\SS@subparafont
+ }
+}
+\makeatother
+
+% Headers & footers
+\usepackage{fancyhdr}
+\pagestyle{fancyplain}
+\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}}
+\fancyhead[CE]{\fancyplain{}{}}
+\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}}
+\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}}
+\fancyhead[CO]{\fancyplain{}{}}
+\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}}
+\fancyfoot[LE]{\fancyplain{}{}}
+\fancyfoot[CE]{\fancyplain{}{}}
+\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize <{ tr.generatedAt:doxygen.date,config.PROJECT_NAME }>}}
+\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize <{ tr.generatedAt:doxygen.date,config.PROJECT_NAME }>}}
+\fancyfoot[CO]{\fancyplain{}{}}
+\fancyfoot[RO]{\fancyplain{}{}}
+\renewcommand{\footrulewidth}{0.4pt}
+<% if not config.COMPACT_LATEX %>
+\renewcommand{\chaptermark}[1]{
+ \markboth{ #1}{}%
+}
+<% endif %>
+\renewcommand{\sectionmark}[1]{
+ \markright{\thesection\ #1}
+}
+
+% Indices & bibliography
+\usepackage{natbib}
+\usepackage[titles]{tocloft}
+\setcounter{tocdepth}{3}
+\setcounter{secnumdepth}{5}
+\makeindex
+
+<% if config.EXTRA_PACKAGES %>
+% Packages requested by user
+<% for package in config.EXTRA_PACKAGES %>
+\usepackage{<{ package }>}
+<% endfor %>
+<% endif %>
+
+<% if config.PDF_HYPERLINKS %>
+% Hyperlinks (required, but should be loaded last)
+\usepackage{ifpdf}
+\ifpdf
+ \usepackage[pdftex,pagebackref=true]{hyperref}
+\else
+ \usepackage[ps2pdf,pagebackref=true]{hyperref}
+\fi
+\hypersetup{
+ colorlinks=true,
+ linkcolor=blue,
+ citecolor=blue,
+ unicode
+}
+<% endif %>
+
+% Custom commands
+\newcommand{\clearemptydoublepage}{
+ \newpage{\pagestyle{empty}\cleardoublepage}
+}
+
+%===== C O N T E N T S =====
+
+\begin{document}
+<# TODO: select language for greek #>
+
+% Titlepage & ToC
+<% if config.USE_PDFLATEX and config.PDF_HYPERLINKS %>
+\hypersetup{pageanchor=false,
+ bookmarks=true,
+ bookmarksnumbered=true,
+ pdfencoding=unicode
+ }
+<% endif %>
+\pagenumbering{roman}
+\begin{titlepage}
+<% tabbing %>
+\vspace*{7cm}
+\begin{center}%
+{\Large
+<% if config.PROJECT_NAME %>
+ <{ config.PROJECT_NAME }>
+<% else %>
+ <{ tr.referenceManual }>
+<% endif %>
+<% if config.PROJECT_NUMBER %>
+\\[1ex]\large <{ config.PROJECT_NUMBER }>
+<% endif %>
+}\\
+\vspace*{1cm}{\large <{ tr.generatedBy }> Doxygen <{ doxygen.version }>}\\
+\vspace*{0.5cm}{\small <{ doxygen.date }>}\\
+\end{center}
+<% endtabbing %>
+\end{titlepage}
+<% if not config.COMPACT_LATEX %>\clearemptydoublepage<% endif %>
+
+\tableofcontents
+<% if not config.COMPACT_LATEX %>\clearemptydoublepage<% endif %>
+\pagenumbering{arabic}
+<% if config.USE_PDFLATEX and config.PDF_HYPERLINKS %>
+\hypersetup{pageanchor=true}
+<% endif %>
+
+%--- Begin generated contents ---
+<# TODO: loop over pages #>
+<% if moduleTree.tree %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.moduleIndex }>}
+\input{modules}
+<% endif %>
+<% if namespaceTree.tree %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.namespaceIndex }>}
+\input{namespaces}
+<% endif %>
+<% if classTree.tree %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.classIndex }>}
+\input{annotated}
+<% endif %>
+<% if fileTree.tree %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.fileIndex }>}
+\input{files}
+<% endif %>
+<% if moduleList %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.moduleDocumentation }>}
+<% for compound in moduleList %>
+\input{<{ compound.fileName|raw }>}
+<% endfor %>
+<% endif %>
+<% if namespaceList %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.namespaceDocumentation }>}
+<% for compound in namespaceList %>
+\input{<{ compound.fileName|raw }>}
+<% endfor %>
+<% endif %>
+<% if classList %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.classDocumentation }>}
+<% for compound in classList %>
+\input{<{ compound.fileName|raw }>}
+<% endfor %>
+<% endif %>
+<% if fileList %>
+<% if config.COMPACT_LATEX %>\section<% else %>\chapter<% endif %>{<{ tr.fileDocumentation }>}
+<% for compound in fileList %>
+\input{<{ compound.fileName|raw }>}
+<% endfor %>
+<% endif %>
+%--- End generated contents ---
+
+<# TODO: write bibliography #>
+% Index
+<% if not config.COMPACT_LATEX %>
+\backmatter
+<% endif %>
+\newpage
+\phantomsection
+\clearemptydoublepage
+\addcontentsline{toc}{<% if config.COMPACT_LATEX %>section<% else %>chapter<% endif %>}{<{ tr.index }>}
+\printindex
+
+\end{document}
+
+
diff --git a/templates/latex/latextypeconstraints.tpl b/templates/latex/latextypeconstraints.tpl
new file mode 100644
index 0000000..2853ab2
--- /dev/null
+++ b/templates/latex/latextypeconstraints.tpl
@@ -0,0 +1,12 @@
+<# obj should be a class or member #>
+<% msg %>type constraints = <{ obj.typeConstraints|length }><% endmsg %>
+<% if obj.typeConstraints %>
+\begin{Desc}
+\item[<{ tr.typeConstraints }>]
+\begin{description}
+<% for arg in obj.typeConstraints %>
+ \item[{\em <{ arg.name }>} : {\em <{ arg.type }>}] <{ arg.docs }>
+<% endfor %>
+\end{description}
+\end{Desc}
+<% endif %>