diff options
-rw-r--r-- | src/classdef.cpp | 3 | ||||
-rw-r--r-- | src/config.l | 5 | ||||
-rw-r--r-- | src/context.cpp | 638 | ||||
-rw-r--r-- | src/latexgen.cpp | 441 | ||||
-rw-r--r-- | src/latexgen.h | 88 | ||||
-rw-r--r-- | src/template.cpp | 241 | ||||
-rw-r--r-- | src/template.h | 14 | ||||
-rw-r--r-- | src/util.cpp | 90 | ||||
-rw-r--r-- | src/util.h | 8 | ||||
-rw-r--r-- | templates/html/htmlbase.tpl | 4 | ||||
-rw-r--r-- | templates/html/htmltypeconstraints.tpl | 2 | ||||
-rw-r--r-- | templates/latex/doxygen.sty | 6 | ||||
-rw-r--r-- | templates/latex/latexannotated.tpl | 9 | ||||
-rw-r--r-- | templates/latex/latexclass.tpl | 114 | ||||
-rw-r--r-- | templates/latex/latexfiles.tpl | 0 | ||||
-rw-r--r-- | templates/latex/latexinclude.tpl | 32 | ||||
-rw-r--r-- | templates/latex/latexlayout.tpl | 35 | ||||
-rw-r--r-- | templates/latex/latexmakefile.tpl | 64 | ||||
-rw-r--r-- | templates/latex/latexmodules.tpl | 0 | ||||
-rw-r--r-- | templates/latex/latexnamespaces.tpl | 0 | ||||
-rw-r--r-- | templates/latex/latexobjlink.tpl | 6 | ||||
-rw-r--r-- | templates/latex/latexrefman.tpl | 227 | ||||
-rw-r--r-- | templates/latex/latextypeconstraints.tpl | 12 |
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; } + + + @@ -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 %}  <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 %> |