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