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