Orb/Doxygen/src/rtfgen.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * 
       
     4  *
       
     5  * Copyright (C) 1997-2008 by Parker Waechter & Dimitri van Heesch.
       
     6  *
       
     7  * Style sheet additions by Alexander Bartolich
       
     8  *
       
     9  * Permission to use, copy, modify, and distribute this software and its
       
    10  * documentation under the terms of the GNU General Public License is hereby
       
    11  * granted. No representations are made about the suitability of this software
       
    12  * for any purpose. It is provided "as is" without express or implied warranty.
       
    13  * See the GNU General Public License for more details.
       
    14  *
       
    15  * Documents produced by Doxygen are derivative works derived from the
       
    16  * input used in their production; they are not affected by this license.
       
    17  *
       
    18  */
       
    19 
       
    20 #include <stdlib.h>
       
    21 
       
    22 #include "qtbc.h"
       
    23 #include <qdir.h>
       
    24 #include <qregexp.h>
       
    25 
       
    26 #include "rtfgen.h"
       
    27 #include "config.h"
       
    28 #include "message.h"
       
    29 #include "doxygen.h"
       
    30 #include "util.h"
       
    31 #include "diagram.h"
       
    32 #include "language.h"
       
    33 #include "dot.h"
       
    34 #include "version.h"
       
    35 #include "pagedef.h"
       
    36 #include "rtfstyle.h"
       
    37 #include "rtfdocvisitor.h"
       
    38 #include "docparser.h"
       
    39 #include "dirdef.h"
       
    40 #include "vhdldocgen.h"
       
    41 
       
    42 //#define DBG_RTF(x) x;
       
    43 #define DBG_RTF(x)
       
    44 
       
    45 static QCString dateToRTFDateString()
       
    46 {
       
    47   const QDateTime &d = QDateTime::currentDateTime();
       
    48   QCString result;
       
    49   result.sprintf("\\yr%d\\mo%d\\dy%d\\hr%d\\min%d\\sec%d",
       
    50       d.date().year(), d.date().month(), d.date().day(),
       
    51       d.time().hour(),d.time().minute(),d.time().second());
       
    52   return result;
       
    53 } 
       
    54 
       
    55 RTFGenerator::RTFGenerator() : OutputGenerator()
       
    56 {
       
    57   dir=Config_getString("RTF_OUTPUT");
       
    58   col=0;
       
    59   //insideTabbing=FALSE;
       
    60   m_listLevel = 0;
       
    61   m_bstartedBody = FALSE;
       
    62   m_omitParagraph = FALSE;
       
    63   m_numCols = 0;
       
    64 }
       
    65 
       
    66 RTFGenerator::~RTFGenerator()
       
    67 {
       
    68 }
       
    69 
       
    70 //void RTFGenerator::append(const OutputGenerator *g)
       
    71 //{
       
    72 //  t << g->getContents();
       
    73 //  col+=((RTFGenerator *)g)->col;
       
    74 //  //insideTabbing=insideTabbing || ((RTFGenerator *)g)->insideTabbing;
       
    75 //  m_listLevel=((RTFGenerator *)g)->m_listLevel;
       
    76 //  m_omitParagraph=((RTFGenerator *)g)->m_omitParagraph;
       
    77 //  //printf("RTFGenerator::append(%s) insideTabbing=%s\n", g->getContents().data(),
       
    78 //  //    insideTabbing ? "TRUE" : "FALSE" );
       
    79 //}
       
    80 
       
    81 //OutputGenerator *RTFGenerator::copy()
       
    82 //{
       
    83 //  RTFGenerator *result = new RTFGenerator;
       
    84 //  //result->insideTabbing=insideTabbing;
       
    85 //  result->m_listLevel=m_listLevel;
       
    86 //  result->m_omitParagraph=m_omitParagraph;
       
    87 //  return result;
       
    88 //}
       
    89 
       
    90 void RTFGenerator::writeStyleSheetFile(QFile &file)
       
    91 {
       
    92   QTextStream t(&file);
       
    93   t << "# Generated by doxygen " << versionString << "\n\n";
       
    94   t << "# This file describes styles used for generating RTF output.\n";
       
    95   t << "# All text after a hash (#) is considered a comment and will be ignored.\n";
       
    96   t << "# Remove a hash to activate a line.\n\n";
       
    97 
       
    98   int i;
       
    99   for ( i=0 ; rtf_Style_Default[i].reference!=0 ; i++ )
       
   100   {
       
   101     t << "# " << rtf_Style_Default[i].name << " = "
       
   102               << rtf_Style_Default[i].reference
       
   103               << rtf_Style_Default[i].definition << endl;
       
   104   }
       
   105 }
       
   106 
       
   107 void RTFGenerator::writeExtensionsFile(QFile &file)
       
   108 {
       
   109   QTextStream t(&file);
       
   110   t << "# Generated by doxygen " << versionString << "\n\n";
       
   111   t << "# This file describes extensions used for generating RTF output.\n";
       
   112   t << "# All text after a hash (#) is considered a comment and will be ignored.\n";
       
   113   t << "# Remove a hash to activate a line.\n\n";
       
   114 
       
   115   t << "# Overrides the project title.\n";
       
   116 
       
   117   t << "#Title           = \n\n";
       
   118 
       
   119   t << "# Name of the company that produced this document.\n";
       
   120   t << "#Company         = \n\n";
       
   121 
       
   122   t << "# Filename of a company or project logo.\n";
       
   123   t << "#LogoFilename    = \n\n";
       
   124 
       
   125   t << "# Author of the document.\n";
       
   126   t << "#Author          = \n\n";
       
   127 
       
   128   t << "# Type of document (e.g. Design Specification, User Manual, etc.).\n";
       
   129   t << "#DocumentType    = \n\n";
       
   130 
       
   131   t << "# Document tracking number.\n";
       
   132   t << "#DocumentId      = \n\n";
       
   133 
       
   134   t << "# Name of the author's manager.\n";
       
   135   t << "# This field is not displayed in the document itself, but it is \n";
       
   136   t << "# available in the information block of the rtf file.  In Microsoft \n";
       
   137   t << "# Word, it is available under File:Properties.\n";
       
   138   t << "#Manager         = \n\n";
       
   139 
       
   140   t << "# Subject of the document.\n";
       
   141   t << "# This field is not displayed in the document itself, but it is \n";
       
   142   t << "# available in the information block of the rtf file.  In Microsoft \n";
       
   143   t << "# Word, it is available under File:Properties.\n";
       
   144   t << "#Subject         = \n\n";
       
   145 
       
   146   t << "# Comments regarding the document.\n";
       
   147   t << "# This field is not displayed in the document itself, but it is \n";
       
   148   t << "# available in the information block of the rtf file.  In Microsoft \n";
       
   149   t << "# Word, it is available under File:Properties.\n";
       
   150   t << "#Comments        = \n\n";
       
   151 
       
   152   t << "# Keywords associated with the document.\n";
       
   153   t << "# This field is not displayed in the document itself, but it is \n";
       
   154   t << "# available in the information block of the rtf file.  In Microsoft \n";
       
   155   t << "# Word, it is available under File:Properties.\n";
       
   156   t << "#Keywords        = \n\n";
       
   157 }
       
   158 
       
   159 
       
   160 void RTFGenerator::init()
       
   161 {
       
   162   QCString dir=Config_getString("RTF_OUTPUT");
       
   163   QDir d(dir);
       
   164   if (!d.exists() && !d.mkdir(dir))
       
   165   {
       
   166     err("Could not create output directory %s\n",dir.data());
       
   167     exit(1);
       
   168   }
       
   169   rtf_Style.setAutoDelete(TRUE);
       
   170 
       
   171   // first duplicate strings of rtf_Style_Default
       
   172   const struct Rtf_Style_Default* def = rtf_Style_Default;
       
   173   while(def->reference != 0)
       
   174   {
       
   175     if (def->definition == 0)
       
   176       err("Internal error: rtf_Style_Default[%s] has no definition.\n", def->name);
       
   177     StyleData* styleData = new StyleData(def->reference, def->definition);
       
   178     rtf_Style.insert(def->name, styleData);
       
   179     def++;
       
   180   }
       
   181 
       
   182   // overwrite some (or all) definitions from file
       
   183   QCString &rtfStyleSheetFile = Config_getString("RTF_STYLESHEET_FILE");
       
   184   if (!rtfStyleSheetFile.isEmpty())
       
   185   {
       
   186     loadStylesheet(rtfStyleSheetFile, rtf_Style);
       
   187   }
       
   188 
       
   189   // If user has defined an extension file, load its contents.
       
   190   QCString &rtfExtensionsFile = Config_getString("RTF_EXTENSIONS_FILE");
       
   191   if (!rtfExtensionsFile.isEmpty())
       
   192   {
       
   193     loadExtensions(rtfExtensionsFile);
       
   194   }
       
   195 
       
   196   createSubDirs(d);
       
   197 }
       
   198 
       
   199 static QCString makeIndexName(const char *s,int i)
       
   200 {
       
   201   QCString result=s;
       
   202   result+=(char)(i+'0');
       
   203   return result;
       
   204 }
       
   205 
       
   206 void RTFGenerator::beginRTFDocument()
       
   207 {
       
   208   /* all the included RTF files should begin with the
       
   209    * same header
       
   210    */
       
   211   t <<"{\\rtf1\\ansi\\ansicpg" << theTranslator->trRTFansicp();
       
   212   t <<"\\uc1 \\deff0\\deflang1033\\deflangfe1033\n";
       
   213 
       
   214   DBG_RTF(t <<"{\\comment Begining font list}\n")
       
   215   t <<"{\\fonttbl ";
       
   216   t <<"{\\f0\\froman\\fcharset" << theTranslator->trRTFCharSet();
       
   217   t <<"\\fprq2{\\*\\panose 02020603050405020304}Times New Roman;}\n";
       
   218   t <<"{\\f1\\fswiss\\fcharset" << theTranslator->trRTFCharSet();
       
   219   t <<"\\fprq2{\\*\\panose 020b0604020202020204}Arial;}\n";
       
   220   t <<"{\\f2\\fmodern\\fcharset" << theTranslator->trRTFCharSet();
       
   221   t <<"\\fprq1{\\*\\panose 02070309020205020404}Courier New;}\n";
       
   222   t <<"{\\f3\\froman\\fcharset2\\fprq2{\\*\\panose 05050102010706020507}Symbol;}\n";
       
   223   t <<"}\n";
       
   224   DBG_RTF(t <<"{\\comment begin colors}\n")
       
   225   t <<"{\\colortbl;";
       
   226   t <<"\\red0\\green0\\blue0;";
       
   227   t <<"\\red0\\green0\\blue255;";
       
   228   t <<"\\red0\\green255\\blue255;";
       
   229   t <<"\\red0\\green255\\blue0;";
       
   230   t <<"\\red255\\green0\\blue255;";
       
   231   t <<"\\red255\\green0\\blue0;";
       
   232   t <<"\\red255\\green255\\blue0;";
       
   233   t <<"\\red255\\green255\\blue255;";
       
   234   t <<"\\red0\\green0\\blue128;";
       
   235   t <<"\\red0\\green128\\blue128;";
       
   236   t <<"\\red0\\green128\\blue0;";
       
   237   t <<"\\red128\\green0\\blue128;";
       
   238   t <<"\\red128\\green0\\blue0;";
       
   239   t <<"\\red128\\green128\\blue0;";
       
   240   t <<"\\red128\\green128\\blue128;";
       
   241   t <<"\\red192\\green192\\blue192;}" << endl;
       
   242 
       
   243   DBG_RTF(t <<"{\\comment Beginning style list}\n")
       
   244   t <<"{\\stylesheet\n";
       
   245   t <<"{\\widctlpar\\adjustright \\fs20\\cgrid \\snext0 Normal;}\n";
       
   246 
       
   247   // sort styles ascending by \s-number via an intermediate QArray
       
   248   QArray<const StyleData*> array(128);
       
   249   array.fill(0);
       
   250   QDictIterator<StyleData> iter(rtf_Style);
       
   251   const StyleData* style;
       
   252   for(; (style = iter.current()); ++iter)
       
   253   {
       
   254     unsigned index = style->index;
       
   255     unsigned size = array.size();
       
   256     if (index >= size)
       
   257     {
       
   258       // +1 to add at least one element, then align up to multiple of 8
       
   259       array.resize((index + 1 + 7) & ~7);
       
   260       array.fill(0, size);
       
   261       ASSERT(index < array.size());
       
   262     }
       
   263     if (array.at(index) != 0)
       
   264     {
       
   265       QCString key(convertToQCString(iter.currentKey()));
       
   266       msg("Style '%s' redefines \\s%d.\n", key.data(), index);
       
   267     }
       
   268     array.at(index) = style;
       
   269   }
       
   270 
       
   271   // write array elements
       
   272   unsigned size = array.size();
       
   273   for(unsigned i = 0; i < size; i++)
       
   274   {
       
   275     const StyleData* style = array.at(i);
       
   276     if (style != 0)
       
   277       t <<"{" << style->reference << style->definition << ";}\n";
       
   278   }
       
   279 
       
   280   t <<"}" << endl;
       
   281   // this comment is needed for postprocessing!
       
   282   t <<"{\\comment begin body}" << endl;
       
   283 
       
   284 }
       
   285 
       
   286 void RTFGenerator::beginRTFChapter()
       
   287 {
       
   288   t <<"\n";
       
   289   DBG_RTF(t << "{\\comment BeginRTFChapter}\n")
       
   290   t << rtf_Style_Reset;
       
   291 
       
   292   // if we are compact, no extra page breaks...
       
   293   if (Config_getBool("COMPACT_RTF"))
       
   294   {
       
   295     //      t <<"\\sect\\sectd\\sbknone\n";
       
   296     t <<"\\sect\\sbknone\n";
       
   297     rtfwriteRuler_thick();
       
   298   }
       
   299   else
       
   300     t <<"\\sect\\sbkpage\n";
       
   301   //t <<"\\sect\\sectd\\sbkpage\n";
       
   302 
       
   303   t << rtf_Style["Heading1"]->reference << "\n";
       
   304 }
       
   305 
       
   306 void RTFGenerator::beginRTFSection()
       
   307 {
       
   308   t <<"\n";
       
   309   DBG_RTF(t << "{\\comment BeginRTFSection}\n")
       
   310   t << rtf_Style_Reset;
       
   311 
       
   312   // if we are compact, no extra page breaks...
       
   313   if (Config_getBool("COMPACT_RTF"))
       
   314   {
       
   315     //      t <<"\\sect\\sectd\\sbknone\n";
       
   316     t <<"\\sect\\sbknone\n";
       
   317     rtfwriteRuler_emboss();
       
   318   }
       
   319   else
       
   320     t <<"\\sect\\sbkpage\n";
       
   321   //t <<"\\sect\\sectd\\sbkpage\n";
       
   322 
       
   323   t << rtf_Style["Heading2"]->reference << "\n";
       
   324 }
       
   325 
       
   326 void RTFGenerator::startFile(const char *name,const char *,const char *)
       
   327 {
       
   328   setEncoding(QCString().sprintf("CP%s",theTranslator->trRTFansicp().data()));
       
   329   QCString fileName=name;
       
   330   relPath = relativePathToRoot(fileName);
       
   331 
       
   332   if (fileName.right(4)!=".rtf" ) fileName+=".rtf";
       
   333   startPlainFile(fileName);
       
   334   beginRTFDocument();
       
   335 }
       
   336 
       
   337 void RTFGenerator::endFile()
       
   338 {
       
   339   DBG_RTF(t << "{\\comment endFile}\n")
       
   340   t << "}";
       
   341 
       
   342   endPlainFile();
       
   343 }
       
   344 
       
   345 void RTFGenerator::startProjectNumber()
       
   346 {
       
   347   DBG_RTF(t <<"{\\comment startProjectNumber }" << endl)
       
   348   t << " ";
       
   349 }
       
   350 
       
   351 void RTFGenerator::endProjectNumber()
       
   352 {
       
   353   DBG_RTF(t <<"{\\comment endProjectNumber }" << endl)
       
   354 }
       
   355 
       
   356 void RTFGenerator::startIndexSection(IndexSections is)
       
   357 {
       
   358   //QCString paperName;
       
   359 
       
   360   m_listLevel = 0;
       
   361 
       
   362   switch (is)
       
   363   {
       
   364     case isTitlePageStart:
       
   365       // basic RTFstart
       
   366       // get readyfor author etc
       
   367 
       
   368       t << "{\\info \n";
       
   369       t << "{\\title {\\comment ";
       
   370       break;
       
   371     case isTitlePageAuthor:
       
   372       t << "}\n";
       
   373       if (rtf_subject)      t << "{\\subject "  << rtf_subject      << "}\n";
       
   374       if (rtf_comments)     t << "{\\comment "  << rtf_comments     << "}\n";
       
   375       if (rtf_company)      t << "{\\company "  << rtf_company      << "}\n";
       
   376       if (rtf_author)       t << "{\\author "   << rtf_author       << "}\n";
       
   377       if (rtf_manager)      t << "{\\manager "  << rtf_manager      << "}\n";
       
   378       if (rtf_documentType) t << "{\\category " << rtf_documentType << "}\n";
       
   379       if (rtf_keywords)     t << "{\\keywords " << rtf_keywords     << "}\n";
       
   380       t << "{\\comment ";
       
   381       break;
       
   382     case isMainPage:
       
   383       //Introduction
       
   384       beginRTFChapter();
       
   385       break;
       
   386     //case isPackageIndex:
       
   387     //  //Package Index
       
   388     //  beginRTFChapter();
       
   389     //  break;
       
   390     case isModuleIndex:
       
   391       //Module Index
       
   392       beginRTFChapter();
       
   393       break;
       
   394     case isDirIndex:
       
   395       //Directory Index
       
   396       beginRTFChapter();
       
   397       break;
       
   398     case isNamespaceIndex:
       
   399       //Namespace Index
       
   400       beginRTFChapter();
       
   401       break;
       
   402     case isClassHierarchyIndex:
       
   403       //Hierarchical Index
       
   404       DBG_RTF(t << "{\\comment start classhierarchy}\n")
       
   405       beginRTFChapter();
       
   406       break;
       
   407     case isCompoundIndex:
       
   408       //Annotated Compound Index
       
   409       beginRTFChapter();
       
   410       break;
       
   411     case isFileIndex:
       
   412       //Annotated File Index
       
   413       beginRTFChapter();
       
   414       break;
       
   415     case isPageIndex:
       
   416       //Related Page Index
       
   417       beginRTFChapter();
       
   418       break;
       
   419     case isModuleDocumentation:
       
   420       {
       
   421         //Module Documentation
       
   422         GroupSDict::Iterator gli(*Doxygen::groupSDict);
       
   423         GroupDef *gd;
       
   424         bool found=FALSE;
       
   425         for (gli.toFirst();(gd=gli.current()) && !found;++gli)
       
   426         {
       
   427           if (!gd->isReference())
       
   428           {
       
   429             beginRTFChapter();
       
   430             found=TRUE;
       
   431           }
       
   432         }
       
   433       }
       
   434       break;
       
   435     case isDirDocumentation:
       
   436       {
       
   437         //Directory Documentation
       
   438         SDict<DirDef>::Iterator dli(*Doxygen::directories);
       
   439         DirDef *dd;
       
   440         bool found=FALSE;
       
   441         for (dli.toFirst();(dd=dli.current()) && !found;++dli)
       
   442         {
       
   443           if (dd->isLinkableInProject())
       
   444           {
       
   445             beginRTFChapter();
       
   446             found=TRUE;
       
   447           }
       
   448         }
       
   449       }
       
   450       break;
       
   451     case isNamespaceDocumentation:
       
   452       {
       
   453         // Namespace Documentation
       
   454         NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
       
   455         NamespaceDef *nd;
       
   456         bool found=FALSE;
       
   457         for (nli.toFirst();(nd=nli.current()) && !found;++nli)
       
   458         {
       
   459           if (nd->isLinkableInProject())
       
   460           {
       
   461             beginRTFChapter();
       
   462             found=TRUE;
       
   463           }
       
   464         }
       
   465       }
       
   466       break;
       
   467     case isClassDocumentation:
       
   468       {
       
   469         //Compound Documentation
       
   470         ClassSDict::Iterator cli(*Doxygen::classSDict);
       
   471         ClassDef *cd=0;
       
   472         bool found=FALSE;
       
   473         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
       
   474         {
       
   475           if (cd->isLinkableInProject() && cd->templateMaster()==0)
       
   476           {
       
   477             beginRTFChapter();
       
   478             found=TRUE;
       
   479           }
       
   480         }
       
   481       }
       
   482       break;
       
   483     case isFileDocumentation:
       
   484       {
       
   485         //File Documentation
       
   486         bool isFirst=TRUE;
       
   487         FileName *fn=Doxygen::inputNameList->first();
       
   488         while (fn)
       
   489         {
       
   490           FileDef *fd=fn->first();
       
   491           while (fd)
       
   492           {
       
   493             if (fd->isLinkableInProject())
       
   494             {
       
   495               if (isFirst)
       
   496               {
       
   497                 beginRTFChapter();
       
   498                 isFirst=FALSE;
       
   499                 break;
       
   500               }
       
   501             }
       
   502             fd=fn->next();
       
   503           }
       
   504           fn=Doxygen::inputNameList->next();
       
   505         }
       
   506       }
       
   507       break;
       
   508     case isExampleDocumentation:
       
   509       {
       
   510         //Example Documentation
       
   511         beginRTFChapter();
       
   512       }
       
   513       break;
       
   514     case isPageDocumentation:
       
   515       {
       
   516         //Page Documentation
       
   517         beginRTFChapter();
       
   518       }
       
   519       break;
       
   520     case isPageDocumentation2:
       
   521       {
       
   522         t << "{\\tc \\v ";
       
   523       }
       
   524       break;
       
   525     case isEndIndex:
       
   526       break;
       
   527   }
       
   528 }
       
   529 
       
   530 void RTFGenerator::endIndexSection(IndexSections is)
       
   531 {
       
   532   bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN");
       
   533   bool vhdlOpt    = Config_getBool("OPTIMIZE_OUTPUT_VHDL");  
       
   534   switch (is)
       
   535   {
       
   536     case isTitlePageStart:
       
   537       if (rtf_title)
       
   538         // User has overridden document title in extensions file
       
   539         t << "}" << rtf_title;
       
   540       else
       
   541         t << "}" << Config_getString("PROJECT_NAME");
       
   542       break;
       
   543     case isTitlePageAuthor:
       
   544       {
       
   545         t << "Doxgyen. }\n";
       
   546         t << "{\\creatim " << dateToRTFDateString() << "}\n}";
       
   547         DBG_RTF(t << "{\\comment end of infoblock}\n");
       
   548         // setup for this section
       
   549         t << rtf_Style_Reset <<"\n";
       
   550         t <<"\\sectd\\pgnlcrm\n";
       
   551         t <<"{\\footer "<<rtf_Style["Footer"]->reference << "{\\chpgn}}\n";
       
   552         // the title entry
       
   553         DBG_RTF(t << "{\\comment begin title page}\n")
       
   554 
       
   555 
       
   556         t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to title style
       
   557 
       
   558         t << "\\vertalc\\qc\\par\\par\\par\\par\\par\\par\\par\n";
       
   559         if (rtf_logoFilename)
       
   560         {
       
   561           t << "{\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"" << rtf_logoFilename;
       
   562           t << "\" \\\\d \\\\*MERGEFORMAT} {\\fldrslt IMAGE }}\\par\\par\n";
       
   563         }
       
   564         if (rtf_company)
       
   565         {
       
   566           t << rtf_company << "\\par\\par\n";
       
   567         }
       
   568 
       
   569         t << rtf_Style_Reset << rtf_Style["Title"]->reference << endl; // set to title style
       
   570         t << "{\\field\\fldedit {\\*\\fldinst TITLE \\\\*MERGEFORMAT}{\\fldrslt TITLE}}\\par" << endl;
       
   571 
       
   572         t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to title style
       
   573         t << "\\par\n";
       
   574         if (rtf_documentType)
       
   575         {
       
   576           t << rtf_documentType << "\\par\n";
       
   577         }
       
   578         if (rtf_documentId)
       
   579         {
       
   580           t << rtf_documentId << "\\par\n";
       
   581         }
       
   582         t << "\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\\par\n";
       
   583 
       
   584         t << rtf_Style_Reset << rtf_Style["SubTitle"]->reference << endl; // set to subtitle style
       
   585         t << "{\\field\\fldedit {\\*\\fldinst AUTHOR \\\\*MERGEFORMAT}{\\fldrslt AUTHOR}}\\par" << endl;
       
   586         t << "Version " << Config_getString("PROJECT_NUMBER") << "\\par";
       
   587         t << "{\\field\\fldedit {\\*\\fldinst CREATEDATE \\\\*MERGEFORMAT}"
       
   588           "{\\fldrslt CREATEDATE}}\\par"<<endl;
       
   589         t << "\\page\\page";
       
   590         DBG_RTF(t << "{\\comment End title page}" << endl)
       
   591 
       
   592         // table of contents section
       
   593         DBG_RTF(t << "{\\comment Table of contents}\n")
       
   594         t << "\\vertalt\n";
       
   595         t << rtf_Style_Reset << endl;
       
   596         t << rtf_Style["Heading1"]->reference;
       
   597         t << theTranslator->trRTFTableOfContents() << "\\par"<< endl;
       
   598         t << rtf_Style_Reset << "\\par" << endl;
       
   599         t << "{\\field\\fldedit {\\*\\fldinst TOC \\\\f \\\\*MERGEFORMAT}{\\fldrslt Table of contents}}\\par\n";
       
   600         t << rtf_Style_Reset << endl;
       
   601       }
       
   602       break;
       
   603     case isMainPage:
       
   604       t << "\\par " << rtf_Style_Reset << endl;
       
   605       if (!Doxygen::mainPage || Doxygen::mainPage->title().isEmpty())
       
   606       {
       
   607         t << "{\\tc \\v " << theTranslator->trMainPage() << "}"<< endl;
       
   608       }
       
   609       else
       
   610       {
       
   611         t << "{\\tc \\v " << substitute(Doxygen::mainPage->title(),"%","") << "}"<< endl;
       
   612       }
       
   613       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   614       if (Config_getBool("GENERATE_TREEVIEW")) t << "main"; else t << "index";
       
   615       t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   616       break;
       
   617     //case isPackageIndex:
       
   618     //  t << "\\par " << rtf_Style_Reset << endl;
       
   619     //  t << "{\\tc \\v " << theTranslator->trPackageList() << "}"<< endl;
       
   620     //  t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"packages.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   621     //  break;
       
   622     case isModuleIndex:
       
   623       t << "\\par " << rtf_Style_Reset << endl;
       
   624       t << "{\\tc \\v " << theTranslator->trModuleIndex() << "}"<< endl;
       
   625       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"modules.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   626       break;
       
   627     case isDirIndex:
       
   628       t << "\\par " << rtf_Style_Reset << endl;
       
   629       t << "{\\tc \\v " << theTranslator->trDirIndex() << "}"<< endl;
       
   630       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"dirs.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   631       break;
       
   632     case isNamespaceIndex:
       
   633       t << "\\par " << rtf_Style_Reset << endl;
       
   634       if (fortranOpt)
       
   635       {
       
   636           t << "{\\tc \\v " << theTranslator->trModulesIndex() << "}"<< endl;
       
   637       }
       
   638       else
       
   639       {
       
   640           t << "{\\tc \\v " << theTranslator->trNamespaceIndex() << "}"<< endl;
       
   641       }
       
   642       
       
   643       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"namespaces.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   644       break;
       
   645     case isClassHierarchyIndex:
       
   646       t << "\\par " << rtf_Style_Reset << endl;
       
   647       t << "{\\tc \\v " << theTranslator->trHierarchicalIndex() << "}"<< endl;
       
   648       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"hierarchy.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   649       break;
       
   650     case isCompoundIndex:
       
   651       t << "\\par " << rtf_Style_Reset << endl;
       
   652       if (fortranOpt)
       
   653       {
       
   654         t << "{\\tc \\v " << theTranslator->trCompoundIndexFortran() << "}"<< endl;
       
   655       }
       
   656       else if (vhdlOpt)
       
   657       {
       
   658         t << "{\\tc \\v " << VhdlDocGen::trDesignUnitIndex() << "}"<< endl;
       
   659       }
       
   660       else
       
   661       {
       
   662         t << "{\\tc \\v " << theTranslator->trCompoundIndex() << "}"<< endl;
       
   663       }
       
   664       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"annotated.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   665       break;
       
   666     case isFileIndex:
       
   667       t << "\\par " << rtf_Style_Reset << endl;
       
   668       t << "{\\tc \\v " << theTranslator->trFileIndex() << "}"<< endl;
       
   669       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"files.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   670       break;
       
   671     case isPageIndex:
       
   672       t << "\\par " << rtf_Style_Reset << endl;
       
   673       t << "{\\tc \\v " << theTranslator->trPageIndex() << "}"<< endl;
       
   674       t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"pages.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   675       break;
       
   676     case isModuleDocumentation:
       
   677       {
       
   678         GroupSDict::Iterator gli(*Doxygen::groupSDict);
       
   679         GroupDef *gd;
       
   680         t << "{\\tc \\v " << theTranslator->trModuleDocumentation() << "}"<< endl;
       
   681         for (gli.toFirst();(gd=gli.current());++gli)
       
   682         {
       
   683           if (!gd->isReference())
       
   684           {
       
   685             t << "\\par " << rtf_Style_Reset << endl;
       
   686             t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   687             t << gd->getOutputFileBase();
       
   688             t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   689           }
       
   690         }
       
   691       }
       
   692       break;
       
   693     case isDirDocumentation:
       
   694       {
       
   695         SDict<DirDef>::Iterator dli(*Doxygen::directories);
       
   696         DirDef *dd;
       
   697         t << "{\\tc \\v " << theTranslator->trDirDocumentation() << "}"<< endl;
       
   698         for (dli.toFirst();(dd=dli.current());++dli)
       
   699         {
       
   700           if (dd->isLinkableInProject())
       
   701           {
       
   702             t << "\\par " << rtf_Style_Reset << endl;
       
   703             t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   704             t << dd->getOutputFileBase();
       
   705             t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   706           }
       
   707         }
       
   708       }
       
   709       break;
       
   710     case isNamespaceDocumentation:
       
   711       {
       
   712         NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
       
   713         NamespaceDef *nd;
       
   714         bool found=FALSE;
       
   715         for (nli.toFirst();(nd=nli.current()) && !found;++nli)
       
   716         {
       
   717           if (nd->isLinkableInProject())
       
   718           {
       
   719             t << "\\par " << rtf_Style_Reset << endl;
       
   720             t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   721             t << nd->getOutputFileBase();
       
   722             t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   723             found=TRUE;
       
   724           }
       
   725         }
       
   726         while ((nd=nli.current()))
       
   727         {
       
   728           if (nd->isLinkableInProject())
       
   729           {
       
   730             t << "\\par " << rtf_Style_Reset << endl;
       
   731             beginRTFSection();
       
   732             t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   733             t << nd->getOutputFileBase();
       
   734             t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   735           }
       
   736           ++nli;
       
   737         }
       
   738       }
       
   739       break;
       
   740     case isClassDocumentation:
       
   741       {
       
   742         ClassSDict::Iterator cli(*Doxygen::classSDict);
       
   743         ClassDef *cd=0;
       
   744         bool found=FALSE;
       
   745         if (fortranOpt)
       
   746         {
       
   747           t << "{\\tc \\v " << theTranslator->trTypeDocumentation() << "}"<< endl;
       
   748         }
       
   749         else
       
   750         {
       
   751           t << "{\\tc \\v " << theTranslator->trClassDocumentation() << "}"<< endl;
       
   752         }
       
   753         for (cli.toFirst();(cd=cli.current()) && !found;++cli)
       
   754         {
       
   755           if (cd->isLinkableInProject() && cd->templateMaster()==0)
       
   756           {
       
   757             t << "\\par " << rtf_Style_Reset << endl;
       
   758             t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   759             t << cd->getOutputFileBase();
       
   760             t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   761             found=TRUE;
       
   762           }
       
   763         }
       
   764         for (;(cd=cli.current());++cli)
       
   765         {
       
   766           if (cd->isLinkableInProject() && cd->templateMaster()==0)
       
   767           {
       
   768             t << "\\par " << rtf_Style_Reset << endl;
       
   769             beginRTFSection();
       
   770             t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   771             t << cd->getOutputFileBase();
       
   772             t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   773           }
       
   774         }
       
   775       }
       
   776       break;
       
   777     case isFileDocumentation:
       
   778       {
       
   779         bool isFirst=TRUE;
       
   780         FileName *fn=Doxygen::inputNameList->first();
       
   781 
       
   782         t << "{\\tc \\v " << theTranslator->trFileDocumentation() << "}"<< endl;
       
   783         while (fn)
       
   784         {
       
   785           FileDef *fd=fn->first();
       
   786           while (fd)
       
   787           {
       
   788             if (fd->isLinkableInProject())
       
   789             {
       
   790               if (isFirst)
       
   791               {
       
   792                 t << "\\par " << rtf_Style_Reset << endl;
       
   793                 t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   794                 t << fd->getOutputFileBase();
       
   795                 t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   796                 isFirst=FALSE;
       
   797               }
       
   798               else
       
   799               {
       
   800                 t << "\\par " << rtf_Style_Reset << endl;
       
   801                 beginRTFSection();
       
   802                 t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   803                 t << fd->getOutputFileBase();
       
   804                 t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   805               }
       
   806             }
       
   807             fd=fn->next();
       
   808           }
       
   809           fn=Doxygen::inputNameList->next();
       
   810         }
       
   811       }
       
   812       break;
       
   813     case isExampleDocumentation:
       
   814       {
       
   815         //t << "}\n";
       
   816         t << "{\\tc \\v " << theTranslator->trExampleDocumentation() << "}"<< endl;
       
   817         PageSDict::Iterator pdi(*Doxygen::exampleSDict);
       
   818         PageDef *pd=pdi.toFirst();
       
   819         if (pd)
       
   820         {
       
   821           t << "\\par " << rtf_Style_Reset << endl;
       
   822           t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   823           t << pd->getOutputFileBase();
       
   824           t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   825         }
       
   826         for (++pdi;(pd=pdi.current());++pdi)
       
   827         {
       
   828           t << "\\par " << rtf_Style_Reset << endl;
       
   829           beginRTFSection();
       
   830           t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   831           t << pd->getOutputFileBase();
       
   832           t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   833         }
       
   834       }
       
   835       break;
       
   836     case isPageDocumentation:
       
   837       {
       
   838 //#error "fix me in the same way as the latex index..."
       
   839         //t << "{\\tc \\v " << theTranslator->trPageDocumentation() << "}"<< endl;
       
   840         //t << "}"<< endl;
       
   841         //PageSDict::Iterator pdi(*Doxygen::pageSDict);
       
   842         //PageDef *pd=pdi.toFirst();
       
   843         //bool first=TRUE;
       
   844         //for (pdi.toFirst();(pd=pdi.current());++pdi)
       
   845         //{
       
   846         //  if (!pd->getGroupDef() && !pd->isReference())
       
   847         //  {
       
   848         //    if (first) t << "\\par " << rtf_Style_Reset << endl;
       
   849         //    t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   850         //    t << pd->getOutputFileBase();
       
   851         //    t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   852         //    first=FALSE;
       
   853         //  }
       
   854         //}
       
   855       }
       
   856       break;
       
   857     case isPageDocumentation2:
       
   858       {
       
   859         t << "}";
       
   860         t << "\\par " << rtf_Style_Reset << endl;
       
   861       }
       
   862       break;
       
   863     case isEndIndex:
       
   864       beginRTFChapter();
       
   865       t << rtf_Style["Heading1"]->reference;
       
   866       t << theTranslator->trRTFGeneralIndex() << "\\par "<< endl;
       
   867       t << rtf_Style_Reset << endl;
       
   868       t << "{\\tc \\v " << theTranslator->trRTFGeneralIndex() << "}" << endl;
       
   869       t << "{\\field\\fldedit {\\*\\fldinst INDEX \\\\c2 \\\\*MERGEFORMAT}{\\fldrslt INDEX}}\n";
       
   870 
       
   871       break;
       
   872    }
       
   873 }
       
   874 
       
   875 void RTFGenerator::writePageLink(const char *name,bool first)
       
   876 {
       
   877    if (first) t << "\\par " << rtf_Style_Reset << endl;
       
   878    t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \"";
       
   879    t << name;
       
   880    t << ".rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n";
       
   881 }
       
   882 
       
   883 void RTFGenerator::lastIndexPage()
       
   884 {
       
   885   DBG_RTF(t <<"{\\comment Beginning Body of RTF Document}\n")
       
   886   // end page and setup for rest of document
       
   887   t <<"\\sect \\sbkpage \\pgndec \\pgnrestart\n";
       
   888   t <<"\\sect \\sectd \\sbknone\n";
       
   889 
       
   890   // set new footer with arabic numbers
       
   891   t <<"{\\footer "<< rtf_Style["Footer"]->reference << "{\\chpgn}}\n";
       
   892   //t << rtf_Style["Heading1"]->reference << "\n";
       
   893 
       
   894 }
       
   895 
       
   896 void RTFGenerator::writeStyleInfo(int)
       
   897 {
       
   898 }
       
   899 
       
   900 void RTFGenerator::lineBreak(const char *)
       
   901 {
       
   902   DBG_RTF(t << "{\\comment (lineBreak)}"    << endl)
       
   903   t << "\\par" << endl;
       
   904   m_omitParagraph = TRUE;
       
   905 }
       
   906 
       
   907 void RTFGenerator::writeString(const char *text)
       
   908 {
       
   909   t << text;
       
   910 }
       
   911 
       
   912 void RTFGenerator::startIndexList()
       
   913 {
       
   914   DBG_RTF(t << "{\\comment (startIndexList)}" << endl)
       
   915   t << "{" << endl;
       
   916   t << "\\par" << endl;
       
   917   incrementIndentLevel();
       
   918   t << rtf_Style_Reset << rtf_LCList_DepthStyle() << endl;
       
   919   m_omitParagraph = TRUE;
       
   920 }
       
   921 
       
   922 void RTFGenerator::endIndexList()
       
   923 {
       
   924   DBG_RTF(t << "{\\comment (endIndexList)}" << endl)
       
   925   if (!m_omitParagraph)
       
   926   {
       
   927     t << "\\par";
       
   928     m_omitParagraph = TRUE;
       
   929   }
       
   930   t << "}";
       
   931   decrementIndentLevel();
       
   932 }
       
   933 
       
   934 /*! start bullet list */
       
   935 void RTFGenerator::startItemList()
       
   936 {
       
   937   newParagraph();
       
   938   DBG_RTF(t << "{\\comment (startItemList level=" << m_listLevel << ") }" << endl)
       
   939   t << "{";
       
   940   incrementIndentLevel();
       
   941   rtf_listItemInfo[m_listLevel].isEnum = FALSE;
       
   942 }
       
   943 
       
   944 /*! end bullet list */
       
   945 void RTFGenerator::endItemList()
       
   946 {
       
   947   newParagraph();
       
   948   DBG_RTF(t << "{\\comment (endItemList level=" << m_listLevel << ")}" << endl)
       
   949   t << "}";
       
   950   decrementIndentLevel();
       
   951   m_omitParagraph = TRUE;
       
   952 }
       
   953 
       
   954 ///*! start enumeration list */
       
   955 //void RTFGenerator::startEnumList()  // starts an enumeration list
       
   956 //{
       
   957 //  DBG_RTF(t << "{\\comment (startEnumList)}" << endl)
       
   958 //  t << "{" << endl;
       
   959 //  incrementIndentLevel();
       
   960 //  rtf_listItemInfo[m_listLevel].isEnum = TRUE;
       
   961 //  rtf_listItemInfo[m_listLevel].number = 1;
       
   962 //}
       
   963 //
       
   964 ///*! end enumeration list */
       
   965 //void RTFGenerator::endEnumList()
       
   966 //{
       
   967 //  newParagraph();
       
   968 //  DBG_RTF(t << "{\\comment (endEnumList)}" << endl)
       
   969 //  t << "}";
       
   970 //  decrementIndentLevel();
       
   971 //  m_omitParagraph = TRUE;
       
   972 //}
       
   973 
       
   974 /*! write bullet or enum item */
       
   975 void RTFGenerator::startItemListItem()
       
   976 {
       
   977   DBG_RTF(t << "{\\comment (startItemListItem)}" << endl)
       
   978   newParagraph();
       
   979   t << rtf_Style_Reset;
       
   980   if (rtf_listItemInfo[m_listLevel].isEnum)
       
   981   {
       
   982     t << rtf_EList_DepthStyle() << endl;
       
   983     t << rtf_listItemInfo[m_listLevel].number << ".\\tab ";
       
   984     rtf_listItemInfo[m_listLevel].number++;
       
   985   }
       
   986   else
       
   987   {
       
   988     t << rtf_BList_DepthStyle() << endl;
       
   989   }
       
   990   m_omitParagraph = TRUE;
       
   991 }
       
   992 
       
   993 void RTFGenerator::endItemListItem()
       
   994 {
       
   995   DBG_RTF(t << "{\\comment (endItemListItem)}" << endl)
       
   996 }
       
   997 
       
   998 void RTFGenerator::startIndexItem(const char *,const char *)
       
   999 {
       
  1000   DBG_RTF(t << "{\\comment (startIndexItem)}" << endl)
       
  1001 
       
  1002   if (!m_omitParagraph)
       
  1003   {
       
  1004     t << "\\par" << endl;
       
  1005     m_omitParagraph = TRUE;
       
  1006   }
       
  1007 }
       
  1008 
       
  1009 void RTFGenerator::endIndexItem(const char *ref,const char *fn)
       
  1010 {
       
  1011   DBG_RTF(t << "{\\comment (endIndexItem)}" << endl)
       
  1012   if (!ref && fn)
       
  1013   {
       
  1014     t << "\\tab ";
       
  1015     writeRTFReference(fn);
       
  1016     t << endl;
       
  1017   }
       
  1018   else
       
  1019   {
       
  1020     t << endl;
       
  1021   }
       
  1022   m_omitParagraph = TRUE;
       
  1023 }
       
  1024 
       
  1025 //void RTFGenerator::writeIndexFileItem(const char *,const char *text)
       
  1026 //{
       
  1027 //  t << "\\item\\contentsline{section}{";
       
  1028 //  docify(text);
       
  1029 //  t << "}{\\pageref{" << text << "}}" << endl;
       
  1030 //}
       
  1031 
       
  1032 void RTFGenerator::startHtmlLink(const char *url)
       
  1033 {
       
  1034 
       
  1035   if (Config_getBool("RTF_HYPERLINKS"))
       
  1036   {
       
  1037     t << "{\\field {\\*\\fldinst { HYPERLINK  \\\\l \"";
       
  1038     t << url;
       
  1039     t << "\" }{}";
       
  1040     t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
       
  1041   }
       
  1042   else
       
  1043   {
       
  1044     startTypewriter();
       
  1045   }
       
  1046 }
       
  1047 
       
  1048 void RTFGenerator::endHtmlLink()
       
  1049 {
       
  1050   if (Config_getBool("RTF_HYPERLINKS"))
       
  1051   {
       
  1052     t << "}}}" << endl;
       
  1053   }
       
  1054   else
       
  1055   {
       
  1056     endTypewriter();
       
  1057   }
       
  1058 }
       
  1059 
       
  1060 //void RTFGenerator::writeMailLink(const char *url)
       
  1061 //{
       
  1062 //  startTypewriter();
       
  1063 //  docify(url);
       
  1064 //  endTypewriter();
       
  1065 //}
       
  1066 
       
  1067 void RTFGenerator::writeStartAnnoItem(const char *,const char *f,
       
  1068     const char *path,const char *name)
       
  1069 {
       
  1070   DBG_RTF(t << "{\\comment (writeStartAnnoItem)}" << endl)
       
  1071   t << "{\\b ";
       
  1072   if (path) docify(path);
       
  1073   if (f && Config_getBool("RTF_HYPERLINKS"))
       
  1074   {
       
  1075     t << "{\\field {\\*\\fldinst { HYPERLINK  \\\\l \"";
       
  1076     t << rtfFormatBmkStr(f);
       
  1077     t << "\" }{}";
       
  1078     t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
       
  1079 
       
  1080     docify(name);
       
  1081 
       
  1082     t << "}}}" << endl;
       
  1083   }
       
  1084   else
       
  1085   {
       
  1086     docify(name);
       
  1087   }
       
  1088   t << "} ";
       
  1089 }
       
  1090 
       
  1091 void RTFGenerator::writeEndAnnoItem(const char *name)
       
  1092 {
       
  1093   DBG_RTF(t << "{\\comment (writeEndAnnoItem)}" << endl)
       
  1094   if (name)
       
  1095   {
       
  1096     t << "\\tab ";
       
  1097     writeRTFReference(name);
       
  1098     t << endl;
       
  1099   }
       
  1100   else
       
  1101   {
       
  1102     t << endl;
       
  1103   }
       
  1104   newParagraph();
       
  1105 }
       
  1106 
       
  1107 void RTFGenerator::startIndexKey()
       
  1108 {
       
  1109   DBG_RTF(t << "{\\comment (startIndexKey)}" << endl)
       
  1110   t << "{\\b ";
       
  1111 }
       
  1112 
       
  1113 void RTFGenerator::endIndexKey()
       
  1114 {
       
  1115   DBG_RTF(t << "{\\comment (endIndexKey)}" << endl)
       
  1116 }
       
  1117 
       
  1118 void RTFGenerator::startIndexValue(bool hasBrief)
       
  1119 {
       
  1120   DBG_RTF(t << "{\\comment (startIndexValue)}" << endl)
       
  1121   t << " ";
       
  1122   if (hasBrief) t << "(";
       
  1123 }
       
  1124 
       
  1125 void RTFGenerator::endIndexValue(const char *name,bool hasBrief)
       
  1126 {
       
  1127   DBG_RTF(t << "{\\comment (endIndexValue)}" << endl)
       
  1128   if (hasBrief) t << ")";
       
  1129   t << "} ";
       
  1130   if (name)
       
  1131   {
       
  1132     t << "\\tab ";
       
  1133     writeRTFReference(name);
       
  1134     t << endl;
       
  1135   }
       
  1136   else
       
  1137   {
       
  1138     t << endl;
       
  1139   }
       
  1140   m_omitParagraph=FALSE;
       
  1141   newParagraph();
       
  1142 }
       
  1143 
       
  1144 void RTFGenerator::startSubsection()
       
  1145 {
       
  1146   //beginRTFSubSection();
       
  1147   t <<"\n";
       
  1148   DBG_RTF(t << "{\\comment Begin SubSection}\n")
       
  1149   t << rtf_Style_Reset;
       
  1150   t << rtf_Style["Heading3"]->reference << "\n";
       
  1151 }
       
  1152 
       
  1153 void RTFGenerator::endSubsection()
       
  1154 {
       
  1155   newParagraph();
       
  1156   t << rtf_Style_Reset << endl;
       
  1157 }
       
  1158 
       
  1159 void RTFGenerator::startSubsubsection()
       
  1160 {
       
  1161   //beginRTFSubSubSection();
       
  1162   t << "\n";
       
  1163   DBG_RTF(t << "{\\comment Begin SubSubSection}\n")
       
  1164   t << "{" << endl;
       
  1165   t << rtf_Style_Reset << rtf_Style["Heading4"]->reference << "\n";
       
  1166 }
       
  1167 
       
  1168 void RTFGenerator::endSubsubsection()
       
  1169 {
       
  1170   newParagraph();
       
  1171   t << "}" << endl;
       
  1172 }
       
  1173 
       
  1174 
       
  1175 //void RTFGenerator::writeClassLink(const char *,const char *,
       
  1176 //                                    const char *,const char *name)
       
  1177 //{
       
  1178 //  t << "{\\bf ";
       
  1179 //  docify(name);
       
  1180 //  t << "}";
       
  1181 //}
       
  1182 
       
  1183 //void RTFGenerator::startTable(bool,int colNumbers) 
       
  1184 //{
       
  1185 //  DBG_RTF(t << "{\\comment startTable}\n";)
       
  1186 //  m_numCols=colNumbers;
       
  1187 //  t << "\\par\n";
       
  1188 //}
       
  1189 //
       
  1190 //void RTFGenerator::endTable(bool hasCaption) 
       
  1191 //{ 
       
  1192 //  DBG_RTF(t << "{\\comment endTable}\n";)
       
  1193 //  if (!hasCaption) 
       
  1194 //    t << "\n\\pard \\widctlpar\\intbl\\adjustright\n{\\row }\n"; 
       
  1195 //  t << "\\pard\n" << endl; 
       
  1196 //}
       
  1197 //
       
  1198 //void  RTFGenerator::startCaption() 
       
  1199 //{
       
  1200 //  DBG_RTF(t << "{\\comment startCaption}\n";)
       
  1201 //  endTableRow();
       
  1202 //  t << "\\trowd \\trgaph108\\trleft-108\\trbrdrt\\brdrs\\brdrw10 \\trbrdrl\\brdrs\\brdrw10 \\trbrdrb\\brdrs\\brdrw10 \\trbrdrr\\brdrs\\brdrw10 \\trbrdrh\\brdrs\\brdrw10 \\trbrdrv\\brdrs\\brdrw10" << endl;
       
  1203 //  t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 \\clbrdrl\\brdrs\\brdrw10 \\clbrdrb\\brdrs\\brdrw10 \\clbrdrr \\brdrs\\brdrw10 \\cltxlrtb \\cellx"<<rtf_pageWidth<<"\\pard \\qc\\nowidctlpar\\widctlpar\\intbl\\adjustright " << endl;
       
  1204 //  nextTableColumn();
       
  1205 //}
       
  1206 //
       
  1207 //void  RTFGenerator::endCaption() 
       
  1208 //{
       
  1209 //  DBG_RTF(t << "{\\comment endCaption}\n";)
       
  1210 //  endTableColumn();
       
  1211 //  endTableRow();
       
  1212 //}
       
  1213 //
       
  1214 //void RTFGenerator::nextTableRow() 
       
  1215 //{  
       
  1216 //  DBG_RTF(t << "{\\comment nextTableRow}\n";)
       
  1217 //  ASSERT(m_numCols>0 && m_numCols<25);
       
  1218 //  uint columnWidth=rtf_pageWidth/m_numCols;
       
  1219 //  t << "\\trowd \\trgaph108\\trleft-108\\trbrdrt\\brdrs\\brdrw10 "
       
  1220 //       "\\trbrdrl\\brdrs\\brdrw10 \\trbrdrb\\brdrs\\brdrw10 "
       
  1221 //       "\\trbrdrr\\brdrs\\brdrw10 \\trbrdrh\\brdrs\\brdrw10 "
       
  1222 //       "\\trbrdrv\\brdrs\\brdrw10 "<<endl;
       
  1223 //  for (int i=0;i<m_numCols;i++) 
       
  1224 //  {
       
  1225 //    t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 \\clbrdrl\\brdrs\\brdrw10 "
       
  1226 //         "\\clbrdrb\\brdrs\\brdrw10 \\clbrdrr \\brdrs\\brdrw10 \\cltxlrtb "
       
  1227 //         "\\cellx" << (i*columnWidth) << endl;
       
  1228 //  }
       
  1229 //  t << "\\pard \\widctlpar\\intbl\\adjustright\n{";
       
  1230 //}
       
  1231 // 
       
  1232 //void RTFGenerator::endTableRow() 
       
  1233 //{ 
       
  1234 //  DBG_RTF(t << "{\\comment endTableRow}\n";)
       
  1235 //  t << "\n\\pard \\widctlpar\\intbl\\adjustright\n{\\row }\n";
       
  1236 //}
       
  1237 // 
       
  1238 //void RTFGenerator::nextTableColumn() 
       
  1239 //{
       
  1240 //  DBG_RTF(t << "{\\comment nextTableColumn}\n";)
       
  1241 //  t << "{ ";
       
  1242 //}
       
  1243 //
       
  1244 //void RTFGenerator::endTableColumn() 
       
  1245 //{ 
       
  1246 //  DBG_RTF(t << "{\\comment endTableColumn}\n";)
       
  1247 //  t << " \\cell }";
       
  1248 //}
       
  1249 //
       
  1250 void RTFGenerator::startTextLink(const char *f,const char *anchor)
       
  1251 {
       
  1252   if (Config_getBool("RTF_HYPERLINKS"))
       
  1253   {
       
  1254     QCString ref;
       
  1255     if (f)
       
  1256     {
       
  1257       ref+=f;
       
  1258     }
       
  1259     if (anchor)
       
  1260     {
       
  1261       ref+='_';
       
  1262       ref+=anchor;
       
  1263     }
       
  1264 
       
  1265     t << "{\\field {\\*\\fldinst { HYPERLINK  \\\\l \"";
       
  1266     t << rtfFormatBmkStr(ref);
       
  1267     t << "\" }{}";
       
  1268     t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
       
  1269   }
       
  1270 }
       
  1271 
       
  1272 void RTFGenerator::endTextLink()
       
  1273 {
       
  1274   if (Config_getBool("RTF_HYPERLINKS"))
       
  1275   {
       
  1276     t << "}}}" << endl;
       
  1277   }
       
  1278 }
       
  1279 
       
  1280 void RTFGenerator::writeObjectLink(const char *ref, const char *f,
       
  1281     const char *anchor, const char *text)
       
  1282 {
       
  1283   if (!ref && Config_getBool("RTF_HYPERLINKS"))
       
  1284   {
       
  1285     QCString refName;
       
  1286     if (f)
       
  1287     {
       
  1288       refName+=f;
       
  1289     }
       
  1290     if (anchor)
       
  1291     {
       
  1292       refName+='_';
       
  1293       refName+=anchor;
       
  1294     }
       
  1295 
       
  1296     t << "{\\field {\\*\\fldinst { HYPERLINK  \\\\l \"";
       
  1297     t << rtfFormatBmkStr(refName);
       
  1298     t << "\" }{}";
       
  1299     t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
       
  1300 
       
  1301     docify(text);
       
  1302 
       
  1303     t << "}}}" << endl;
       
  1304   }
       
  1305   else
       
  1306   {
       
  1307     startBold();
       
  1308     docify(text);
       
  1309     endBold();
       
  1310   }
       
  1311 }
       
  1312 
       
  1313 void RTFGenerator::startPageRef()
       
  1314 {
       
  1315   t << " (";
       
  1316   startEmphasis();
       
  1317 }
       
  1318 
       
  1319 void RTFGenerator::endPageRef(const char *clname, const char *anchor)
       
  1320 {
       
  1321   QCString ref;
       
  1322   if (clname)
       
  1323   {
       
  1324     ref+=clname;
       
  1325   }
       
  1326   if (anchor)
       
  1327   {
       
  1328     ref+='_';
       
  1329     ref+=anchor;
       
  1330   }
       
  1331   writeRTFReference(ref);
       
  1332   endEmphasis();
       
  1333   t << ")";
       
  1334 }
       
  1335 
       
  1336 void RTFGenerator::writeCodeLink(const char *ref,const char *f,
       
  1337                                  const char *anchor,const char *name,
       
  1338                                  const char *)
       
  1339 {
       
  1340   if (!ref && Config_getBool("RTF_HYPERLINKS"))
       
  1341   {
       
  1342     QCString refName;
       
  1343     if (f)
       
  1344     {
       
  1345       refName+=f;
       
  1346     }
       
  1347     if (anchor)
       
  1348     {
       
  1349       refName+='_';
       
  1350       refName+=anchor;
       
  1351     }
       
  1352 
       
  1353     t << "{\\field {\\*\\fldinst { HYPERLINK  \\\\l \"";
       
  1354     t << rtfFormatBmkStr(refName);
       
  1355     t << "\" }{}";
       
  1356     t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
       
  1357 
       
  1358     codify(name);
       
  1359 
       
  1360     t << "}}}" << endl;
       
  1361   }
       
  1362   else
       
  1363   {
       
  1364     codify(name);
       
  1365   }
       
  1366 }
       
  1367 
       
  1368 void RTFGenerator::startTitleHead(const char *)
       
  1369 {
       
  1370   DBG_RTF(t <<"{\\comment startTitleHead}" << endl)
       
  1371 
       
  1372   //    beginRTFSection();
       
  1373   t << rtf_Style_Reset << rtf_Style["Heading2"]->reference << endl;
       
  1374 }
       
  1375 
       
  1376 void RTFGenerator::endTitleHead(const char *fileName,const char *name)
       
  1377 {
       
  1378   DBG_RTF(t <<"{\\comment endTitleHead}" << endl)
       
  1379   t << "\\par " << rtf_Style_Reset << endl;
       
  1380   if (name)
       
  1381   {
       
  1382     // make table of contents entry
       
  1383     t << "{\\tc\\tcl2 \\v ";
       
  1384     docify(name);
       
  1385     t << "}" << endl;
       
  1386 
       
  1387     // make an index entry
       
  1388     addIndexItem(name,0);
       
  1389 
       
  1390     //if (name)
       
  1391     //{
       
  1392     //  writeAnchor(0,name);
       
  1393     //}
       
  1394     //
       
  1395     //if (Config_getBool("RTF_HYPERLINKS") && fileName)
       
  1396     //{
       
  1397       writeAnchor(fileName,0);
       
  1398     //}
       
  1399   }
       
  1400 }
       
  1401 
       
  1402 void RTFGenerator::startTitle()
       
  1403 {
       
  1404   DBG_RTF(t <<"{\\comment startTitle}" << endl)
       
  1405   if (Config_getBool("COMPACT_RTF"))
       
  1406     beginRTFSection();
       
  1407   else
       
  1408     beginRTFChapter();
       
  1409 }
       
  1410 
       
  1411 void RTFGenerator::startGroupHeader()
       
  1412 {
       
  1413   DBG_RTF(t <<"{\\comment startGroupHeader}" << endl)
       
  1414   //newParagraph();
       
  1415   t << rtf_Style_Reset;
       
  1416   t << rtf_Style["Heading3"]->reference;
       
  1417   t << endl;
       
  1418 }
       
  1419 
       
  1420 void RTFGenerator::endGroupHeader()
       
  1421 {
       
  1422   DBG_RTF(t <<"{\\comment endGroupHeader}" << endl)
       
  1423   t << "\\par" << endl;
       
  1424   t << rtf_Style_Reset << endl;
       
  1425 }
       
  1426 
       
  1427 void RTFGenerator::startMemberDoc(const char *clname,
       
  1428     const char *memname,
       
  1429     const char *,
       
  1430     const char *)
       
  1431 {
       
  1432   DBG_RTF(t << "{\\comment startMemberDoc}" << endl)
       
  1433   if (memname && memname[0]!='@')
       
  1434   {
       
  1435     addIndexItem(memname,clname);
       
  1436     addIndexItem(clname,memname);
       
  1437   }
       
  1438   t << rtf_Style_Reset << rtf_Style["Heading4"]->reference;
       
  1439   //styleStack.push(rtf_Style_Heading4);
       
  1440   t << "{" << endl;
       
  1441   //printf("RTFGenerator::startMemberDoc() `%s'\n",rtf_Style["Heading4"]->reference);
       
  1442   startBold();
       
  1443   t << endl;
       
  1444 }
       
  1445 
       
  1446 void RTFGenerator::endMemberDoc(bool)
       
  1447 {
       
  1448   DBG_RTF(t << "{\\comment endMemberDoc}" << endl)
       
  1449   t << "}" << endl;
       
  1450   //const char *style = styleStack.pop();
       
  1451   //printf("RTFGenerator::endMemberDoc() `%s'\n",style);
       
  1452   //ASSERT(style==rtf_Style["Heading4"]->reference);
       
  1453   endBold();
       
  1454   newParagraph();
       
  1455 }
       
  1456 
       
  1457 void RTFGenerator::startDoxyAnchor(const char *,const char *,
       
  1458                                    const char *,const char *,
       
  1459                                    const char *
       
  1460                                   )
       
  1461 {
       
  1462   DBG_RTF(t << "{\\comment startDoxyAnchor}" << endl)
       
  1463 }
       
  1464 
       
  1465 void RTFGenerator::endDoxyAnchor(const char *fName,const char *anchor)
       
  1466 {
       
  1467   QCString ref;
       
  1468   if (fName)
       
  1469   {
       
  1470     ref+=fName;
       
  1471   }
       
  1472   if (anchor)
       
  1473   {
       
  1474     ref+='_';
       
  1475     ref+=anchor;
       
  1476   }
       
  1477 
       
  1478   DBG_RTF(t << "{\\comment endDoxyAnchor}" << endl)
       
  1479   t << "{\\bkmkstart ";
       
  1480   t << rtfFormatBmkStr(ref);
       
  1481   t << "}" << endl;
       
  1482   t << "{\\bkmkend ";
       
  1483   t << rtfFormatBmkStr(ref);
       
  1484   t << "}" << endl;
       
  1485 }
       
  1486 
       
  1487 
       
  1488 //void RTFGenerator::writeLatexLabel(const char *clName,const char *anchor)
       
  1489 //{
       
  1490 //  writeDoxyAnchor(0,clName,anchor,0);
       
  1491 //}
       
  1492 
       
  1493 void RTFGenerator::addIndexItem(const char *s1,const char *s2)
       
  1494 {
       
  1495   if (s1)
       
  1496   {
       
  1497     t << "{\\xe \\v ";
       
  1498     docify(s1);
       
  1499     if (s2)
       
  1500     {
       
  1501       t << "\\:";
       
  1502       docify(s2);
       
  1503     }
       
  1504     t << "}" << endl;
       
  1505   }
       
  1506 }
       
  1507 
       
  1508 void RTFGenerator::startIndent()
       
  1509 {
       
  1510   incrementIndentLevel();
       
  1511   DBG_RTF(t << "{\\comment (startIndent) }" << endl)
       
  1512   t << "{" << endl;
       
  1513   t << rtf_Style_Reset << rtf_CList_DepthStyle() << endl;
       
  1514 }
       
  1515 
       
  1516 void RTFGenerator::endIndent()
       
  1517 {
       
  1518   t << "}" << endl;
       
  1519   decrementIndentLevel();
       
  1520 }
       
  1521 
       
  1522 
       
  1523 void RTFGenerator::startDescription()
       
  1524 {
       
  1525   DBG_RTF(t << "{\\comment (startDescription)}"    << endl)
       
  1526   t << "{" << endl;
       
  1527   t << rtf_Style_Reset << rtf_DList_DepthStyle();
       
  1528 }
       
  1529 
       
  1530 void RTFGenerator::endDescription()
       
  1531 {
       
  1532   DBG_RTF(t << "{\\comment (endDescription)}"    << endl)
       
  1533   newParagraph();
       
  1534   t << "}";
       
  1535 }
       
  1536 
       
  1537 void RTFGenerator::startDescItem()
       
  1538 {
       
  1539   newParagraph();
       
  1540   DBG_RTF(t << "{\\comment (startDescItem)}"    << endl)
       
  1541   t << "{\\b ";
       
  1542 }
       
  1543 
       
  1544 void RTFGenerator::endDescItem()
       
  1545 {
       
  1546   DBG_RTF(t << "{\\comment (endDescItem)}"    << endl)
       
  1547   t << "}" << endl;
       
  1548   newParagraph();
       
  1549 }
       
  1550 
       
  1551 void RTFGenerator::startMemberDescription()
       
  1552 {
       
  1553   DBG_RTF(t << "{\\comment (startMemberDescription)}"    << endl)
       
  1554   t << "{" << endl;
       
  1555   incrementIndentLevel();
       
  1556   t << rtf_Style_Reset << rtf_CList_DepthStyle();
       
  1557   startEmphasis();
       
  1558 }
       
  1559 
       
  1560 void RTFGenerator::endMemberDescription()
       
  1561 {
       
  1562   DBG_RTF(t << "{\\comment (endMemberDescription)}"    << endl)
       
  1563   endEmphasis();
       
  1564   newParagraph();
       
  1565   decrementIndentLevel();
       
  1566   //t << "\\par";
       
  1567   t << "}" << endl;
       
  1568   //m_omitParagraph = TRUE;
       
  1569 }
       
  1570 
       
  1571 void RTFGenerator::startDescList(SectionTypes)
       
  1572 {
       
  1573   DBG_RTF(t << "{\\comment (startDescList)}"    << endl)
       
  1574   t << "{"; // ends at endDescList
       
  1575   t << "{"; // ends at endDescTitle
       
  1576   startBold();
       
  1577   newParagraph();
       
  1578 }
       
  1579 
       
  1580 //void RTFGenerator::endDescTitle()
       
  1581 //{
       
  1582 //  DBG_RTF(t << "{\\comment (endDescTitle) }"    << endl)
       
  1583 //  endBold();
       
  1584 //  t << "}";
       
  1585 //  newParagraph();
       
  1586 //  incrementIndentLevel();
       
  1587 //  t << rtf_Style_Reset << rtf_DList_DepthStyle();
       
  1588 //}
       
  1589 
       
  1590 void RTFGenerator::startDescForItem()
       
  1591 {
       
  1592   DBG_RTF(t << "{\\comment (startDescForItem) }"    << endl)
       
  1593 }
       
  1594 
       
  1595 void RTFGenerator::endDescForItem()
       
  1596 {
       
  1597   DBG_RTF(t << "{\\comment (endDescForItem) }"    << endl)
       
  1598 }
       
  1599 
       
  1600 //void RTFGenerator::endDescList()
       
  1601 //{
       
  1602 //  DBG_RTF(t << "{\\comment (endDescList)}"    << endl)
       
  1603 //  newParagraph();
       
  1604 //  decrementIndentLevel();
       
  1605 //  m_omitParagraph = TRUE;
       
  1606 //  t << "}";
       
  1607 //}
       
  1608 
       
  1609 
       
  1610 void RTFGenerator::startSection(const char *,const char *title,SectionInfo::SectionType type)
       
  1611 {
       
  1612   DBG_RTF(t << "{\\comment (startSection)}"    << endl)
       
  1613   t << "{";
       
  1614   t<< rtf_Style_Reset;
       
  1615   int num=4;
       
  1616   switch(type)
       
  1617   {
       
  1618     case SectionInfo::Page:          num=2; break;
       
  1619     case SectionInfo::Section:       num=3; break;
       
  1620     case SectionInfo::Subsection:    num=4; break;
       
  1621     case SectionInfo::Subsubsection: num=4; break;
       
  1622     case SectionInfo::Paragraph:     num=4; break;
       
  1623     default: ASSERT(0); break;
       
  1624   }
       
  1625   QCString heading;
       
  1626   heading.sprintf("Heading%d",num);
       
  1627   // set style
       
  1628   t << rtf_Style[heading]->reference;
       
  1629   // make table of contents entry
       
  1630   t << "{\\tc\\tcl" << num << " \\v ";
       
  1631   docify(title);
       
  1632   t << "}" << endl;
       
  1633 }
       
  1634 
       
  1635 void RTFGenerator::endSection(const char *lab,SectionInfo::SectionType)
       
  1636 {
       
  1637   DBG_RTF(t << "{\\comment (endSection)}"    << endl)
       
  1638   // make bookmark
       
  1639   m_omitParagraph=FALSE;
       
  1640   newParagraph();
       
  1641   writeAnchor(0,lab);
       
  1642   t << "}";
       
  1643 }
       
  1644 
       
  1645 //void RTFGenerator::writeSectionRef(const char *ref,const char *,
       
  1646 //                                   const char *lab,const char *title)
       
  1647 //{
       
  1648 //  if (ref)
       
  1649 //  {
       
  1650 //    docify(title);
       
  1651 //  }
       
  1652 //  else
       
  1653 //  {
       
  1654 //    startBold();
       
  1655 //    docify(title);
       
  1656 //    endBold();
       
  1657 //    t << " (";
       
  1658 //    docify(theTranslator->trPageAbbreviation());
       
  1659 //    writeRTFReference(lab);
       
  1660 //    t << ")" << endl;
       
  1661 //  }
       
  1662 //}
       
  1663 //
       
  1664 //void RTFGenerator::writeSectionRefItem(const char *,const char *lab,
       
  1665 //    const char *title)
       
  1666 //{
       
  1667 //  docify(title);
       
  1668 //  t << "\\tab";
       
  1669 //  writeRTFReference(lab);
       
  1670 //  t << endl;
       
  1671 //}
       
  1672 //
       
  1673 //void RTFGenerator::writeSectionRefAnchor(const char *name,const char *lab,
       
  1674 //    const char *title)
       
  1675 //{
       
  1676 //  writeSectionRef(name,lab,title);
       
  1677 //}
       
  1678 
       
  1679 //char* RTFGenerator::getMultiByte(int c)
       
  1680 //{
       
  1681 //    static char s[10];
       
  1682 //
       
  1683 //    sprintf(s,"\\'%X",c);
       
  1684 //    return s;
       
  1685 //}
       
  1686 
       
  1687 void RTFGenerator::docify(const char *str)
       
  1688 {
       
  1689   if (str)
       
  1690   {
       
  1691     const unsigned char *p=(const unsigned char *)str;
       
  1692     unsigned char c;
       
  1693     unsigned char pc='\0';
       
  1694     while (*p)
       
  1695     {
       
  1696       //static bool MultiByte = FALSE;
       
  1697       c=*p++;
       
  1698 
       
  1699 #if 0
       
  1700       if ( MultiByte )
       
  1701       {
       
  1702         t << getMultiByte( c );
       
  1703         MultiByte = FALSE;
       
  1704         continue;
       
  1705       }
       
  1706       if ( c >= 0x80 )
       
  1707       {
       
  1708         MultiByte = TRUE;
       
  1709         t << getMultiByte( c );
       
  1710         continue;
       
  1711       }
       
  1712 #endif
       
  1713 
       
  1714       switch (c)
       
  1715       {
       
  1716         case '{':  t << "\\{";            break;
       
  1717         case '}':  t << "\\}";            break;
       
  1718         case '\\': t << "\\\\";           break;
       
  1719         default:
       
  1720           {
       
  1721             // see if we can insert an hyphenation hint
       
  1722             //if (isupper(c) && islower(pc) && !insideTabbing) t << "\\-";
       
  1723             t << (char)c;
       
  1724           }
       
  1725       }
       
  1726       pc = c;
       
  1727       m_omitParagraph = FALSE;
       
  1728     }
       
  1729   }
       
  1730 }
       
  1731 
       
  1732 void RTFGenerator::codify(const char *str)
       
  1733 {
       
  1734   // note that RTF does not have a "verbatim", so "\n" means
       
  1735   // nothing... add a "newParagraph()";
       
  1736   //static char spaces[]="        ";
       
  1737   if (str)
       
  1738   {
       
  1739     const unsigned char *p=(const unsigned char *)str;
       
  1740     unsigned char c;
       
  1741     int spacesToNextTabStop;
       
  1742 
       
  1743     while (*p)
       
  1744     {
       
  1745       //static bool MultiByte = FALSE;
       
  1746 
       
  1747       c=*p++;
       
  1748 
       
  1749 #if 0
       
  1750       if( MultiByte )
       
  1751       {
       
  1752         t << getMultiByte( c );
       
  1753         MultiByte = FALSE;
       
  1754         continue;
       
  1755       }
       
  1756       if( c >= 0x80 )
       
  1757       {
       
  1758         MultiByte = TRUE;
       
  1759         t << getMultiByte( c );
       
  1760         continue;
       
  1761       }
       
  1762 #endif
       
  1763 
       
  1764       switch(c)
       
  1765       {
       
  1766         case '\t':  spacesToNextTabStop = Config_getInt("TAB_SIZE") - (col%Config_getInt("TAB_SIZE"));
       
  1767                     t << Doxygen::spaces.left(spacesToNextTabStop);
       
  1768                     col+=spacesToNextTabStop;
       
  1769                     break;
       
  1770         case '\n':  newParagraph();
       
  1771                     t << '\n'; col=0;
       
  1772                     break;
       
  1773         case '{':   t << "\\{"; col++;          break;
       
  1774         case '}':   t << "\\}"; col++;          break;
       
  1775         case '\\':  t << "\\\\"; col++;         break;
       
  1776         default:    t << (char)c; col++;           break;
       
  1777       }
       
  1778     }
       
  1779   }
       
  1780 }
       
  1781 
       
  1782 void RTFGenerator::writeChar(char c)
       
  1783 {
       
  1784   char cs[2];
       
  1785   cs[0]=c;
       
  1786   cs[1]=0;
       
  1787   docify(cs);
       
  1788 }
       
  1789 
       
  1790 void RTFGenerator::startClassDiagram()
       
  1791 {
       
  1792   DBG_RTF(t <<"{\\comment startClassDiagram }" << endl)
       
  1793 }
       
  1794 
       
  1795 void RTFGenerator::endClassDiagram(const ClassDiagram &d,
       
  1796     const char *fileName,const char *)
       
  1797 {
       
  1798   newParagraph();
       
  1799 
       
  1800   // create a png file
       
  1801   d.writeImage(t,dir,relPath,fileName,FALSE);
       
  1802 
       
  1803   // display the file
       
  1804   t << "{" << endl;
       
  1805   t << rtf_Style_Reset << endl;
       
  1806   t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  1807   t << fileName << ".png\"";
       
  1808   t << " \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  1809   t << "}" << endl;
       
  1810 }
       
  1811 
       
  1812 //void RTFGenerator::writeFormula(const char *,const char *text)
       
  1813 //{
       
  1814 //  t << text;
       
  1815 //}
       
  1816 
       
  1817 void RTFGenerator::startMemberItem(int)
       
  1818 {
       
  1819   DBG_RTF(t <<"{\\comment startMemberItem }" << endl)
       
  1820   t << rtf_Style_Reset << rtf_BList_DepthStyle() << endl; // set style to apropriate depth
       
  1821 }
       
  1822 
       
  1823 void RTFGenerator::endMemberItem()
       
  1824 {
       
  1825   DBG_RTF(t <<"{\\comment endMemberItem }" << endl)
       
  1826   newParagraph();
       
  1827 }
       
  1828 
       
  1829 void RTFGenerator::writeAnchor(const char *fileName,const char *name)
       
  1830 {
       
  1831   QCString anchor;
       
  1832   if (fileName)
       
  1833   {
       
  1834     anchor+=fileName;
       
  1835   }
       
  1836   if (fileName && name)
       
  1837   {
       
  1838     anchor+='_';
       
  1839   }
       
  1840   if (name)
       
  1841   {
       
  1842     anchor+=name;
       
  1843   }
       
  1844 
       
  1845   DBG_RTF(t <<"{\\comment writeAnchor (" << anchor << ")}" << endl)
       
  1846   t << "{\\bkmkstart " << rtfFormatBmkStr(anchor) << "}" << endl;
       
  1847   t << "{\\bkmkend " << rtfFormatBmkStr(anchor) << "}" << endl;
       
  1848 }
       
  1849 
       
  1850 void RTFGenerator::writeRTFReference(const char *label)
       
  1851 {
       
  1852   t << "{\\field\\fldedit {\\*\\fldinst PAGEREF ";
       
  1853   t << rtfFormatBmkStr(label);
       
  1854   t << " \\\\*MERGEFORMAT}{\\fldrslt pagenum}}";
       
  1855 }
       
  1856 
       
  1857 void RTFGenerator::startCodeFragment()
       
  1858 {
       
  1859   DBG_RTF(t << "{\\comment (startCodeFragment) }"    << endl)
       
  1860   t << "{" << endl;
       
  1861   //newParagraph();
       
  1862   t << rtf_Style_Reset << rtf_Code_DepthStyle();
       
  1863   //styleStack.push(rtf_Style_CodeExample);
       
  1864 }
       
  1865 
       
  1866 void RTFGenerator::endCodeFragment()
       
  1867 {
       
  1868   //newParagraph();
       
  1869   //styleStack.pop();
       
  1870   //printf("RTFGenerator::endCodeFrament() top=%s\n",styleStack.top());
       
  1871   //t << rtf_Style_Reset << styleStack.top() << endl;
       
  1872   DBG_RTF(t << "{\\comment (endCodeFragment) }"    << endl)
       
  1873   t << "}" << endl;
       
  1874   m_omitParagraph = TRUE;
       
  1875 }
       
  1876 
       
  1877 void RTFGenerator::writeNonBreakableSpace(int)
       
  1878 {
       
  1879   t << "\\~ ";
       
  1880 }
       
  1881 
       
  1882 
       
  1883 void RTFGenerator::startMemberList()
       
  1884 {
       
  1885   t << endl;
       
  1886   DBG_RTF(t << "{\\comment (startMemberList) }"    << endl)
       
  1887   t << "{" << endl;
       
  1888 #ifdef DELETEDCODE
       
  1889   if (!insideTabbing)
       
  1890     t << "\\begin{CompactItemize}" << endl;
       
  1891 #endif
       
  1892 }
       
  1893 
       
  1894 void RTFGenerator::endMemberList()
       
  1895 {
       
  1896   DBG_RTF(t << "{\\comment (endMemberList) }"    << endl)
       
  1897   t << "}" << endl;
       
  1898 #ifdef DELETEDCODE
       
  1899   if (!insideTabbing)
       
  1900     t << "\\end{CompactItemize}"   << endl;
       
  1901 #endif
       
  1902 }
       
  1903 
       
  1904 //void RTFGenerator::startImage(const char *name,const char *,bool)
       
  1905 //{
       
  1906 //  newParagraph();
       
  1907 //  t << "{" << endl;
       
  1908 //  t << rtf_Style_Reset << endl;
       
  1909 //  t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE ";
       
  1910 //  t << name;
       
  1911 //  t << " \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  1912 //  t << "}" << endl;
       
  1913 //}
       
  1914 //
       
  1915 //void RTFGenerator::endImage(bool)
       
  1916 //{
       
  1917 //  // not yet implemented
       
  1918 //}
       
  1919 //
       
  1920 //void RTFGenerator::startDotFile(const char *name,bool)
       
  1921 //{
       
  1922 //  QCString baseName=name;
       
  1923 //  int i;
       
  1924 //  if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
       
  1925 //  {
       
  1926 //    baseName=baseName.right(baseName.length()-i-1);
       
  1927 //  }
       
  1928 //  QCString outDir = Config_getString("RTF_OUTPUT");
       
  1929 //  writeDotGraphFromFile(name,outDir,baseName,BITMAP);
       
  1930 //  newParagraph();
       
  1931 //  t << "{" << endl;
       
  1932 //  t << rtf_Style_Reset << endl;
       
  1933 //  t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE ";
       
  1934 //  t << outDir << "\\" << baseName;
       
  1935 //  t << " \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  1936 //  t << "}" << endl;
       
  1937 //}
       
  1938 //
       
  1939 //void RTFGenerator::endDotFile(bool)
       
  1940 //{
       
  1941 //  // not yet implemented
       
  1942 //}
       
  1943 //
       
  1944 void RTFGenerator::startDescTable()
       
  1945 {
       
  1946   DBG_RTF(t << "{\\comment (startDescTable) }"    << endl)
       
  1947   //t << "{" << endl;
       
  1948   //incrementIndentLevel();
       
  1949   //t << rtf_Style_Reset << rtf_CList_DepthStyle();
       
  1950 }
       
  1951 
       
  1952 void RTFGenerator::endDescTable()
       
  1953 {
       
  1954   //decrementIndentLevel();
       
  1955   DBG_RTF(t << "{\\comment (endDescTable)}"      << endl)
       
  1956   //t << "}" << endl;
       
  1957   //t << rtf_Style_Reset << styleStack.top();
       
  1958 }
       
  1959 
       
  1960 void RTFGenerator::startDescTableTitle()
       
  1961 {
       
  1962   //t << rtf_BList_DepthStyle() << endl;
       
  1963   DBG_RTF(t << "{\\comment (startDescTableTitle) }"    << endl)
       
  1964   startBold();
       
  1965   startEmphasis();
       
  1966 }
       
  1967 
       
  1968 void RTFGenerator::endDescTableTitle()
       
  1969 {
       
  1970   DBG_RTF(t << "{\\comment (endDescTableTitle) }"    << endl)
       
  1971   endEmphasis();
       
  1972   endBold();
       
  1973   t << "  ";
       
  1974 }
       
  1975 
       
  1976 void RTFGenerator::startDescTableData()
       
  1977 {
       
  1978   DBG_RTF(t << "{\\comment (startDescTableData) }"    << endl)
       
  1979   m_omitParagraph = FALSE;
       
  1980 }
       
  1981 
       
  1982 void RTFGenerator::endDescTableData()
       
  1983 {
       
  1984   DBG_RTF(t << "{\\comment (endDescTableData) }"    << endl)
       
  1985   newParagraph();
       
  1986   m_omitParagraph = TRUE;
       
  1987 }
       
  1988 
       
  1989 // a style for list formatted as a "bulleted list"
       
  1990 
       
  1991 void RTFGenerator::incrementIndentLevel()
       
  1992 {
       
  1993   m_listLevel++;
       
  1994   if (m_listLevel>rtf_maxIndentLevels-1)
       
  1995   {
       
  1996     warn_cont("Warning: Maximum indent level (%d) exceeded while generating RTF output!\n",rtf_maxIndentLevels);
       
  1997     m_listLevel=rtf_maxIndentLevels-1;
       
  1998   }
       
  1999 }
       
  2000 
       
  2001 void RTFGenerator::decrementIndentLevel()
       
  2002 {
       
  2003   m_listLevel--;
       
  2004   if (m_listLevel<0)
       
  2005   {
       
  2006     warn_cont("Warning: Negative indent level while generating RTF output!\n");
       
  2007     m_listLevel=0;
       
  2008   }
       
  2009 }
       
  2010 
       
  2011 // a style for list formatted with "list continue" style
       
  2012 const char * RTFGenerator::rtf_CList_DepthStyle()
       
  2013 {
       
  2014   QCString n=makeIndexName("ListContinue",m_listLevel);
       
  2015   return rtf_Style[n]->reference;
       
  2016 }
       
  2017 
       
  2018 // a style for list formatted as a "latext style" table of contents
       
  2019 const char * RTFGenerator::rtf_LCList_DepthStyle()
       
  2020 {
       
  2021   QCString n=makeIndexName("LatexTOC",m_listLevel);
       
  2022   return rtf_Style[n]->reference;
       
  2023 }
       
  2024 
       
  2025 // a style for list formatted as a "bullet" style
       
  2026 const char * RTFGenerator::rtf_BList_DepthStyle()
       
  2027 {
       
  2028   QCString n=makeIndexName("ListBullet",m_listLevel);
       
  2029   return rtf_Style[n]->reference;
       
  2030 }
       
  2031 
       
  2032 // a style for list formatted as a "enumeration" style
       
  2033 const char * RTFGenerator::rtf_EList_DepthStyle()
       
  2034 {
       
  2035   QCString n=makeIndexName("ListEnum",m_listLevel);
       
  2036   return rtf_Style[n]->reference;
       
  2037 }
       
  2038 
       
  2039 const char * RTFGenerator::rtf_DList_DepthStyle()
       
  2040 {
       
  2041   QCString n=makeIndexName("DescContinue",m_listLevel);
       
  2042   return rtf_Style[n]->reference;
       
  2043 }
       
  2044 
       
  2045 const char * RTFGenerator::rtf_Code_DepthStyle()
       
  2046 {
       
  2047   QCString n=makeIndexName("CodeExample",m_listLevel);
       
  2048   return rtf_Style[n]->reference;
       
  2049 }
       
  2050 
       
  2051 void RTFGenerator::startTextBlock(bool dense)
       
  2052 {
       
  2053   DBG_RTF(t << "{\\comment startTextBlock}" << endl)
       
  2054   t << "{" << endl;
       
  2055   t << rtf_Style_Reset;
       
  2056   if (dense) // no spacing between "paragraphs"
       
  2057   {
       
  2058     t << rtf_Style["DenseText"]->reference;
       
  2059   }
       
  2060   else // some spacing
       
  2061   {
       
  2062     t << rtf_Style["BodyText"]->reference;
       
  2063   }
       
  2064 }
       
  2065 
       
  2066 void RTFGenerator::endTextBlock(bool /*paraBreak*/)
       
  2067 {
       
  2068   newParagraph();
       
  2069   DBG_RTF(t << "{\\comment endTextBlock}" << endl)
       
  2070   t << "}" << endl;
       
  2071   //m_omitParagraph = TRUE;
       
  2072 }
       
  2073 
       
  2074 void RTFGenerator::newParagraph()
       
  2075 {
       
  2076   if (!m_omitParagraph)
       
  2077   {
       
  2078     DBG_RTF(t << "{\\comment (newParagraph)}"    << endl)
       
  2079     t << "\\par" << endl;
       
  2080   }
       
  2081   m_omitParagraph = FALSE;
       
  2082 }
       
  2083 
       
  2084 void RTFGenerator::startParagraph()
       
  2085 {
       
  2086   DBG_RTF(t << "{\\comment startParagraph}" << endl)
       
  2087   newParagraph();
       
  2088   t << "{" << endl;
       
  2089 }
       
  2090 
       
  2091 void RTFGenerator::endParagraph()
       
  2092 {
       
  2093   DBG_RTF(t << "{\\comment endParagraph}" << endl)
       
  2094   t << "}\\par" << endl;
       
  2095   m_omitParagraph = TRUE;
       
  2096 }
       
  2097 
       
  2098 void RTFGenerator::startMemberSubtitle()
       
  2099 {
       
  2100   DBG_RTF(t << "{\\comment startMemberSubtitle}" << endl)
       
  2101   t << "{" << endl;
       
  2102   t << rtf_Style_Reset << rtf_CList_DepthStyle() << endl;
       
  2103 }
       
  2104 
       
  2105 void RTFGenerator::endMemberSubtitle()
       
  2106 {
       
  2107   DBG_RTF(t << "{\\comment endMemberSubtitle}" << endl)
       
  2108   newParagraph();
       
  2109   t << "}" << endl;
       
  2110 }
       
  2111 
       
  2112 //void RTFGenerator::writeUmlaut(char c)
       
  2113 //{
       
  2114 //  switch(c)
       
  2115 //  {
       
  2116 //    case 'A' : t << '\304'; break;
       
  2117 //    case 'E' : t << '\313'; break;
       
  2118 //    case 'I' : t << '\317'; break;
       
  2119 //    case 'O' : t << '\326'; break;
       
  2120 //    case 'U' : t << '\334'; break;
       
  2121 //    case 'Y' : t << 'Y';    break;
       
  2122 //    case 'a' : t << '\344'; break;
       
  2123 //    case 'e' : t << '\353'; break;
       
  2124 //    case 'i' : t << '\357'; break;
       
  2125 //    case 'o' : t << '\366'; break;
       
  2126 //    case 'u' : t << '\374'; break;
       
  2127 //    case 'y' : t << '\377'; break;
       
  2128 //    default: t << '?'; break;
       
  2129 //  }
       
  2130 //}
       
  2131 //
       
  2132 //void RTFGenerator::writeAcute(char c)
       
  2133 //{
       
  2134 //  switch(c)
       
  2135 //  {
       
  2136 //    case 'A' : t << '\301'; break;
       
  2137 //    case 'E' : t << '\311'; break;
       
  2138 //    case 'I' : t << '\315'; break;
       
  2139 //    case 'O' : t << '\323'; break;
       
  2140 //    case 'U' : t << '\332'; break;
       
  2141 //    case 'Y' : t << '\335'; break;
       
  2142 //    case 'a' : t << '\341'; break;
       
  2143 //    case 'e' : t << '\351'; break;
       
  2144 //    case 'i' : t << '\355'; break;
       
  2145 //    case 'o' : t << '\363'; break;
       
  2146 //    case 'u' : t << '\372'; break;
       
  2147 //    case 'y' : t << '\375'; break;
       
  2148 //    default: t << '?'; break;
       
  2149 //  }
       
  2150 //}
       
  2151 //
       
  2152 //void RTFGenerator::writeGrave(char c)
       
  2153 //{
       
  2154 //  switch(c)
       
  2155 //  {
       
  2156 //    case 'A' : t << '\300'; break;
       
  2157 //    case 'E' : t << '\310'; break;
       
  2158 //    case 'I' : t << '\314'; break;
       
  2159 //    case 'O' : t << '\322'; break;
       
  2160 //    case 'U' : t << '\331'; break;
       
  2161 //    case 'a' : t << '\340'; break;
       
  2162 //    case 'e' : t << '\350'; break;
       
  2163 //    case 'i' : t << '\354'; break;
       
  2164 //    case 'o' : t << '\362'; break;
       
  2165 //    case 'u' : t << '\371'; break;
       
  2166 //    default: t << '?'; break;
       
  2167 //  }
       
  2168 //}
       
  2169 //
       
  2170 //void RTFGenerator::writeCirc(char c)
       
  2171 //{
       
  2172 //  switch(c)
       
  2173 //  {
       
  2174 //    case 'A' : t << '\302'; break;
       
  2175 //    case 'E' : t << '\312'; break;
       
  2176 //    case 'I' : t << '\316'; break;
       
  2177 //    case 'O' : t << '\324'; break;
       
  2178 //    case 'U' : t << '\333'; break;
       
  2179 //    case 'a' : t << '\342'; break;
       
  2180 //    case 'e' : t << '\352'; break;
       
  2181 //    case 'i' : t << '\356'; break;
       
  2182 //    case 'o' : t << '\364'; break;
       
  2183 //    case 'u' : t << '\373'; break;
       
  2184 //    default: t << '?'; break;
       
  2185 //  }
       
  2186 //}
       
  2187 //
       
  2188 //void RTFGenerator::writeTilde(char c)
       
  2189 //{
       
  2190 //  switch(c)
       
  2191 //  {
       
  2192 //    case 'A' : t << '\303'; break;
       
  2193 //    case 'N' : t << '\321'; break;
       
  2194 //    case 'O' : t << '\325'; break;
       
  2195 //    case 'a' : t << '\343'; break;
       
  2196 //    case 'n' : t << '\361'; break;
       
  2197 //    case 'o' : t << '\365'; break;
       
  2198 //    default: t << '?'; break;
       
  2199 //  }
       
  2200 //}
       
  2201 //
       
  2202 //void RTFGenerator::writeRing(char c)
       
  2203 //{
       
  2204 //  switch(c)
       
  2205 //  {
       
  2206 //    case 'A' : t << '\305'; break;
       
  2207 //    case 'a' : t << '\345'; break;
       
  2208 //    default: t << '?'; break;
       
  2209 //  }
       
  2210 //}
       
  2211 //
       
  2212 //void RTFGenerator::writeCCedil(char c)
       
  2213 //{
       
  2214 //  switch(c)
       
  2215 //  {
       
  2216 //    case 'C' : t << '\307'; break;
       
  2217 //    case 'c' : t << '\347'; break;
       
  2218 //    default: t << '?'; break;
       
  2219 //  }
       
  2220 //}
       
  2221 //
       
  2222 /**
       
  2223  * VERY brittle routine inline RTF's included by other RTF's.
       
  2224  * it is recursive and ugly.
       
  2225  */
       
  2226 static bool PreProcessFile(QDir &d,QCString &infName, QTextStream &t, bool bIncludeHeader=TRUE)
       
  2227 {
       
  2228   QFile f(infName);
       
  2229   if (!f.open(IO_ReadOnly))
       
  2230   {
       
  2231     err("Error opening rtf file %s for reading\n",infName.data());
       
  2232     return FALSE;
       
  2233   }
       
  2234 
       
  2235   const int maxLineLength = 10240;
       
  2236   static QCString lineBuf(maxLineLength);
       
  2237 
       
  2238   // scan until find end of header
       
  2239   // this is EXTREEEEEEEMLY brittle.  It works on OUR rtf
       
  2240   // files because the first line before the body
       
  2241   // ALWAYS contains "{\comment begin body}"
       
  2242   do
       
  2243   {
       
  2244     if (f.readLine(lineBuf.data(),maxLineLength)==-1)
       
  2245     {
       
  2246       err("ERROR - read error in %s before end of RTF header!\n",infName.data());
       
  2247       return FALSE;
       
  2248     }
       
  2249     if (bIncludeHeader) t << lineBuf;
       
  2250   } while (lineBuf.find("\\comment begin body")==-1);
       
  2251 
       
  2252 
       
  2253   //while (fgets(buffer,sizeof(buffer),infp) != NULL)
       
  2254   while (f.readLine(lineBuf.data(),maxLineLength)!=-1)
       
  2255   {
       
  2256     int pos;
       
  2257     if ((pos=lineBuf.find("INCLUDETEXT"))!=-1)
       
  2258     {
       
  2259       int startNamePos  = lineBuf.find('"',pos)+1;
       
  2260       int endNamePos    = lineBuf.find('"',startNamePos);
       
  2261       QCString fileName = lineBuf.mid(startNamePos,endNamePos-startNamePos);
       
  2262       DBG_RTF(t << "{\\comment begin include " << fileName << "}" << endl)
       
  2263       if (!PreProcessFile(d,fileName,t,FALSE)) return FALSE;
       
  2264       DBG_RTF(t << "{\\comment end include " << fileName << "}" << endl)
       
  2265     }
       
  2266     else
       
  2267     {
       
  2268       // elaborate hoopla to skip  the final "}" if we didn't include the
       
  2269       // headers
       
  2270       if (!f.atEnd() || bIncludeHeader)
       
  2271       {
       
  2272         t << lineBuf;
       
  2273       }
       
  2274       else
       
  2275       {
       
  2276         // null terminate at the last '}'
       
  2277         //char *str = strrchr(buffer,'}');
       
  2278         int pos = lineBuf.findRev('}');
       
  2279 
       
  2280         if (pos != -1)
       
  2281           lineBuf.at(pos) = '\0';
       
  2282         else
       
  2283           err("Strange, the last char was not a '}'\n");
       
  2284         t << lineBuf;
       
  2285       }
       
  2286     }
       
  2287   }
       
  2288   f.close();
       
  2289   // remove temporary file
       
  2290   d.remove(infName);
       
  2291   return TRUE;
       
  2292 }
       
  2293 
       
  2294 void RTFGenerator::startDotGraph()
       
  2295 {
       
  2296   DBG_RTF(t << "{\\comment (startDotGraph)}"    << endl)
       
  2297 }
       
  2298 
       
  2299 void RTFGenerator::endDotGraph(const DotClassGraph &g)
       
  2300 {
       
  2301   newParagraph();
       
  2302 
       
  2303   QCString fileName =
       
  2304     g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"),relPath,TRUE,FALSE);
       
  2305 
       
  2306   // display the file
       
  2307   t << "{" << endl;
       
  2308   t << rtf_Style_Reset << endl;
       
  2309   t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  2310   t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT");
       
  2311   t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  2312   t << "}" << endl;
       
  2313   newParagraph();
       
  2314   DBG_RTF(t << "{\\comment (endDotGraph)}"    << endl)
       
  2315 }
       
  2316 
       
  2317 void RTFGenerator::startInclDepGraph()
       
  2318 {
       
  2319   DBG_RTF(t << "{\\comment (startInclDepGraph)}"    << endl)
       
  2320 }
       
  2321 
       
  2322 void RTFGenerator::endInclDepGraph(const DotInclDepGraph &g)
       
  2323 {
       
  2324   newParagraph();
       
  2325 
       
  2326   QCString fileName = g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"),
       
  2327                          relPath,FALSE);
       
  2328 
       
  2329   // display the file
       
  2330   t << "{" << endl;
       
  2331   t << rtf_Style_Reset << endl;
       
  2332   t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  2333   t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT");
       
  2334   t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  2335   t << "}" << endl;
       
  2336   DBG_RTF(t << "{\\comment (endInclDepGraph)}"    << endl)
       
  2337 }
       
  2338 
       
  2339 void RTFGenerator::startGroupCollaboration()
       
  2340 {
       
  2341 }
       
  2342 
       
  2343 void RTFGenerator::endGroupCollaboration(const DotGroupCollaboration &)
       
  2344 {
       
  2345 }
       
  2346 
       
  2347 void RTFGenerator::startCallGraph()
       
  2348 {
       
  2349   DBG_RTF(t << "{\\comment (startCallGraph)}"    << endl)
       
  2350 }
       
  2351 
       
  2352 void RTFGenerator::endCallGraph(const DotCallGraph &g)
       
  2353 {
       
  2354   newParagraph();
       
  2355 
       
  2356   QCString fileName = g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"),
       
  2357                         relPath,FALSE);
       
  2358 
       
  2359   // display the file
       
  2360   t << "{" << endl;
       
  2361   t << rtf_Style_Reset << endl;
       
  2362   t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  2363   t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT");
       
  2364   t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  2365   t << "}" << endl;
       
  2366   DBG_RTF(t << "{\\comment (endCallGraph)}"    << endl)
       
  2367 }
       
  2368 
       
  2369 void RTFGenerator::startDirDepGraph()
       
  2370 {
       
  2371   DBG_RTF(t << "{\\comment (startDirDepGraph)}"    << endl)
       
  2372 }
       
  2373 
       
  2374 void RTFGenerator::endDirDepGraph(const DotDirDeps &g)
       
  2375 {
       
  2376   newParagraph();
       
  2377 
       
  2378   QCString fileName = g.writeGraph(t,BITMAP,Config_getString("RTF_OUTPUT"),
       
  2379                         relPath,FALSE);
       
  2380 
       
  2381   // display the file
       
  2382   t << "{" << endl;
       
  2383   t << rtf_Style_Reset << endl;
       
  2384   t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
       
  2385   t << fileName << "." << Config_getEnum("DOT_IMAGE_FORMAT");
       
  2386   t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
       
  2387   t << "}" << endl;
       
  2388   DBG_RTF(t << "{\\comment (endDirDepGraph)}"    << endl)
       
  2389 }
       
  2390 
       
  2391 /** Tests the integrity of the result by counting brackets.
       
  2392  *
       
  2393  */
       
  2394 void testRTFOutput(const char *name)
       
  2395 {
       
  2396   int bcount=0;
       
  2397   int line=1;
       
  2398   int c;
       
  2399   QFile f(name);
       
  2400   if (f.open(IO_ReadOnly))
       
  2401   {
       
  2402     while ((c=f.getch())!=-1)
       
  2403     {
       
  2404       if (c=='\\') // escape char
       
  2405       {
       
  2406         c=f.getch();
       
  2407         if (c==-1) break;
       
  2408       }
       
  2409       else if (c=='{') // open bracket
       
  2410       {
       
  2411         bcount++;
       
  2412       }
       
  2413       else if (c=='}') // close bracket
       
  2414       {
       
  2415         bcount--;
       
  2416         if (bcount<0)
       
  2417         {
       
  2418           goto err;
       
  2419           break;
       
  2420         }
       
  2421       }
       
  2422       else if (c=='\n') // newline
       
  2423       {
       
  2424         line++;
       
  2425       }
       
  2426     }
       
  2427   }
       
  2428   if (bcount==0) return; // file is OK.
       
  2429 err:
       
  2430   err("Error: RTF integrity test failed at line %d of %s due to a bracket mismatch.\n",line,name);
       
  2431   err("       Please try to create a small code example that produces this error \n"
       
  2432       "       and send that to dimitri@stack.nl.\n");
       
  2433 }
       
  2434 
       
  2435 /**
       
  2436  * This is an API to a VERY brittle RTF preprocessor that combines nested
       
  2437  * RTF files.  This version replaces the infile with the new file
       
  2438  */
       
  2439 bool RTFGenerator::preProcessFileInplace(const char *path,const char *name)
       
  2440 {
       
  2441   QDir d(path);
       
  2442   // store the original directory
       
  2443   if (!d.exists())
       
  2444   {
       
  2445     err("Error: Output dir %s does not exist!\n",path);
       
  2446     return FALSE;
       
  2447   }
       
  2448   QCString oldDir = convertToQCString(QDir::currentDirPath());
       
  2449 
       
  2450   // go to the html output directory (i.e. path)
       
  2451   QDir::setCurrent(d.absPath());
       
  2452   QDir thisDir;
       
  2453 
       
  2454   QCString combinedName = (QCString)path+"/combined.rtf";
       
  2455   QCString mainRTFName  = (QCString)path+"/"+name;
       
  2456 
       
  2457   QFile outf(combinedName);
       
  2458   if (!outf.open(IO_WriteOnly))
       
  2459   {
       
  2460     err("Failed to open %s for writing!\n",combinedName.data());
       
  2461     return FALSE;
       
  2462   }
       
  2463   QTextStream outt(&outf);
       
  2464   outt.setEncoding(QTextStream::UnicodeUTF8);
       
  2465 
       
  2466   if (!PreProcessFile(thisDir,mainRTFName,outt))
       
  2467   {
       
  2468     // it failed, remove the temp file
       
  2469     outf.close();
       
  2470     thisDir.remove(combinedName);
       
  2471     QDir::setCurrent(oldDir);
       
  2472     return FALSE;
       
  2473   }
       
  2474 
       
  2475   // everything worked, move the files
       
  2476   outf.close();
       
  2477   thisDir.remove(mainRTFName);
       
  2478   thisDir.rename(combinedName,mainRTFName);
       
  2479 
       
  2480   testRTFOutput(mainRTFName);
       
  2481 
       
  2482   QDir::setCurrent(oldDir);
       
  2483   return TRUE;
       
  2484 }
       
  2485 
       
  2486 void RTFGenerator::startMemberGroupHeader(bool hasHeader)
       
  2487 {
       
  2488   DBG_RTF(t << "{\\comment startMemberGroupHeader}" << endl)
       
  2489   t << "{" << endl;
       
  2490   if (hasHeader) incrementIndentLevel();
       
  2491   t << rtf_Style_Reset << rtf_Style["GroupHeader"]->reference;
       
  2492 }
       
  2493 
       
  2494 void RTFGenerator::endMemberGroupHeader()
       
  2495 {
       
  2496   DBG_RTF(t << "{\\comment endMemberGroupHeader}" << endl)
       
  2497   newParagraph();
       
  2498   t << rtf_Style_Reset << rtf_CList_DepthStyle();
       
  2499 }
       
  2500 
       
  2501 void RTFGenerator::startMemberGroupDocs()
       
  2502 {
       
  2503   DBG_RTF(t << "{\\comment startMemberGroupDocs}" << endl)
       
  2504   startEmphasis();
       
  2505 }
       
  2506 
       
  2507 void RTFGenerator::endMemberGroupDocs()
       
  2508 {
       
  2509   DBG_RTF(t << "{\\comment endMemberGroupDocs}" << endl)
       
  2510   endEmphasis();
       
  2511   newParagraph();
       
  2512 }
       
  2513 
       
  2514 void RTFGenerator::startMemberGroup()
       
  2515 {
       
  2516   DBG_RTF(t << "{\\comment startMemberGroup}" << endl)
       
  2517   t << rtf_Style_Reset << rtf_BList_DepthStyle() << endl;
       
  2518 }
       
  2519 
       
  2520 void RTFGenerator::endMemberGroup(bool hasHeader)
       
  2521 {
       
  2522   DBG_RTF(t << "{\\comment endMemberGroup}" << endl)
       
  2523   if (hasHeader) decrementIndentLevel();
       
  2524   t << "}";
       
  2525 }
       
  2526 
       
  2527 void RTFGenerator::startSimpleSect(SectionTypes,const char *file,const char *anchor,const char *title)
       
  2528 {
       
  2529   DBG_RTF(t << "{\\comment (startSimpleSect)}"    << endl)
       
  2530   t << "{"; // ends at endDescList
       
  2531   t << "{"; // ends at endDescTitle
       
  2532   startBold();
       
  2533   newParagraph();
       
  2534   if (file)
       
  2535   {
       
  2536     writeObjectLink(0,file,anchor,title);
       
  2537   }
       
  2538   else
       
  2539   {
       
  2540     docify(title);
       
  2541   }
       
  2542   endBold();
       
  2543   t << "}";
       
  2544   newParagraph();
       
  2545   incrementIndentLevel();
       
  2546   t << rtf_Style_Reset << rtf_DList_DepthStyle();
       
  2547 }
       
  2548 
       
  2549 void RTFGenerator::endSimpleSect()
       
  2550 {
       
  2551   DBG_RTF(t << "{\\comment (endSimpleSect)}"    << endl)
       
  2552   newParagraph();
       
  2553   decrementIndentLevel();
       
  2554   m_omitParagraph = TRUE;
       
  2555   t << "}";
       
  2556 }
       
  2557 
       
  2558 void RTFGenerator::startParamList(ParamListTypes,const char *title)
       
  2559 {
       
  2560   DBG_RTF(t << "{\\comment (startParamList)}"    << endl)
       
  2561   t << "{"; // ends at endParamList
       
  2562   t << "{"; // ends at endDescTitle
       
  2563   startBold();
       
  2564   newParagraph();
       
  2565   docify(title);
       
  2566   endBold();
       
  2567   t << "}";
       
  2568   newParagraph();
       
  2569   incrementIndentLevel();
       
  2570   t << rtf_Style_Reset << rtf_DList_DepthStyle();
       
  2571 }
       
  2572 
       
  2573 void RTFGenerator::endParamList()
       
  2574 {
       
  2575   DBG_RTF(t << "{\\comment (endParamList)}"    << endl)
       
  2576   newParagraph();
       
  2577   decrementIndentLevel();
       
  2578   m_omitParagraph = TRUE;
       
  2579   t << "}";
       
  2580 }
       
  2581 
       
  2582 void RTFGenerator::startParameterType(bool first,const char *key)
       
  2583 {
       
  2584   DBG_RTF(t << "{\\comment (startParameterList)}"    << endl)
       
  2585   if (!first)
       
  2586   {
       
  2587     t << " " << key << " ";
       
  2588   }
       
  2589 }
       
  2590 
       
  2591 void RTFGenerator::printDoc(DocNode *n,const char *langExt)
       
  2592 {
       
  2593   RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,langExt);
       
  2594   n->accept(visitor);
       
  2595   delete visitor; 
       
  2596   m_omitParagraph = TRUE;
       
  2597 }
       
  2598 
       
  2599 void RTFGenerator::rtfwriteRuler_doubleline() 
       
  2600 { 
       
  2601   DBG_RTF(t << "{\\comment (rtfwriteRuler_doubleline)}"    << endl)
       
  2602   t << "{\\pard\\widctlpar\\brdrb\\brdrdb\\brdrw15\\brsp20 \\adjustright \\par}" << endl; 
       
  2603 }
       
  2604 
       
  2605 void RTFGenerator::rtfwriteRuler_emboss() 
       
  2606 { 
       
  2607   DBG_RTF(t << "{\\comment (rtfwriteRuler_emboss)}"    << endl)
       
  2608   t << "{\\pard\\widctlpar\\brdrb\\brdremboss\\brdrw15\\brsp20 \\adjustright \\par}" << endl; 
       
  2609 }
       
  2610 
       
  2611 void RTFGenerator::rtfwriteRuler_thick() 
       
  2612 { 
       
  2613   DBG_RTF(t << "{\\comment (rtfwriteRuler_thick)}"    << endl)
       
  2614   t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw75\\brsp20 \\adjustright \\par}" << endl; 
       
  2615 }
       
  2616 
       
  2617 void RTFGenerator::rtfwriteRuler_thin() 
       
  2618 { 
       
  2619   DBG_RTF(t << "{\\comment (rtfwriteRuler_thin)}"    << endl)
       
  2620   t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}" << endl; 
       
  2621 }
       
  2622 
       
  2623 void RTFGenerator::postProcess(QByteArray &a)
       
  2624 {
       
  2625   QByteArray enc(a.size()*4); // worst case
       
  2626   int off=0;
       
  2627   uint i;
       
  2628   bool mbFlag=FALSE;
       
  2629   for (i=0;i<a.size();i++)
       
  2630   {
       
  2631     unsigned char c = (unsigned char)a.at(i);
       
  2632     
       
  2633     // treat characters > 0x80 as multibyte characters, except when they
       
  2634     // are control characters 
       
  2635     if (c>0x80 || (mbFlag && c!='\\' && c!='{' && c!='}'))
       
  2636     {
       
  2637       char s[10];
       
  2638       sprintf(s,"\\'%X",c);
       
  2639       qstrcpy(enc.data()+off,s);
       
  2640       off+=qstrlen(s);
       
  2641       mbFlag=c>0x80;
       
  2642     }
       
  2643     else
       
  2644     {
       
  2645       enc.at(off++)=c;
       
  2646     }
       
  2647   }
       
  2648   enc.resize(off);
       
  2649   a = enc;
       
  2650 }
       
  2651 
       
  2652 void RTFGenerator::startConstraintList(const char *header)
       
  2653 {
       
  2654   DBG_RTF(t << "{\\comment (startConstraintList)}"    << endl)
       
  2655   t << "{"; // ends at endConstraintList
       
  2656   t << "{"; 
       
  2657   startBold();
       
  2658   newParagraph();
       
  2659   docify(header);
       
  2660   endBold();
       
  2661   t << "}";
       
  2662   newParagraph();
       
  2663   incrementIndentLevel();
       
  2664   t << rtf_Style_Reset << rtf_DList_DepthStyle();
       
  2665 }
       
  2666 
       
  2667 void RTFGenerator::startConstraintParam()
       
  2668 {
       
  2669   DBG_RTF(t << "{\\comment (startConstraintParam)}"    << endl)
       
  2670   startEmphasis();
       
  2671 }
       
  2672 
       
  2673 void RTFGenerator::endConstraintParam()
       
  2674 {
       
  2675   DBG_RTF(t << "{\\comment (endConstraintParam)}"    << endl)
       
  2676   endEmphasis();
       
  2677   t << " : ";
       
  2678 }
       
  2679 
       
  2680 void RTFGenerator::startConstraintType()
       
  2681 {
       
  2682   DBG_RTF(t << "{\\comment (startConstraintType)}"    << endl)
       
  2683   startEmphasis();
       
  2684 }
       
  2685 
       
  2686 void RTFGenerator::endConstraintType()
       
  2687 {
       
  2688   DBG_RTF(t << "{\\comment (endConstraintType)}"    << endl)
       
  2689   endEmphasis();
       
  2690   t << " ";
       
  2691 }
       
  2692 
       
  2693 void RTFGenerator::startConstraintDocs()
       
  2694 {
       
  2695   DBG_RTF(t << "{\\comment (startConstraintDocs)}"    << endl)
       
  2696 }
       
  2697 
       
  2698 void RTFGenerator::endConstraintDocs()
       
  2699 {
       
  2700   DBG_RTF(t << "{\\comment (endConstraintDocs)}"    << endl)
       
  2701   newParagraph();
       
  2702 }
       
  2703 
       
  2704 void RTFGenerator::endConstraintList()
       
  2705 {
       
  2706   DBG_RTF(t << "{\\comment (endConstraintList)}"    << endl)
       
  2707   newParagraph();
       
  2708   decrementIndentLevel();
       
  2709   m_omitParagraph = TRUE;
       
  2710   t << "}";
       
  2711 }
       
  2712 
       
  2713 
       
  2714 
       
  2715