/****************************************************************************** * * * * Copyright (C) 1997-2005 by Parker Waechter & Dimitri van Heesch. * * Style sheet additions by Alexander Bartolich * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */ #include #include "qtbc.h" #include #include #include "rtfgen.h" #include "config.h" #include "message.h" #include "doxygen.h" #include "util.h" #include "diagram.h" #include "language.h" #include "dot.h" #include "version.h" #include "pagedef.h" #include "rtfstyle.h" #include "rtfdocvisitor.h" #include "docparser.h" #include "dirdef.h" //#define DBG_RTF(x) x; #define DBG_RTF(x) static QCString dateToRTFDateString() { const QDateTime &d = QDateTime::currentDateTime(); QCString result; result.sprintf("\\yr%d\\mo%d\\dy%d\\hr%d\\min%d\\sec%d", d.date().year(), d.date().month(), d.date().day(), d.time().hour(),d.time().minute(),d.time().second()); return result; } RTFGenerator::RTFGenerator() : OutputGenerator() { dir=Config_getString("RTF_OUTPUT"); col=0; //insideTabbing=FALSE; m_listLevel = 0; m_bstartedBody = FALSE; m_omitParagraph = FALSE; m_numCols = 0; } RTFGenerator::~RTFGenerator() { } //void RTFGenerator::append(const OutputGenerator *g) //{ // t << g->getContents(); // col+=((RTFGenerator *)g)->col; // //insideTabbing=insideTabbing || ((RTFGenerator *)g)->insideTabbing; // m_listLevel=((RTFGenerator *)g)->m_listLevel; // m_omitParagraph=((RTFGenerator *)g)->m_omitParagraph; // //printf("RTFGenerator::append(%s) insideTabbing=%s\n", g->getContents().data(), // // insideTabbing ? "TRUE" : "FALSE" ); //} //OutputGenerator *RTFGenerator::copy() //{ // RTFGenerator *result = new RTFGenerator; // //result->insideTabbing=insideTabbing; // result->m_listLevel=m_listLevel; // result->m_omitParagraph=m_omitParagraph; // return result; //} void RTFGenerator::writeStyleSheetFile(QFile &file) { QTextStream t(&file); t << "# Generated by doxygen " << versionString << "\n\n"; t << "# This file describes styles used for generating RTF output.\n"; t << "# All text after a hash (#) is considered a comment and will be ignored.\n"; t << "# Remove a hash to activate a line.\n\n"; int i; for ( i=0 ; rtf_Style_Default[i].reference!=0 ; i++ ) { t << "# " << rtf_Style_Default[i].name << " = " << rtf_Style_Default[i].reference << rtf_Style_Default[i].definition << endl; } } void RTFGenerator::writeExtensionsFile(QFile &file) { QTextStream t(&file); t << "# Generated by doxygen " << versionString << "\n\n"; t << "# This file describes extensions used for generating RTF output.\n"; t << "# All text after a hash (#) is considered a comment and will be ignored.\n"; t << "# Remove a hash to activate a line.\n\n"; t << "# Overrides the project title.\n"; t << "#Title = \n\n"; t << "# Name of the company that produced this document.\n"; t << "#Company = \n\n"; t << "# Filename of a company or project logo.\n"; t << "#LogoFilename = \n\n"; t << "# Author of the document.\n"; t << "#Author = \n\n"; t << "# Type of document (e.g. Design Specification, User Manual, etc.).\n"; t << "#DocumentType = \n\n"; t << "# Document tracking number.\n"; t << "#DocumentId = \n\n"; t << "# Name of the author's manager.\n"; t << "# This field is not displayed in the document itself, but it is \n"; t << "# available in the information block of the rtf file. In Microsoft \n"; t << "# Word, it is available under File:Properties.\n"; t << "#Manager = \n\n"; t << "# Subject of the document.\n"; t << "# This field is not displayed in the document itself, but it is \n"; t << "# available in the information block of the rtf file. In Microsoft \n"; t << "# Word, it is available under File:Properties.\n"; t << "#Subject = \n\n"; t << "# Comments regarding the document.\n"; t << "# This field is not displayed in the document itself, but it is \n"; t << "# available in the information block of the rtf file. In Microsoft \n"; t << "# Word, it is available under File:Properties.\n"; t << "#Comments = \n\n"; t << "# Keywords associated with the document.\n"; t << "# This field is not displayed in the document itself, but it is \n"; t << "# available in the information block of the rtf file. In Microsoft \n"; t << "# Word, it is available under File:Properties.\n"; t << "#Keywords = \n\n"; } void RTFGenerator::init() { QCString dir=Config_getString("RTF_OUTPUT"); QDir d(dir); if (!d.exists() && !d.mkdir(dir)) { err("Could not create output directory %s\n",dir.data()); exit(1); } rtf_Style.setAutoDelete(TRUE); // first duplicate strings of rtf_Style_Default const struct Rtf_Style_Default* def = rtf_Style_Default; while(def->reference != 0) { if (def->definition == 0) err("Internal error: rtf_Style_Default[%s] has no definition.\n", def->name); StyleData* styleData = new StyleData(def->reference, def->definition); rtf_Style.insert(def->name, styleData); def++; } // overwrite some (or all) definitions from file QCString &rtfStyleSheetFile = Config_getString("RTF_STYLESHEET_FILE"); if (!rtfStyleSheetFile.isEmpty()) { loadStylesheet(rtfStyleSheetFile, rtf_Style); } // If user has defined an extension file, load its contents. QCString &rtfExtensionsFile = Config_getString("RTF_EXTENSIONS_FILE"); if (!rtfExtensionsFile.isEmpty()) { loadExtensions(rtfExtensionsFile); } createSubDirs(d); } static QCString makeIndexName(const char *s,int i) { QCString result=s; result+=(char)(i+'0'); return result; } void RTFGenerator::beginRTFDocument() { /* all the included RTF files should begin with the * same header */ t <<"{\\rtf1\\ansi\\ansicpg" << theTranslator->trRTFansicp(); t <<"\\uc1 \\deff0\\deflang1033\\deflangfe1033\n"; DBG_RTF(t <<"{\\comment Begining font list}\n") t <<"{\\fonttbl "; t <<"{\\f0\\froman\\fcharset" << theTranslator->trRTFCharSet(); t <<"\\fprq2{\\*\\panose 02020603050405020304}Times New Roman;}\n"; t <<"{\\f1\\fswiss\\fcharset" << theTranslator->trRTFCharSet(); t <<"\\fprq2{\\*\\panose 020b0604020202020204}Arial;}\n"; t <<"{\\f2\\fmodern\\fcharset" << theTranslator->trRTFCharSet(); t <<"\\fprq1{\\*\\panose 02070309020205020404}Courier New;}\n"; t <<"{\\f3\\froman\\fcharset2\\fprq2{\\*\\panose 05050102010706020507}Symbol;}\n"; t <<"}\n"; DBG_RTF(t <<"{\\comment begin colors}\n") t <<"{\\colortbl;"; t <<"\\red0\\green0\\blue0;"; t <<"\\red0\\green0\\blue255;"; t <<"\\red0\\green255\\blue255;"; t <<"\\red0\\green255\\blue0;"; t <<"\\red255\\green0\\blue255;"; t <<"\\red255\\green0\\blue0;"; t <<"\\red255\\green255\\blue0;"; t <<"\\red255\\green255\\blue255;"; t <<"\\red0\\green0\\blue128;"; t <<"\\red0\\green128\\blue128;"; t <<"\\red0\\green128\\blue0;"; t <<"\\red128\\green0\\blue128;"; t <<"\\red128\\green0\\blue0;"; t <<"\\red128\\green128\\blue0;"; t <<"\\red128\\green128\\blue128;"; t <<"\\red192\\green192\\blue192;}" << endl; DBG_RTF(t <<"{\\comment Beginning style list}\n") t <<"{\\stylesheet\n"; t <<"{\\widctlpar\\adjustright \\fs20\\cgrid \\snext0 Normal;}\n"; // sort styles ascending by \s-number via an intermediate QArray QArray array(128); array.fill(0); QDictIterator iter(rtf_Style); const StyleData* style; for(; (style = iter.current()); ++iter) { unsigned index = style->index; unsigned size = array.size(); if (index >= size) { // +1 to add at least one element, then align up to multiple of 8 array.resize((index + 1 + 7) & ~7); array.fill(0, size); ASSERT(index < array.size()); } if (array.at(index) != 0) { QCString key(convertToQCString(iter.currentKey())); msg("Style '%s' redefines \\s%d.\n", key.data(), index); } array.at(index) = style; } // write array elements unsigned size = array.size(); for(unsigned i = 0; i < size; i++) { const StyleData* style = array.at(i); if (style != 0) t <<"{" << style->reference << style->definition << ";}\n"; } t <<"}" << endl; // this comment is needed for postprocessing! t <<"{\\comment begin body}" << endl; } void RTFGenerator::beginRTFChapter() { t <<"\n"; DBG_RTF(t << "{\\comment BeginRTFChapter}\n") t << rtf_Style_Reset; // if we are compact, no extra page breaks... if (Config_getBool("COMPACT_RTF")) { // t <<"\\sect\\sectd\\sbknone\n"; t <<"\\sect\\sbknone\n"; rtfwriteRuler_thick(); } else t <<"\\sect\\sbkpage\n"; //t <<"\\sect\\sectd\\sbkpage\n"; t << rtf_Style["Heading1"]->reference << "\n"; } void RTFGenerator::beginRTFSection() { t <<"\n"; DBG_RTF(t << "{\\comment BeginRTFSection}\n") t << rtf_Style_Reset; // if we are compact, no extra page breaks... if (Config_getBool("COMPACT_RTF")) { // t <<"\\sect\\sectd\\sbknone\n"; t <<"\\sect\\sbknone\n"; rtfwriteRuler_emboss(); } else t <<"\\sect\\sbkpage\n"; //t <<"\\sect\\sectd\\sbkpage\n"; t << rtf_Style["Heading2"]->reference << "\n"; } void RTFGenerator::startFile(const char *name,const char *,const char *) { QCString fileName=name; relPath = relativePathToRoot(fileName); if (fileName.right(4)!=".rtf" ) fileName+=".rtf"; startPlainFile(fileName); beginRTFDocument(); } void RTFGenerator::endFile() { DBG_RTF(t << "{\\comment endFile}\n") t << "}"; endPlainFile(); } void RTFGenerator::startProjectNumber() { DBG_RTF(t <<"{\\comment startProjectNumber }" << endl) t << " "; } void RTFGenerator::endProjectNumber() { DBG_RTF(t <<"{\\comment endProjectNumber }" << endl) } void RTFGenerator::startIndexSection(IndexSections is) { //QCString paperName; m_listLevel = 0; switch (is) { case isTitlePageStart: // basic RTFstart // get readyfor author etc t << "{\\info \n"; t << "{\\title {\\comment "; break; case isTitlePageAuthor: t << "}\n"; if (rtf_subject) t << "{\\subject " << rtf_subject << "}\n"; if (rtf_comments) t << "{\\comment " << rtf_comments << "}\n"; if (rtf_company) t << "{\\company " << rtf_company << "}\n"; if (rtf_author) t << "{\\author " << rtf_author << "}\n"; if (rtf_manager) t << "{\\manager " << rtf_manager << "}\n"; if (rtf_documentType) t << "{\\category " << rtf_documentType << "}\n"; if (rtf_keywords) t << "{\\keywords " << rtf_keywords << "}\n"; t << "{\\comment "; break; case isMainPage: //Introduction beginRTFChapter(); break; //case isPackageIndex: // //Package Index // beginRTFChapter(); // break; case isModuleIndex: //Module Index beginRTFChapter(); break; case isDirIndex: //Directory Index beginRTFChapter(); break; case isNamespaceIndex: //Namespace Index beginRTFChapter(); break; case isClassHierarchyIndex: //Hierarchical Index DBG_RTF(t << "{\\comment start classhierarchy}\n") beginRTFChapter(); break; case isCompoundIndex: //Annotated Compound Index beginRTFChapter(); break; case isFileIndex: //Annotated File Index beginRTFChapter(); break; case isPageIndex: //Related Page Index beginRTFChapter(); break; case isModuleDocumentation: { //Module Documentation GroupSDict::Iterator gli(Doxygen::groupSDict); GroupDef *gd; bool found=FALSE; for (gli.toFirst();(gd=gli.current()) && !found;++gli) { if (!gd->isReference()) { beginRTFChapter(); found=TRUE; } } } break; case isDirDocumentation: { //Directory Documentation SDict::Iterator dli(Doxygen::directories); DirDef *dd; bool found=FALSE; for (dli.toFirst();(dd=dli.current()) && !found;++dli) { if (dd->isLinkableInProject()) { beginRTFChapter(); found=TRUE; } } } break; case isNamespaceDocumentation: { // Namespace Documentation NamespaceSDict::Iterator nli(Doxygen::namespaceSDict); NamespaceDef *nd; bool found=FALSE; for (nli.toFirst();(nd=nli.current()) && !found;++nli) { if (nd->isLinkableInProject()) { beginRTFChapter(); found=TRUE; } } } break; case isClassDocumentation: { //Compound Documentation ClassSDict::Iterator cli(Doxygen::classSDict); ClassDef *cd=0; bool found=FALSE; for (cli.toFirst();(cd=cli.current()) && !found;++cli) { if (cd->isLinkableInProject() && cd->templateMaster()==0) { beginRTFChapter(); found=TRUE; } } } break; case isFileDocumentation: { //File Documentation bool isFirst=TRUE; FileName *fn=Doxygen::inputNameList.first(); while (fn) { FileDef *fd=fn->first(); while (fd) { if (fd->isLinkableInProject()) { if (isFirst) { beginRTFChapter(); isFirst=FALSE; break; } } fd=fn->next(); } fn=Doxygen::inputNameList.next(); } } break; case isExampleDocumentation: { //Example Documentation beginRTFChapter(); } break; case isPageDocumentation: { //Page Documentation beginRTFChapter(); } break; case isEndIndex: break; } } void RTFGenerator::endIndexSection(IndexSections is) { switch (is) { case isTitlePageStart: if (rtf_title) // User has overridden document title in extensions file t << "}" << rtf_title; else t << "}" << Config_getString("PROJECT_NAME"); break; case isTitlePageAuthor: { t << "Doxgyen. }\n"; t << "{\\creatim " << dateToRTFDateString() << "}\n}"; DBG_RTF(t << "{\\comment end of infoblock}\n"); // setup for this section t << rtf_Style_Reset <<"\n"; t <<"\\sectd\\pgnlcrm\n"; t <<"{\\footer "<reference << "{\\chpgn}}\n"; // the title entry DBG_RTF(t << "{\\comment begin title page}\n") t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to title style t << "\\vertalc\\qc\\par\\par\\par\\par\\par\\par\\par\n"; if (rtf_logoFilename) { t << "{\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"" << rtf_logoFilename; t << "\" \\\\d \\\\*MERGEFORMAT} {\\fldrslt IMAGE }}\\par\\par\n"; } if (rtf_company) { t << rtf_company << "\\par\\par\n"; } t << rtf_Style_Reset << rtf_Style["Title"]->reference << endl; // set to title style t << "{\\field\\fldedit {\\*\\fldinst TITLE \\\\*MERGEFORMAT}{\\fldrslt TITLE}}\\par" << endl; t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to title style t << "\\par\n"; if (rtf_documentType) { t << rtf_documentType << "\\par\n"; } if (rtf_documentId) { t << rtf_documentId << "\\par\n"; } t << "\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\n"; t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to subtitle style t << "{\\field\\fldedit {\\*\\fldinst AUTHOR \\\\*MERGEFORMAT}{\\fldrslt AUTHOR}}\\par" << endl; t << "Version " << Config_getString("PROJECT_NUMBER") << "\\par"; t << "{\\field\\fldedit {\\*\\fldinst CREATEDATE \\\\*MERGEFORMAT}" "{\\fldrslt CREATEDATE}}\\par"<reference; t << theTranslator->trRTFTableOfContents() << "\\par"<< endl; t << rtf_Style_Reset << "\\par" << endl; t << "{\\field\\fldedit {\\*\\fldinst TOC \\\\f \\\\*MERGEFORMAT}{\\fldrslt Table of contents}}\\par\n"; t << rtf_Style_Reset << endl; } break; case isMainPage: t << "\\par " << rtf_Style_Reset << endl; if (!Doxygen::mainPage || Doxygen::mainPage->title().isEmpty()) { t << "{\\tc \\v " << theTranslator->trMainPage() << "}"<< endl; } else { t << "{\\tc \\v " << substitute(Doxygen::mainPage->title(),"%","") << "}"<< endl; } t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; if (Config_getBool("GENERATE_TREEVIEW")) t << "main"; else t << "index"; t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; //case isPackageIndex: // t << "\\par " << rtf_Style_Reset << endl; // t << "{\\tc \\v " << theTranslator->trPackageList() << "}"<< endl; // t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"packages.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; // break; case isModuleIndex: t << "\\par " << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trModuleIndex() << "}"<< endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"modules.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isDirIndex: t << "\\par " << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trDirIndex() << "}"<< endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"dirs.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isNamespaceIndex: t << "\\par " << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trNamespaceIndex() << "}"<< endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"namespaces.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isClassHierarchyIndex: t << "\\par " << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trHierarchicalIndex() << "}"<< endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"hierarchy.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isCompoundIndex: t << "\\par " << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trCompoundIndex() << "}"<< endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"annotated.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isFileIndex: t << "\\par " << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trFileIndex() << "}"<< endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"files.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isPageIndex: t << "\\par " << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trPageIndex() << "}"<< endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"pages.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; break; case isModuleDocumentation: { GroupSDict::Iterator gli(Doxygen::groupSDict); GroupDef *gd; t << "{\\tc \\v " << theTranslator->trModuleDocumentation() << "}"<< endl; for (gli.toFirst();(gd=gli.current());++gli) { if (!gd->isReference()) { t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << gd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } } } break; case isDirDocumentation: { SDict::Iterator dli(Doxygen::directories); DirDef *dd; t << "{\\tc \\v " << theTranslator->trDirDocumentation() << "}"<< endl; for (dli.toFirst();(dd=dli.current());++dli) { if (dd->isLinkableInProject()) { t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << dd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } } } break; case isNamespaceDocumentation: { NamespaceSDict::Iterator nli(Doxygen::namespaceSDict); NamespaceDef *nd; bool found=FALSE; for (nli.toFirst();(nd=nli.current()) && !found;++nli) { if (nd->isLinkableInProject()) { t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << nd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; found=TRUE; } } while ((nd=nli.current())) { if (nd->isLinkableInProject()) { t << "\\par " << rtf_Style_Reset << endl; beginRTFSection(); t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << nd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } ++nli; } } break; case isClassDocumentation: { ClassSDict::Iterator cli(Doxygen::classSDict); ClassDef *cd=0; bool found=FALSE; t << "{\\tc \\v " << theTranslator->trClassDocumentation() << "}"<< endl; for (cli.toFirst();(cd=cli.current()) && !found;++cli) { if (cd->isLinkableInProject() && cd->templateMaster()==0) { t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << cd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; found=TRUE; } } for (;(cd=cli.current());++cli) { if (cd->isLinkableInProject() && cd->templateMaster()==0) { t << "\\par " << rtf_Style_Reset << endl; beginRTFSection(); t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << cd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } } } break; case isFileDocumentation: { bool isFirst=TRUE; FileName *fn=Doxygen::inputNameList.first(); t << "{\\tc \\v " << theTranslator->trFileDocumentation() << "}"<< endl; while (fn) { FileDef *fd=fn->first(); while (fd) { if (fd->isLinkableInProject()) { if (isFirst) { t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << fd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; isFirst=FALSE; } else { t << "\\par " << rtf_Style_Reset << endl; beginRTFSection(); t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << fd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } } fd=fn->next(); } fn=Doxygen::inputNameList.next(); } } break; case isExampleDocumentation: { //t << "}\n"; t << "{\\tc \\v " << theTranslator->trExampleDocumentation() << "}"<< endl; PageSDict::Iterator pdi(*Doxygen::exampleSDict); PageDef *pd=pdi.toFirst(); if (pd) { t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << pd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } for (++pdi;(pd=pdi.current());++pdi) { t << "\\par " << rtf_Style_Reset << endl; beginRTFSection(); t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << pd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; } } break; case isPageDocumentation: { t << "{\\tc \\v " << theTranslator->trPageDocumentation() << "}"<< endl; PageSDict::Iterator pdi(*Doxygen::pageSDict); PageDef *pd=pdi.toFirst(); bool first=TRUE; for (pdi.toFirst();(pd=pdi.current());++pdi) { if (!pd->getGroupDef() && !pd->isReference()) { if (first) t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; t << pd->getOutputFileBase(); t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; first=FALSE; } } } break; case isEndIndex: beginRTFChapter(); t << rtf_Style["Heading1"]->reference; t << theTranslator->trRTFGeneralIndex() << "\\par "<< endl; t << rtf_Style_Reset << endl; t << "{\\tc \\v " << theTranslator->trRTFGeneralIndex() << "}" << endl; t << "{\\field\\fldedit {\\*\\fldinst INDEX \\\\c2 \\\\*MERGEFORMAT}{\\fldrslt INDEX}}\n"; break; } } void RTFGenerator::lastIndexPage() { DBG_RTF(t <<"{\\comment Beginning Body of RTF Document}\n") // end page and setup for rest of document t <<"\\sect \\sbkpage \\pgndec \\pgnrestart\n"; t <<"\\sect \\sectd \\sbknone\n"; // set new footer with arabic numbers t <<"{\\footer "<< rtf_Style["Footer"]->reference << "{\\chpgn}}\n"; //t << rtf_Style["Heading1"]->reference << "\n"; } void RTFGenerator::writeStyleInfo(int) { } void RTFGenerator::lineBreak() { DBG_RTF(t << "{\\comment (lineBreak)}" << endl) t << "\\par" << endl; } void RTFGenerator::writeString(const char *text) { t << text; } void RTFGenerator::startIndexList() { DBG_RTF(t << "{\\comment (startIndexList)}" << endl) t << "{" << endl; incrementIndentLevel(); t << rtf_Style_Reset << rtf_LCList_DepthStyle() << endl; newParagraph(); m_omitParagraph = TRUE; } void RTFGenerator::endIndexList() { DBG_RTF(t << "{\\comment (endIndexList)}" << endl) newParagraph(); t << "}"; decrementIndentLevel(); m_omitParagraph = TRUE; } /*! start bullet list */ void RTFGenerator::startItemList() { DBG_RTF(t << "{\\comment (startItemList level=" << m_listLevel << ") }" << endl) t << "{"; incrementIndentLevel(); rtf_listItemInfo[m_listLevel].isEnum = FALSE; } /*! end bullet list */ void RTFGenerator::endItemList() { newParagraph(); DBG_RTF(t << "{\\comment (endItemList level=" << m_listLevel << ")}" << endl) t << "}"; decrementIndentLevel(); m_omitParagraph = TRUE; } ///*! start enumeration list */ //void RTFGenerator::startEnumList() // starts an enumeration list //{ // DBG_RTF(t << "{\\comment (startEnumList)}" << endl) // t << "{" << endl; // incrementIndentLevel(); // rtf_listItemInfo[m_listLevel].isEnum = TRUE; // rtf_listItemInfo[m_listLevel].number = 1; //} // ///*! end enumeration list */ //void RTFGenerator::endEnumList() //{ // newParagraph(); // DBG_RTF(t << "{\\comment (endEnumList)}" << endl) // t << "}"; // decrementIndentLevel(); // m_omitParagraph = TRUE; //} /*! write bullet or enum item */ void RTFGenerator::writeListItem() { DBG_RTF(t << "{\\comment (writeListItem)}" << endl) newParagraph(); t << rtf_Style_Reset; if (rtf_listItemInfo[m_listLevel].isEnum) { t << rtf_EList_DepthStyle() << endl; t << rtf_listItemInfo[m_listLevel].number << ".\\tab "; rtf_listItemInfo[m_listLevel].number++; } else { t << rtf_BList_DepthStyle() << endl; } m_omitParagraph = TRUE; } void RTFGenerator::writeIndexItem(const char *ref,const char *fn, const char *name) { DBG_RTF(t << "{\\comment (writeIndexItem)}" << endl) //t << rtf_LCList_DepthStyle() << endl; docify(name); if (!ref && fn) { t << "\\tab "; writeRTFReference(fn); t << endl; } else { t << endl; } newParagraph(); m_omitParagraph = TRUE; } //void RTFGenerator::writeIndexFileItem(const char *,const char *text) //{ // t << "\\item\\contentsline{section}{"; // docify(text); // t << "}{\\pageref{" << text << "}}" << endl; //} void RTFGenerator::startHtmlLink(const char *url) { if (Config_getBool("RTF_HYPERLINKS")) { t << "{\\field {\\*\\fldinst { HYPERLINK \\\\l \""; t << url; t << "\" }{}"; t << "}{\\fldrslt {\\cs37\\ul\\cf2 "; } else { startTypewriter(); } } void RTFGenerator::endHtmlLink() { if (Config_getBool("RTF_HYPERLINKS")) { t << "}}}" << endl; } else { endTypewriter(); } } //void RTFGenerator::writeMailLink(const char *url) //{ // startTypewriter(); // docify(url); // endTypewriter(); //} void RTFGenerator::writeStartAnnoItem(const char *,const char *f, const char *path,const char *name) { DBG_RTF(t << "{\\comment (writeStartAnnoItem)}" << endl) t << "{\\b "; if (path) docify(path); if (f && Config_getBool("RTF_HYPERLINKS")) { t << "{\\field {\\*\\fldinst { HYPERLINK \\\\l \""; t << rtfFormatBmkStr(f); t << "\" }{}"; t << "}{\\fldrslt {\\cs37\\ul\\cf2 "; docify(name); t << "}}}" << endl; } else { docify(name); } t << "} "; } void RTFGenerator::writeEndAnnoItem(const char *name) { DBG_RTF(t << "{\\comment (writeEndAnnoItem)}" << endl) if (name) { t << "\\tab "; writeRTFReference(name); t << endl; } else { t << endl; } newParagraph(); } void RTFGenerator::startIndexKey() { DBG_RTF(t << "{\\comment (startIndexKey)}" << endl) t << "{\\b "; } void RTFGenerator::endIndexKey() { } void RTFGenerator::startIndexValue(bool hasBrief) { t << " "; if (hasBrief) t << "("; } void RTFGenerator::endIndexValue(const char *name,bool hasBrief) { DBG_RTF(t << "{\\comment (endIndexKey)}" << endl) if (hasBrief) t << ")"; t << "} "; if (name) { t << "\\tab "; writeRTFReference(name); t << endl; } else { t << endl; } newParagraph(); } void RTFGenerator::startSubsection() { //beginRTFSubSection(); t <<"\n"; DBG_RTF(t << "{\\comment Begin SubSection}\n") t << rtf_Style_Reset; t << rtf_Style["Heading3"]->reference << "\n"; } void RTFGenerator::endSubsection() { newParagraph(); t << rtf_Style_Reset << endl; } void RTFGenerator::startSubsubsection() { //beginRTFSubSubSection(); t << "\n"; DBG_RTF(t << "{\\comment Begin SubSubSection}\n") t << "{" << endl; t << rtf_Style_Reset << rtf_Style["Heading4"]->reference << "\n"; } void RTFGenerator::endSubsubsection() { newParagraph(); t << "}" << endl; } //void RTFGenerator::writeClassLink(const char *,const char *, // const char *,const char *name) //{ // t << "{\\bf "; // docify(name); // t << "}"; //} //void RTFGenerator::startTable(bool,int colNumbers) //{ // DBG_RTF(t << "{\\comment startTable}\n";) // m_numCols=colNumbers; // t << "\\par\n"; //} // //void RTFGenerator::endTable(bool hasCaption) //{ // DBG_RTF(t << "{\\comment endTable}\n";) // if (!hasCaption) // t << "\n\\pard \\widctlpar\\intbl\\adjustright\n{\\row }\n"; // t << "\\pard\n" << endl; //} // //void RTFGenerator::startCaption() //{ // DBG_RTF(t << "{\\comment startCaption}\n";) // endTableRow(); // t << "\\trowd \\trgaph108\\trleft-108\\trbrdrt\\brdrs\\brdrw10 \\trbrdrl\\brdrs\\brdrw10 \\trbrdrb\\brdrs\\brdrw10 \\trbrdrr\\brdrs\\brdrw10 \\trbrdrh\\brdrs\\brdrw10 \\trbrdrv\\brdrs\\brdrw10" << endl; // t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 \\clbrdrl\\brdrs\\brdrw10 \\clbrdrb\\brdrs\\brdrw10 \\clbrdrr \\brdrs\\brdrw10 \\cltxlrtb \\cellx"<0 && m_numCols<25); // uint columnWidth=rtf_pageWidth/m_numCols; // t << "\\trowd \\trgaph108\\trleft-108\\trbrdrt\\brdrs\\brdrw10 " // "\\trbrdrl\\brdrs\\brdrw10 \\trbrdrb\\brdrs\\brdrw10 " // "\\trbrdrr\\brdrs\\brdrw10 \\trbrdrh\\brdrs\\brdrw10 " // "\\trbrdrv\\brdrs\\brdrw10 "<reference << endl; } void RTFGenerator::endTitleHead(const char *fileName,const char *name) { DBG_RTF(t <<"{\\comment endTitleHead}" << endl) t << "\\par " << rtf_Style_Reset << endl; if (name) { // make table of contents entry t << "{\\tc\\tcl2 \\v "; docify(name); t << "}" << endl; // make an index entry addIndexItem(name,0); //if (name) //{ // writeAnchor(0,name); //} // //if (Config_getBool("RTF_HYPERLINKS") && fileName) //{ writeAnchor(fileName,0); //} } } void RTFGenerator::startTitle() { DBG_RTF(t <<"{\\comment startTitle}" << endl) if (Config_getBool("COMPACT_RTF")) beginRTFSection(); else beginRTFChapter(); } void RTFGenerator::startGroupHeader() { DBG_RTF(t <<"{\\comment startGroupHeader}" << endl) //newParagraph(); t << rtf_Style_Reset; t << rtf_Style["Heading3"]->reference; t << endl; } void RTFGenerator::endGroupHeader() { DBG_RTF(t <<"{\\comment endGroupHeader}" << endl) newParagraph(); t << rtf_Style_Reset << endl; } void RTFGenerator::startMemberDoc(const char *clname, const char *memname, const char *, const char *) { DBG_RTF(t << "{\\comment startMemberDoc}" << endl) if (memname && memname[0]!='@') { addIndexItem(memname,clname); addIndexItem(clname,memname); } t << rtf_Style_Reset << rtf_Style["Heading4"]->reference; //styleStack.push(rtf_Style_Heading4); t << "{" << endl; //printf("RTFGenerator::startMemberDoc() `%s'\n",rtf_Style["Heading4"]->reference); startBold(); t << endl; } void RTFGenerator::endMemberDoc(bool) { DBG_RTF(t << "{\\comment endMemberDoc}" << endl) t << "}" << endl; //const char *style = styleStack.pop(); //printf("RTFGenerator::endMemberDoc() `%s'\n",style); //ASSERT(style==rtf_Style["Heading4"]->reference); endBold(); newParagraph(); } void RTFGenerator::startDoxyAnchor(const char *,const char *, const char *,const char *, const char * ) { DBG_RTF(t << "{\\comment startDoxyAnchor}" << endl) } void RTFGenerator::endDoxyAnchor(const char *fName,const char *anchor) { QCString ref; if (fName) { ref+=fName; } if (anchor) { ref+='_'; ref+=anchor; } DBG_RTF(t << "{\\comment endDoxyAnchor}" << endl) t << "{\\bkmkstart "; t << rtfFormatBmkStr(ref); t << "}" << endl; t << "{\\bkmkend "; t << rtfFormatBmkStr(ref); t << "}" << endl; } //void RTFGenerator::writeLatexLabel(const char *clName,const char *anchor) //{ // writeDoxyAnchor(0,clName,anchor,0); //} void RTFGenerator::addIndexItem(const char *s1,const char *s2) { if (s1) { t << "{\\xe \\v "; docify(s1); if (s2) { t << "\\:"; docify(s2); } t << "}" << endl; } } void RTFGenerator::startIndent() { incrementIndentLevel(); DBG_RTF(t << "{\\comment (startIndent) }" << endl) t << "{" << endl; t << rtf_Style_Reset << rtf_CList_DepthStyle() << endl; } void RTFGenerator::endIndent() { t << "}" << endl; decrementIndentLevel(); } void RTFGenerator::startDescription() { DBG_RTF(t << "{\\comment (startDescription)}" << endl) t << "{" << endl; t << rtf_Style_Reset << rtf_DList_DepthStyle(); } void RTFGenerator::endDescription() { DBG_RTF(t << "{\\comment (endDescription)}" << endl) newParagraph(); t << "}"; } void RTFGenerator::startDescItem() { newParagraph(); DBG_RTF(t << "{\\comment (startDescItem)}" << endl) t << "{\\b "; } void RTFGenerator::endDescItem() { DBG_RTF(t << "{\\comment (endDescItem)}" << endl) t << "}" << endl; newParagraph(); } void RTFGenerator::startMemberDescription() { DBG_RTF(t << "{\\comment (startMemberDescription)}" << endl) t << "{" << endl; incrementIndentLevel(); t << rtf_Style_Reset << rtf_CList_DepthStyle(); startEmphasis(); } void RTFGenerator::endMemberDescription() { DBG_RTF(t << "{\\comment (endMemberDescription)}" << endl) endEmphasis(); newParagraph(); decrementIndentLevel(); t << "\\par}" << endl; } void RTFGenerator::startDescList(SectionTypes) { DBG_RTF(t << "{\\comment (startDescList)}" << endl) t << "{"; // ends at endDescList t << "{"; // ends at endDescTitle startBold(); newParagraph(); } //void RTFGenerator::endDescTitle() //{ // DBG_RTF(t << "{\\comment (endDescTitle) }" << endl) // endBold(); // t << "}"; // newParagraph(); // incrementIndentLevel(); // t << rtf_Style_Reset << rtf_DList_DepthStyle(); //} void RTFGenerator::writeDescItem() { DBG_RTF(t << "{\\comment (writeDescItem) }" << endl) } //void RTFGenerator::endDescList() //{ // DBG_RTF(t << "{\\comment (endDescList)}" << endl) // newParagraph(); // decrementIndentLevel(); // m_omitParagraph = TRUE; // t << "}"; //} void RTFGenerator::startSection(const char *,const char *title,SectionInfo::SectionType type) { DBG_RTF(t << "{\\comment (startSection)}" << endl) t << "{"; t<< rtf_Style_Reset; int num=4; switch(type) { case SectionInfo::Page: num=2; break; case SectionInfo::Section: num=3; break; case SectionInfo::Subsection: num=4; break; case SectionInfo::Subsubsection: num=4; break; case SectionInfo::Paragraph: num=4; break; default: ASSERT(0); break; } QCString heading; heading.sprintf("Heading%d",num); // set style t << rtf_Style[heading]->reference; // make table of contents entry t << "{\\tc\\tcl" << num << " \\v "; docify(title); t << "}" << endl; } void RTFGenerator::endSection(const char *lab,SectionInfo::SectionType) { DBG_RTF(t << "{\\comment (endSection)}" << endl) newParagraph(); // make bookmark writeAnchor(0,lab); t << "}"; } //void RTFGenerator::writeSectionRef(const char *ref,const char *, // const char *lab,const char *title) //{ // if (ref) // { // docify(title); // } // else // { // startBold(); // docify(title); // endBold(); // t << " ("; // docify(theTranslator->trPageAbbreviation()); // writeRTFReference(lab); // t << ")" << endl; // } //} // //void RTFGenerator::writeSectionRefItem(const char *,const char *lab, // const char *title) //{ // docify(title); // t << "\\tab"; // writeRTFReference(lab); // t << endl; //} // //void RTFGenerator::writeSectionRefAnchor(const char *name,const char *lab, // const char *title) //{ // writeSectionRef(name,lab,title); //} char* RTFGenerator::getMultiByte(int c) { static char s[10]; sprintf(s,"\\'%X",c); return s; } void RTFGenerator::docify(const char *str) { if (str) { const unsigned char *p=(const unsigned char *)str; unsigned char c; unsigned char pc='\0'; while (*p) { static bool MultiByte = FALSE; c=*p++; if ( MultiByte ) { t << getMultiByte( c ); MultiByte = FALSE; continue; } if ( c >= 0x80 ) { MultiByte = TRUE; t << getMultiByte( c ); continue; } switch (c) { case '{': t << "\\{"; break; case '}': t << "\\}"; break; case '\\': t << "\\\\"; break; default: { // see if we can insert an hyphenation hint //if (isupper(c) && islower(pc) && !insideTabbing) t << "\\-"; t << (char)c; } } pc = c; m_omitParagraph = FALSE; } } } void RTFGenerator::codify(const char *str) { // note that RTF does not have a "verbatim", so "\n" means // nothing... add a "newParagraph()"; //static char spaces[]=" "; if (str) { const unsigned char *p=(const unsigned char *)str; unsigned char c; int spacesToNextTabStop; while (*p) { static bool MultiByte = FALSE; c=*p++; if( MultiByte ) { t << getMultiByte( c ); MultiByte = FALSE; continue; } if( c >= 0x80 ) { MultiByte = TRUE; t << getMultiByte( c ); continue; } switch(c) { case '\t': spacesToNextTabStop = Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE")); t << spaces.left(spacesToNextTabStop); col+=spacesToNextTabStop; break; case '\n': newParagraph(); t << '\n'; col=0; break; case '{': t << "\\{"; col++; break; case '}': t << "\\}"; col++; break; case '\\': t << "\\\\"; col++; break; default: t << (char)c; col++; break; } } } } void RTFGenerator::writeChar(char c) { char cs[2]; cs[0]=c; cs[1]=0; docify(cs); } void RTFGenerator::startClassDiagram() { } void RTFGenerator::endClassDiagram(ClassDiagram &d, const char *fileName,const char *) { newParagraph(); // create a png file d.writeImage(t,dir,relPath,fileName,FALSE); // display the file t << "{" << endl; t << rtf_Style_Reset << endl; t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \""; t << fileName << ".png\""; t << " \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; t << "}" << endl; } //void RTFGenerator::writeFormula(const char *,const char *text) //{ // t << text; //} void RTFGenerator::startMemberItem(int) { DBG_RTF(t <<"{\\comment startMemberItem }" << endl) t << rtf_Style_Reset << rtf_BList_DepthStyle() << endl; // set style to apropriate depth } void RTFGenerator::endMemberItem() { DBG_RTF(t <<"{\\comment endMemberItem }" << endl) newParagraph(); } void RTFGenerator::writeAnchor(const char *fileName,const char *name) { QCString anchor; if (fileName) { anchor+=fileName; } if (fileName && name) { anchor+='_'; } if (name) { anchor+=name; } DBG_RTF(t <<"{\\comment writeAncheor (" << anchor << ")}" << endl) t << "{\\bkmkstart " << rtfFormatBmkStr(anchor) << "}" << endl; t << "{\\bkmkend " << rtfFormatBmkStr(anchor) << "}" << endl; } void RTFGenerator::writeRTFReference(const char *label) { t << "{\\field\\fldedit {\\*\\fldinst PAGEREF "; t << rtfFormatBmkStr(label); t << " \\\\*MERGEFORMAT}{\\fldrslt pagenum}}"; } void RTFGenerator::startCodeFragment() { DBG_RTF(t << "{\\comment (startCodeFragment) }" << endl) t << "{" << endl; //newParagraph(); t << rtf_Style_Reset << rtf_Code_DepthStyle(); //styleStack.push(rtf_Style_CodeExample); } void RTFGenerator::endCodeFragment() { //newParagraph(); //styleStack.pop(); //printf("RTFGenerator::endCodeFrament() top=%s\n",styleStack.top()); //t << rtf_Style_Reset << styleStack.top() << endl; DBG_RTF(t << "{\\comment (endCodeFragment) }" << endl) t << "}" << endl; m_omitParagraph = TRUE; } void RTFGenerator::writeNonBreakableSpace(int) { t << "\\~ "; } void RTFGenerator::startMemberList() { t << endl; DBG_RTF(t << "{\\comment (startMemberList) }" << endl) t << "{" << endl; #ifdef DELETEDCODE if (!insideTabbing) t << "\\begin{CompactItemize}" << endl; #endif } void RTFGenerator::endMemberList() { DBG_RTF(t << "{\\comment (endMemberList) }" << endl) t << "}" << endl; #ifdef DELETEDCODE if (!insideTabbing) t << "\\end{CompactItemize}" << endl; #endif } //void RTFGenerator::startImage(const char *name,const char *,bool) //{ // newParagraph(); // t << "{" << endl; // t << rtf_Style_Reset << endl; // t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE "; // t << name; // t << " \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; // t << "}" << endl; //} // //void RTFGenerator::endImage(bool) //{ // // not yet implemented //} // //void RTFGenerator::startDotFile(const char *name,bool) //{ // QCString baseName=name; // int i; // if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1) // { // baseName=baseName.right(baseName.length()-i-1); // } // QCString outDir = Config_getString("RTF_OUTPUT"); // writeDotGraphFromFile(name,outDir,baseName,BITMAP); // newParagraph(); // t << "{" << endl; // t << rtf_Style_Reset << endl; // t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE "; // t << outDir << "\\" << baseName; // t << " \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; // t << "}" << endl; //} // //void RTFGenerator::endDotFile(bool) //{ // // not yet implemented //} // void RTFGenerator::startDescTable() { DBG_RTF(t << "{\\comment (startDescTable) }" << endl) //t << "{" << endl; //incrementIndentLevel(); //t << rtf_Style_Reset << rtf_CList_DepthStyle(); } void RTFGenerator::endDescTable() { //decrementIndentLevel(); DBG_RTF(t << "{\\comment (endDescTable)}" << endl) //t << "}" << endl; //t << rtf_Style_Reset << styleStack.top(); } void RTFGenerator::startDescTableTitle() { //t << rtf_BList_DepthStyle() << endl; DBG_RTF(t << "{\\comment (startDescTableTitle) }" << endl) startBold(); startEmphasis(); } void RTFGenerator::endDescTableTitle() { DBG_RTF(t << "{\\comment (endDescTableTitle) }" << endl) endEmphasis(); endBold(); t << " "; } void RTFGenerator::startDescTableData() { DBG_RTF(t << "{\\comment (startDescTableData) }" << endl) m_omitParagraph = FALSE; } void RTFGenerator::endDescTableData() { DBG_RTF(t << "{\\comment (endDescTableData) }" << endl) newParagraph(); m_omitParagraph = TRUE; } // a style for list formatted as a "bulleted list" void RTFGenerator::incrementIndentLevel() { m_listLevel++; if (m_listLevel>rtf_maxIndentLevels-1) { warn_cont("Warning: Maximum indent level (%d) exceeded while generating RTF output!\n",rtf_maxIndentLevels); m_listLevel=rtf_maxIndentLevels-1; } } void RTFGenerator::decrementIndentLevel() { m_listLevel--; if (m_listLevel<0) { warn_cont("Warning: Negative indent level while generating RTF output!\n"); m_listLevel=0; } } // a style for list formatted with "list continue" style const char * RTFGenerator::rtf_CList_DepthStyle() { QCString n=makeIndexName("ListContinue",m_listLevel); return rtf_Style[n]->reference; } // a style for list formatted as a "latext style" table of contents const char * RTFGenerator::rtf_LCList_DepthStyle() { QCString n=makeIndexName("LatexTOC",m_listLevel); return rtf_Style[n]->reference; } // a style for list formatted as a "bullet" style const char * RTFGenerator::rtf_BList_DepthStyle() { QCString n=makeIndexName("ListBullet",m_listLevel); return rtf_Style[n]->reference; } // a style for list formatted as a "enumeration" style const char * RTFGenerator::rtf_EList_DepthStyle() { QCString n=makeIndexName("ListEnum",m_listLevel); return rtf_Style[n]->reference; } const char * RTFGenerator::rtf_DList_DepthStyle() { QCString n=makeIndexName("DescContinue",m_listLevel); return rtf_Style[n]->reference; } const char * RTFGenerator::rtf_Code_DepthStyle() { QCString n=makeIndexName("CodeExample",m_listLevel); return rtf_Style[n]->reference; } void RTFGenerator::startTextBlock(bool dense) { DBG_RTF(t << "{\\comment startTextBlock}" << endl) t << "{" << endl; t << rtf_Style_Reset; if (dense) // no spacing between "paragraphs" { t << rtf_Style["DenseText"]->reference; } else // some spacing { t << rtf_Style["BodyText"]->reference; } } void RTFGenerator::endTextBlock(bool paraBreak) { if (paraBreak) newParagraph(); DBG_RTF(t << "{\\comment endTextBlock}" << endl) t << "}" << endl; //m_omitParagraph = TRUE; } void RTFGenerator::newParagraph() { if (!m_omitParagraph) { DBG_RTF(t << "{\\comment (newParagraph)}" << endl) t << "\\par" << endl; } m_omitParagraph = FALSE; } void RTFGenerator::startMemberSubtitle() { DBG_RTF(t << "{\\comment startMemberSubtitle}" << endl) t << "{" << endl; t << rtf_Style_Reset << rtf_CList_DepthStyle() << endl; } void RTFGenerator::endMemberSubtitle() { DBG_RTF(t << "{\\comment endMemberSubtitle}" << endl) newParagraph(); t << "}" << endl; } //void RTFGenerator::writeUmlaut(char c) //{ // switch(c) // { // case 'A' : t << '\304'; break; // case 'E' : t << '\313'; break; // case 'I' : t << '\317'; break; // case 'O' : t << '\326'; break; // case 'U' : t << '\334'; break; // case 'Y' : t << 'Y'; break; // case 'a' : t << '\344'; break; // case 'e' : t << '\353'; break; // case 'i' : t << '\357'; break; // case 'o' : t << '\366'; break; // case 'u' : t << '\374'; break; // case 'y' : t << '\377'; break; // default: t << '?'; break; // } //} // //void RTFGenerator::writeAcute(char c) //{ // switch(c) // { // case 'A' : t << '\301'; break; // case 'E' : t << '\311'; break; // case 'I' : t << '\315'; break; // case 'O' : t << '\323'; break; // case 'U' : t << '\332'; break; // case 'Y' : t << '\335'; break; // case 'a' : t << '\341'; break; // case 'e' : t << '\351'; break; // case 'i' : t << '\355'; break; // case 'o' : t << '\363'; break; // case 'u' : t << '\372'; break; // case 'y' : t << '\375'; break; // default: t << '?'; break; // } //} // //void RTFGenerator::writeGrave(char c) //{ // switch(c) // { // case 'A' : t << '\300'; break; // case 'E' : t << '\310'; break; // case 'I' : t << '\314'; break; // case 'O' : t << '\322'; break; // case 'U' : t << '\331'; break; // case 'a' : t << '\340'; break; // case 'e' : t << '\350'; break; // case 'i' : t << '\354'; break; // case 'o' : t << '\362'; break; // case 'u' : t << '\371'; break; // default: t << '?'; break; // } //} // //void RTFGenerator::writeCirc(char c) //{ // switch(c) // { // case 'A' : t << '\302'; break; // case 'E' : t << '\312'; break; // case 'I' : t << '\316'; break; // case 'O' : t << '\324'; break; // case 'U' : t << '\333'; break; // case 'a' : t << '\342'; break; // case 'e' : t << '\352'; break; // case 'i' : t << '\356'; break; // case 'o' : t << '\364'; break; // case 'u' : t << '\373'; break; // default: t << '?'; break; // } //} // //void RTFGenerator::writeTilde(char c) //{ // switch(c) // { // case 'A' : t << '\303'; break; // case 'N' : t << '\321'; break; // case 'O' : t << '\325'; break; // case 'a' : t << '\343'; break; // case 'n' : t << '\361'; break; // case 'o' : t << '\365'; break; // default: t << '?'; break; // } //} // //void RTFGenerator::writeRing(char c) //{ // switch(c) // { // case 'A' : t << '\305'; break; // case 'a' : t << '\345'; break; // default: t << '?'; break; // } //} // //void RTFGenerator::writeCCedil(char c) //{ // switch(c) // { // case 'C' : t << '\307'; break; // case 'c' : t << '\347'; break; // default: t << '?'; break; // } //} // /** * VERY brittle routine inline RTF's included by other RTF's. * it is recursive and ugly. */ static bool PreProcessFile(QDir &d,QCString &infName, QTextStream &t, bool bIncludeHeader=TRUE) { QFile f(infName); if (!f.open(IO_ReadOnly)) { err("Error opening rtf file %s for reading\n",infName.data()); return FALSE; } const int maxLineLength = 10240; static QCString lineBuf(maxLineLength); // scan until find end of header // this is EXTREEEEEEEMLY brittle. It works on OUR rtf // files because the first line before the body // ALWAYS contains "{\comment begin body}" do { if (f.readLine(lineBuf.data(),maxLineLength)==-1) { err("ERROR - read error in %s before end of RTF header!\n",infName.data()); return FALSE; } if (bIncludeHeader) t << lineBuf; } while (lineBuf.find("\\comment begin body")==-1); //while (fgets(buffer,sizeof(buffer),infp) != NULL) while (f.readLine(lineBuf.data(),maxLineLength)!=-1) { int pos; if ((pos=lineBuf.find("INCLUDETEXT"))!=-1) { int startNamePos = lineBuf.find('"',pos)+1; int endNamePos = lineBuf.find('"',startNamePos); QCString fileName = lineBuf.mid(startNamePos,endNamePos-startNamePos); DBG_RTF(t << "{\\comment begin include " << fileName << "}" << endl) if (!PreProcessFile(d,fileName,t,FALSE)) return FALSE; DBG_RTF(t << "{\\comment end include " << fileName << "}" << endl) } else { // elaborate hoopla to skip the final "}" if we didn't include the // headers if (!f.atEnd() || bIncludeHeader) { t << lineBuf; } else { // null terminate at the last '}' //char *str = strrchr(buffer,'}'); int pos = lineBuf.findRev('}'); if (pos != -1) lineBuf.at(pos) = '\0'; else err("Strange, the last char was not a '}'\n"); t << lineBuf; } } } f.close(); // remove temporary file d.remove(infName); return TRUE; } void RTFGenerator::startDotGraph() { DBG_RTF(t << "{\\comment (startDotGraph)}" << endl) } void RTFGenerator::endDotGraph(DotClassGraph &g) { newParagraph(); QCString fileName = g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"),relPath,TRUE,FALSE); // display the file t << "{" << endl; t << rtf_Style_Reset << endl; t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \""; t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT"); t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; t << "}" << endl; newParagraph(); DBG_RTF(t << "{\\comment (endDotGraph)}" << endl) } void RTFGenerator::startInclDepGraph() { DBG_RTF(t << "{\\comment (startInclDepGraph)}" << endl) } void RTFGenerator::endInclDepGraph(DotInclDepGraph &g) { newParagraph(); QCString fileName = g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"), relPath,FALSE); // display the file t << "{" << endl; t << rtf_Style_Reset << endl; t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \""; t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT"); t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; t << "}" << endl; DBG_RTF(t << "{\\comment (endInclDepGraph)}" << endl) } void RTFGenerator::startGroupCollaboration() { } void RTFGenerator::endGroupCollaboration(DotGroupCollaboration &) { } void RTFGenerator::startCallGraph() { DBG_RTF(t << "{\\comment (startCallGraph)}" << endl) } void RTFGenerator::endCallGraph(DotCallGraph &g) { newParagraph(); QCString fileName = g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"), relPath,FALSE); // display the file t << "{" << endl; t << rtf_Style_Reset << endl; t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \""; t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT"); t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; t << "}" << endl; DBG_RTF(t << "{\\comment (endCallGraph)}" << endl) } void RTFGenerator::startDirDepGraph() { DBG_RTF(t << "{\\comment (startDirDepGraph)}" << endl) } void RTFGenerator::endDirDepGraph(DotDirDeps &g) { newParagraph(); QCString fileName = g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"), relPath,FALSE); // display the file t << "{" << endl; t << rtf_Style_Reset << endl; t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \""; t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT"); t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl; t << "}" << endl; DBG_RTF(t << "{\\comment (endDirDepGraph)}" << endl) } /** Tests the integrity of the result by counting brackets. * */ void testRTFOutput(const char *name) { int bcount=0; int line=1; int c; QFile f(name); if (f.open(IO_ReadOnly)) { while ((c=f.getch())!=-1) { if (c=='\\') // escape char { c=f.getch(); if (c==-1) break; } else if (c=='{') // open bracket { bcount++; } else if (c=='}') // close bracket { bcount--; if (bcount<0) { goto err; break; } } else if (c=='\n') // newline { line++; } } } if (bcount==0) return; // file is OK. err: err("Error: RTF integrity test failed at line %d of %s due to a bracket mismatch.\n",line,name); err(" Please try to create a small code example that produces this error \n" " and send that to dimitri@stack.nl.\n"); } /** * This is an API to a VERY brittle RTF preprocessor that combines nested * RTF files. This version replaces the infile with the new file */ bool RTFGenerator::preProcessFileInplace(const char *path,const char *name) { QDir d(path); // store the original directory if (!d.exists()) { err("Error: Output dir %s does not exist!\n",path); return FALSE; } QCString oldDir = convertToQCString(QDir::currentDirPath()); // go to the html output directory (i.e. path) QDir::setCurrent(d.absPath()); QDir thisDir; QCString combinedName = (QCString)path+"/combined.rtf"; QCString mainRTFName = (QCString)path+"/"+name; QFile outf(combinedName); if (!outf.open(IO_WriteOnly)) { err("Failed to open %s for writing!\n",combinedName.data()); return FALSE; } QTextStream outt(&outf); #if QT_VERSION >= 200 outt.setEncoding(QTextStream::Latin1); #endif if (!PreProcessFile(thisDir,mainRTFName,outt)) { // it failed, remove the temp file outf.close(); thisDir.remove(combinedName); QDir::setCurrent(oldDir); return FALSE; } // everything worked, move the files outf.close(); thisDir.remove(mainRTFName); thisDir.rename(combinedName,mainRTFName); testRTFOutput(mainRTFName); QDir::setCurrent(oldDir); return TRUE; } void RTFGenerator::startMemberGroupHeader(bool hasHeader) { DBG_RTF(t << "{\\comment startMemberGroupHeader}" << endl) t << "{" << endl; if (hasHeader) incrementIndentLevel(); t << rtf_Style_Reset << rtf_Style["GroupHeader"]->reference; } void RTFGenerator::endMemberGroupHeader() { DBG_RTF(t << "{\\comment endMemberGroupHeader}" << endl) newParagraph(); t << rtf_Style_Reset << rtf_CList_DepthStyle(); } void RTFGenerator::startMemberGroupDocs() { DBG_RTF(t << "{\\comment startMemberGroupDocs}" << endl) startEmphasis(); } void RTFGenerator::endMemberGroupDocs() { DBG_RTF(t << "{\\comment endMemberGroupDocs}" << endl) endEmphasis(); newParagraph(); } void RTFGenerator::startMemberGroup() { DBG_RTF(t << "{\\comment startMemberGroup}" << endl) t << rtf_Style_Reset << rtf_BList_DepthStyle() << endl; } void RTFGenerator::endMemberGroup(bool hasHeader) { DBG_RTF(t << "{\\comment endMemberGroup}" << endl) if (hasHeader) decrementIndentLevel(); t << "}"; } void RTFGenerator::startSimpleSect(SectionTypes,const char *file,const char *anchor,const char *title) { DBG_RTF(t << "{\\comment (startSimpleSect)}" << endl) t << "{"; // ends at endDescList t << "{"; // ends at endDescTitle startBold(); newParagraph(); if (file) { writeObjectLink(0,file,anchor,title); } else { docify(title); } endBold(); t << "}"; newParagraph(); incrementIndentLevel(); t << rtf_Style_Reset << rtf_DList_DepthStyle(); } void RTFGenerator::endSimpleSect() { DBG_RTF(t << "{\\comment (endSimpleSect)}" << endl) newParagraph(); decrementIndentLevel(); m_omitParagraph = TRUE; t << "}"; } void RTFGenerator::startParamList(ParamListTypes,const char *title) { DBG_RTF(t << "{\\comment (startParamList)}" << endl) t << "{"; // ends at endParamList t << "{"; // ends at endDescTitle startBold(); newParagraph(); docify(title); endBold(); t << "}"; newParagraph(); incrementIndentLevel(); t << rtf_Style_Reset << rtf_DList_DepthStyle(); } void RTFGenerator::endParamList() { DBG_RTF(t << "{\\comment (endParamList)}" << endl) newParagraph(); decrementIndentLevel(); m_omitParagraph = TRUE; t << "}"; } void RTFGenerator::printDoc(DocNode *n,const char *langExt) { RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,langExt); n->accept(visitor); delete visitor; } void RTFGenerator::rtfwriteRuler_doubleline() { DBG_RTF(t << "{\\comment (rtfwriteRuler_doubleline)}" << endl) t << "{\\pard\\widctlpar\\brdrb\\brdrdb\\brdrw15\\brsp20 \\adjustright \\par}" << endl; } void RTFGenerator::rtfwriteRuler_emboss() { DBG_RTF(t << "{\\comment (rtfwriteRuler_emboss)}" << endl) t << "{\\pard\\widctlpar\\brdrb\\brdremboss\\brdrw15\\brsp20 \\adjustright \\par}" << endl; } void RTFGenerator::rtfwriteRuler_thick() { DBG_RTF(t << "{\\comment (rtfwriteRuler_thick)}" << endl) t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw75\\brsp20 \\adjustright \\par}" << endl; } void RTFGenerator::rtfwriteRuler_thin() { DBG_RTF(t << "{\\comment (rtfwriteRuler_thin)}" << endl) t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}" << endl; }