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