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