1 /******************************************************************************
2 *
3 *
4 *
5 *
6 * Copyright (C) 1997-2015 by Dimitri van Heesch.
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation under the terms of the GNU General Public License is hereby
10 * granted. No representations are made about the suitability of this software
11 * for any purpose. It is provided "as is" without express or implied warranty.
12 * See the GNU General Public License for more details.
13 *
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
16 *
17 */
18
19 #include <algorithm>
20
21 #include "rtfdocvisitor.h"
22 #include "docparser.h"
23 #include "language.h"
24 #include "doxygen.h"
25 #include "outputgen.h"
26 #include "dot.h"
27 #include "msc.h"
28 #include "util.h"
29 #include "rtfstyle.h"
30 #include "message.h"
31 #include "parserintf.h"
32 #include "msc.h"
33 #include "dia.h"
34 #include "filedef.h"
35 #include "config.h"
36 #include "htmlentity.h"
37 #include "emoji.h"
38 #include "plantuml.h"
39 #include "fileinfo.h"
40
41 //#define DBG_RTF(x) m_t << x
42 #define DBG_RTF(x) do {} while(0)
43
align(DocHtmlCell * cell)44 static QCString align(DocHtmlCell *cell)
45 {
46 for (const auto &attr : cell->attribs())
47 {
48 if (attr.name.lower()=="align")
49 {
50 if (attr.value.lower()=="center") return "\\qc ";
51 else if (attr.value.lower()=="right") return "\\qr ";
52 else return "";
53 }
54 }
55 return "";
56 }
57
RTFDocVisitor(TextStream & t,CodeOutputInterface & ci,const QCString & langExt)58 RTFDocVisitor::RTFDocVisitor(TextStream &t,CodeOutputInterface &ci,
59 const QCString &langExt)
60 : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_langExt(langExt)
61 {
62 }
63
getStyle(const QCString & name)64 QCString RTFDocVisitor::getStyle(const QCString &name)
65 {
66 QCString n = name + QCString().setNum(indentLevel());
67 StyleData &sd = rtf_Style[n.str()];
68 return sd.reference();
69 }
70
indentLevel() const71 int RTFDocVisitor::indentLevel() const
72 {
73 return std::min(m_indentLevel,maxIndentLevels-1);
74 }
75
incIndentLevel()76 void RTFDocVisitor::incIndentLevel()
77 {
78 m_indentLevel++;
79 if (m_indentLevel>=maxIndentLevels)
80 {
81 err("Maximum indent level (%d) exceeded while generating RTF output!\n",maxIndentLevels-1);
82 }
83 }
84
decIndentLevel()85 void RTFDocVisitor::decIndentLevel()
86 {
87 if (m_indentLevel>0) m_indentLevel--;
88 }
89
90 //------------------------------------
91 // visitor functions for leaf nodes
92 //--------------------------------------
93
visit(DocWord * w)94 void RTFDocVisitor::visit(DocWord *w)
95 {
96 if (m_hide) return;
97 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWord)}\n");
98 filter(w->word());
99 m_lastIsPara=FALSE;
100 }
101
visit(DocLinkedWord * w)102 void RTFDocVisitor::visit(DocLinkedWord *w)
103 {
104 if (m_hide) return;
105 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLinkedWord)}\n");
106 startLink(w->ref(),w->file(),w->anchor());
107 filter(w->word());
108 endLink(w->ref());
109 m_lastIsPara=FALSE;
110 }
111
visit(DocWhiteSpace * w)112 void RTFDocVisitor::visit(DocWhiteSpace *w)
113 {
114 if (m_hide) return;
115 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWhiteSpace)}\n");
116 if (m_insidePre)
117 {
118 m_t << w->chars();
119 }
120 else
121 {
122 m_t << " ";
123 }
124 m_lastIsPara=FALSE;
125 }
126
visit(DocSymbol * s)127 void RTFDocVisitor::visit(DocSymbol *s)
128 {
129 if (m_hide) return;
130 DBG_RTF("{\\comment RTFDocVisitor::visit(DocSymbol)}\n");
131 const char *res = HtmlEntityMapper::instance()->rtf(s->symbol());
132 if (res)
133 {
134 m_t << res;
135 }
136 else
137 {
138 err("RTF: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
139 }
140 m_lastIsPara=FALSE;
141 }
142
visit(DocEmoji * s)143 void RTFDocVisitor::visit(DocEmoji *s)
144 {
145 if (m_hide) return;
146 DBG_RTF("{\\comment RTFDocVisitor::visit(DocEmoji)}\n");
147 const char *res = EmojiEntityMapper::instance()->unicode(s->index());
148 if (res)
149 {
150 const char *p = res;
151 int val = 0;
152 int val1 = 0;
153 while (*p)
154 {
155 switch(*p)
156 {
157 case '&': case '#': case 'x':
158 break;
159 case ';':
160 val1 = val;
161 val = 0xd800 + ( ( val1 - 0x10000 ) & 0xffc00 ) / 0x400 - 0x10000;
162 m_t << "\\u" << val << "?";
163 val = 0xdC00 + ( ( val1 - 0x10000 ) & 0x3ff ) - 0x10000 ;
164 m_t << "\\u" << val << "?";
165 val = 0;
166 break;
167 case '0': case '1': case '2': case '3': case '4':
168 case '5': case '6': case '7': case '8': case '9':
169 val = val * 16 + *p - '0';
170 break;
171 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
172 val = val * 16 + *p - 'a' + 10;
173 break;
174 }
175 p++;
176 }
177 }
178 else
179 {
180 m_t << s->name();
181 }
182 m_lastIsPara=FALSE;
183 }
184
visit(DocURL * u)185 void RTFDocVisitor::visit(DocURL *u)
186 {
187 if (m_hide) return;
188 DBG_RTF("{\\comment RTFDocVisitor::visit(DocURL)}\n");
189 if (Config_getBool(RTF_HYPERLINKS))
190 {
191 m_t << "{\\field "
192 "{\\*\\fldinst "
193 "{ HYPERLINK \"";
194 if (u->isEmail()) m_t << "mailto:";
195 m_t << u->url();
196 m_t << "\" }"
197 "{}";
198 m_t << "}"
199 "{\\fldrslt "
200 "{\\cs37\\ul\\cf2 ";
201 filter(u->url());
202 m_t << "}"
203 "}"
204 "}\n";
205 }
206 else
207 {
208 m_t << "{\\f2 ";
209 filter(u->url());
210 m_t << "}";
211 }
212 m_lastIsPara=FALSE;
213 }
214
visit(DocLineBreak *)215 void RTFDocVisitor::visit(DocLineBreak *)
216 {
217 if (m_hide) return;
218 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLineBreak)}\n");
219 m_t << "\\par\n";
220 m_lastIsPara=TRUE;
221 }
222
visit(DocHorRuler *)223 void RTFDocVisitor::visit(DocHorRuler *)
224 {
225 if (m_hide) return;
226 DBG_RTF("{\\comment RTFDocVisitor::visit(DocHorRuler)}\n");
227 m_t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}\n";
228 m_lastIsPara=TRUE;
229 }
230
visit(DocStyleChange * s)231 void RTFDocVisitor::visit(DocStyleChange *s)
232 {
233 if (m_hide) return;
234 m_lastIsPara=FALSE;
235 DBG_RTF("{\\comment RTFDocVisitor::visit(DocStyleChange)}\n");
236 switch (s->style())
237 {
238 case DocStyleChange::Bold:
239 if (s->enable()) m_t << "{\\b "; else m_t << "} ";
240 break;
241 case DocStyleChange::S:
242 case DocStyleChange::Strike:
243 case DocStyleChange::Del:
244 if (s->enable()) m_t << "{\\strike "; else m_t << "} ";
245 break;
246 case DocStyleChange::Underline:
247 case DocStyleChange::Ins:
248 if (s->enable()) m_t << "{\\ul "; else m_t << "} ";
249 break;
250 case DocStyleChange::Italic:
251 if (s->enable()) m_t << "{\\i "; else m_t << "} ";
252 break;
253 case DocStyleChange::Code:
254 if (s->enable()) m_t << "{\\f2 "; else m_t << "} ";
255 break;
256 case DocStyleChange::Subscript:
257 if (s->enable()) m_t << "{\\sub "; else m_t << "} ";
258 break;
259 case DocStyleChange::Superscript:
260 if (s->enable()) m_t << "{\\super "; else m_t << "} ";
261 break;
262 case DocStyleChange::Center:
263 if (s->enable()) m_t << "{\\qc "; else m_t << "} ";
264 break;
265 case DocStyleChange::Small:
266 if (s->enable()) m_t << "{\\sub "; else m_t << "} ";
267 break;
268 case DocStyleChange::Cite:
269 if (s->enable()) m_t << "{\\i "; else m_t << "} ";
270 break;
271 case DocStyleChange::Preformatted:
272 if (s->enable())
273 {
274 m_t << "{\n";
275 m_t << "\\par\n";
276 m_t << rtf_Style_Reset << getStyle("CodeExample");
277 m_insidePre=TRUE;
278 }
279 else
280 {
281 m_insidePre=FALSE;
282 m_t << "\\par";
283 m_t << "}\n";
284 }
285 m_lastIsPara=TRUE;
286 break;
287 case DocStyleChange::Div: /* HTML only */ break;
288 case DocStyleChange::Span: /* HTML only */ break;
289 case DocStyleChange::Details: /* emulation of the <details> tag */
290 if (s->enable())
291 {
292 m_t << "{\n";
293 m_t << "\\par\n";
294 }
295 else
296 {
297 m_t << "\\par";
298 m_t << "}\n";
299 }
300 m_lastIsPara=TRUE;
301 break;
302 case DocStyleChange::Summary: /* emulation of the <summary> tag inside a <details> tag */
303 if (s->enable()) m_t << "{\\b "; else m_t << "} ";
304 break;
305 }
306 }
307
visitCaption(RTFDocVisitor * parent,const DocNodeList & children)308 static void visitCaption(RTFDocVisitor *parent, const DocNodeList &children)
309 {
310 for (const auto &n : children) n->accept(parent);
311 }
312
visit(DocVerbatim * s)313 void RTFDocVisitor::visit(DocVerbatim *s)
314 {
315 if (m_hide) return;
316 DBG_RTF("{\\comment RTFDocVisitor::visit(DocVerbatim)}\n");
317 QCString lang = m_langExt;
318 if (!s->language().isEmpty()) // explicit language setting
319 {
320 lang = s->language();
321 }
322 SrcLangExt langExt = getLanguageFromCodeLang(lang);
323 switch(s->type())
324 {
325 case DocVerbatim::Code:
326 m_t << "{\n";
327 m_t << "\\par\n";
328 m_t << rtf_Style_Reset << getStyle("CodeExample");
329 getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt,
330 s->isExample(),s->exampleFile());
331 //m_t << "\\par\n";
332 m_t << "}\n";
333 break;
334 case DocVerbatim::JavaDocLiteral:
335 filter(s->text(),TRUE);
336 break;
337 case DocVerbatim::JavaDocCode:
338 m_t << "{\n";
339 m_t << "{\\f2 ";
340 filter(s->text(),TRUE);
341 m_t << "}";
342 m_t << "}\n";
343 break;
344 case DocVerbatim::Verbatim:
345 m_t << "{\n";
346 m_t << "\\par\n";
347 m_t << rtf_Style_Reset << getStyle("CodeExample");
348 filter(s->text(),TRUE);
349 //m_t << "\\par\n";
350 m_t << "}\n";
351 break;
352 case DocVerbatim::RtfOnly:
353 m_t << s->text();
354 break;
355 case DocVerbatim::HtmlOnly:
356 case DocVerbatim::LatexOnly:
357 case DocVerbatim::XmlOnly:
358 case DocVerbatim::ManOnly:
359 case DocVerbatim::DocbookOnly:
360 /* nothing */
361 break;
362 case DocVerbatim::Dot:
363 {
364 static int dotindex = 1;
365 QCString fileName(4096);
366
367 fileName.sprintf("%s%d%s",
368 qPrint(Config_getString(RTF_OUTPUT)+"/inline_dotgraph_"),
369 dotindex++,
370 ".dot"
371 );
372 std::ofstream file(fileName.str(),std::ofstream::out | std::ofstream::binary);
373 if (!file.is_open())
374 {
375 err("Could not open file %s for writing\n",qPrint(fileName));
376 }
377 else
378 {
379 QCString stext = s->text();
380 file.write( stext.data(), stext.length() );
381 file.close();
382 }
383
384 writeDotFile(fileName, s->hasCaption(), s->srcFile(), s->srcLine());
385 visitCaption(this, s->children());
386 includePicturePostRTF(true, s->hasCaption());
387
388 if (Config_getBool(DOT_CLEANUP)) Dir().remove(fileName.str());
389 }
390 break;
391 case DocVerbatim::Msc:
392 {
393 static int mscindex = 1;
394 QCString baseName(4096);
395
396 baseName.sprintf("%s%d%s",
397 qPrint(Config_getString(RTF_OUTPUT)+"/inline_mscgraph_"),
398 mscindex++,
399 ".msc"
400 );
401 std::ofstream file(baseName.str(),std::ofstream::out | std::ofstream::binary);
402 if (!file.is_open())
403 {
404 err("Could not open file %s for writing\n",qPrint(baseName));
405 }
406 QCString text = "msc {";
407 text+=s->text();
408 text+="}";
409 file.write( text.data(), text.length() );
410 file.close();
411
412 writeMscFile(baseName, s->hasCaption(), s->srcFile(), s->srcLine());
413 visitCaption(this, s->children());
414 includePicturePostRTF(true, s->hasCaption());
415
416 if (Config_getBool(DOT_CLEANUP)) Dir().remove(baseName.str());
417 }
418 break;
419 case DocVerbatim::PlantUML:
420 {
421 static QCString rtfOutput = Config_getString(RTF_OUTPUT);
422 QCString baseName = PlantumlManager::instance().writePlantUMLSource(
423 rtfOutput,s->exampleFile(),s->text(),PlantumlManager::PUML_BITMAP,
424 s->engine(),s->srcFile(),s->srcLine());
425
426 writePlantUMLFile(baseName, s->hasCaption());
427 visitCaption(this, s->children());
428 includePicturePostRTF(true, s->hasCaption());
429 }
430 break;
431 }
432 m_lastIsPara=FALSE;
433 }
434
visit(DocAnchor * anc)435 void RTFDocVisitor::visit(DocAnchor *anc)
436 {
437 if (m_hide) return;
438 DBG_RTF("{\\comment RTFDocVisitor::visit(DocAnchor)}\n");
439 QCString anchor;
440 if (!anc->file().isEmpty())
441 {
442 anchor+=stripPath(anc->file());
443 }
444 if (!anc->file().isEmpty() && !anc->anchor().isEmpty())
445 {
446 anchor+="_";
447 }
448 if (!anc->anchor().isEmpty())
449 {
450 anchor+=anc->anchor();
451 }
452 m_t << "{\\bkmkstart " << rtfFormatBmkStr(anchor) << "}\n";
453 m_t << "{\\bkmkend " << rtfFormatBmkStr(anchor) << "}\n";
454 m_lastIsPara=FALSE;
455 }
456
visit(DocInclude * inc)457 void RTFDocVisitor::visit(DocInclude *inc)
458 {
459 if (m_hide) return;
460 SrcLangExt langExt = getLanguageFromFileName(inc->extension());
461 DBG_RTF("{\\comment RTFDocVisitor::visit(DocInclude)}\n");
462 switch(inc->type())
463 {
464 case DocInclude::IncWithLines:
465 {
466 m_t << "{\n";
467 m_t << "\\par\n";
468 m_t << rtf_Style_Reset << getStyle("CodeExample");
469 FileInfo cfi( inc->file().str() );
470 FileDef *fd = createFileDef( cfi.dirPath(), cfi.fileName() );
471 getCodeParser(inc->extension()).parseCode(m_ci,inc->context(),
472 inc->text(),
473 langExt,
474 inc->isExample(),
475 inc->exampleFile(),
476 fd, // fileDef,
477 -1, // start line
478 -1, // end line
479 FALSE, // inline fragment
480 0, // memberDef
481 TRUE // show line numbers
482 );
483 delete fd;
484 m_t << "\\par";
485 m_t << "}\n";
486 }
487 break;
488 case DocInclude::Include:
489 m_t << "{\n";
490 m_t << "\\par\n";
491 m_t << rtf_Style_Reset << getStyle("CodeExample");
492 getCodeParser(inc->extension()).parseCode(m_ci,inc->context(),
493 inc->text(),langExt,inc->isExample(),
494 inc->exampleFile(),
495 0, // fileDef
496 -1, // startLine
497 -1, // endLine
498 TRUE, // inlineFragment
499 0, // memberDef
500 FALSE // show line numbers
501 );
502 m_t << "\\par";
503 m_t << "}\n";
504 break;
505 case DocInclude::DontInclude:
506 case DocInclude::DontIncWithLines:
507 case DocInclude::HtmlInclude:
508 case DocInclude::LatexInclude:
509 case DocInclude::ManInclude:
510 case DocInclude::XmlInclude:
511 case DocInclude::DocbookInclude:
512 break;
513 case DocInclude::RtfInclude:
514 m_t << inc->text();
515 break;
516 case DocInclude::VerbInclude:
517 m_t << "{\n";
518 m_t << "\\par\n";
519 m_t << rtf_Style_Reset << getStyle("CodeExample");
520 filter(inc->text());
521 m_t << "\\par";
522 m_t << "}\n";
523 break;
524 case DocInclude::Snippet:
525 m_t << "{\n";
526 if (!m_lastIsPara) m_t << "\\par\n";
527 m_t << rtf_Style_Reset << getStyle("CodeExample");
528 getCodeParser(inc->extension()).parseCode(m_ci,
529 inc->context(),
530 extractBlock(inc->text(),inc->blockId()),
531 langExt,
532 inc->isExample(),
533 inc->exampleFile()
534 );
535 m_t << "}";
536 break;
537 case DocInclude::SnipWithLines:
538 {
539 FileInfo cfi( inc->file().str() );
540 FileDef *fd = createFileDef( cfi.dirPath(), cfi.fileName() );
541 m_t << "{\n";
542 if (!m_lastIsPara) m_t << "\\par\n";
543 m_t << rtf_Style_Reset << getStyle("CodeExample");
544 getCodeParser(inc->extension()).parseCode(m_ci,
545 inc->context(),
546 extractBlock(inc->text(),inc->blockId()),
547 langExt,
548 inc->isExample(),
549 inc->exampleFile(),
550 fd,
551 lineBlock(inc->text(),inc->blockId()),
552 -1, // endLine
553 FALSE, // inlineFragment
554 0, // memberDef
555 TRUE // show line number
556 );
557 delete fd;
558 m_t << "}";
559 }
560 break;
561 case DocInclude::SnippetDoc:
562 case DocInclude::IncludeDoc:
563 err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
564 "Please create a bug report\n",__FILE__);
565 break;
566 }
567 m_lastIsPara=TRUE;
568 }
569
visit(DocIncOperator * op)570 void RTFDocVisitor::visit(DocIncOperator *op)
571 {
572 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
573 // op->type(),op->isFirst(),op->isLast(),qPrint(op->text()));
574 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIncOperator)}\n");
575 QCString locLangExt = getFileNameExtension(op->includeFileName());
576 if (locLangExt.isEmpty()) locLangExt = m_langExt;
577 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
578 if (op->isFirst())
579 {
580 if (!m_hide)
581 {
582 m_t << "{\n";
583 m_t << "\\par\n";
584 m_t << rtf_Style_Reset << getStyle("CodeExample");
585 }
586 pushHidden(m_hide);
587 m_hide = TRUE;
588 }
589 if (op->type()!=DocIncOperator::Skip)
590 {
591 m_hide = popHidden();
592 if (!m_hide)
593 {
594 FileDef *fd = 0;
595 if (!op->includeFileName().isEmpty())
596 {
597 FileInfo cfi( op->includeFileName().str() );
598 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
599 }
600
601 getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt,
602 op->isExample(),op->exampleFile(),
603 fd, // fileDef
604 op->line(), // startLine
605 -1, // endLine
606 FALSE, // inline fragment
607 0, // memberDef
608 op->showLineNo() // show line numbers
609 );
610 if (fd) delete fd;
611 }
612 pushHidden(m_hide);
613 m_hide=TRUE;
614 }
615 if (op->isLast())
616 {
617 m_hide = popHidden();
618 if (!m_hide)
619 {
620 m_t << "\\par";
621 m_t << "}\n";
622 }
623 m_lastIsPara=TRUE;
624 }
625 else
626 {
627 if (!m_hide) m_t << "\n";
628 m_lastIsPara=FALSE;
629 }
630 }
631
visit(DocFormula * f)632 void RTFDocVisitor::visit(DocFormula *f)
633 {
634 if (m_hide) return;
635 DBG_RTF("{\\comment RTFDocVisitor::visit(DocFormula)}\n");
636 bool bDisplay = !f->isInline();
637 if (bDisplay)
638 {
639 m_t << "\\par";
640 m_t << "{";
641 m_t << "\\pard\\plain";
642 m_t << "\\pard";
643 m_t << "\\qc";
644 }
645 m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"" << f->relPath() << f->name() << ".png\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}";
646 if (bDisplay)
647 {
648 m_t << "\\par}";
649 }
650 m_lastIsPara=FALSE;
651 }
652
visit(DocIndexEntry * i)653 void RTFDocVisitor::visit(DocIndexEntry *i)
654 {
655 if (m_hide) return;
656 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIndexEntry)}\n");
657 m_t << "{\\xe \\v " << i->entry() << "}\n";
658 m_lastIsPara=FALSE;
659 }
660
visit(DocSimpleSectSep *)661 void RTFDocVisitor::visit(DocSimpleSectSep *)
662 {
663 }
664
visit(DocCite * cite)665 void RTFDocVisitor::visit(DocCite *cite)
666 {
667 if (m_hide) return;
668 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCite)}\n");
669 if (!cite->file().isEmpty())
670 {
671 startLink(cite->ref(),cite->file(),cite->anchor());
672 }
673 else
674 {
675 m_t << "{\\b ";
676 }
677 filter(cite->text());
678 if (!cite->file().isEmpty())
679 {
680 endLink(cite->ref());
681 }
682 else
683 {
684 m_t << "}";
685 }
686 }
687
688
689 //--------------------------------------
690 // visitor functions for compound nodes
691 //--------------------------------------
692
visitPre(DocAutoList * l)693 void RTFDocVisitor::visitPre(DocAutoList *l)
694 {
695 if (m_hide) return;
696 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoList)}\n");
697 m_t << "{\n";
698 int level = indentLevel();
699 m_listItemInfo[level].isEnum = l->isEnumList();
700 m_listItemInfo[level].type = '1';
701 m_listItemInfo[level].number = 1;
702 m_lastIsPara=FALSE;
703 }
704
visitPost(DocAutoList *)705 void RTFDocVisitor::visitPost(DocAutoList *)
706 {
707 if (m_hide) return;
708 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoList)}\n");
709 if (!m_lastIsPara) m_t << "\\par";
710 m_t << "}\n";
711 m_lastIsPara=TRUE;
712 if (indentLevel()==0) m_t << "\\par\n";
713 }
714
visitPre(DocAutoListItem *)715 void RTFDocVisitor::visitPre(DocAutoListItem *)
716 {
717 if (m_hide) return;
718 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoListItem)}\n");
719 if (!m_lastIsPara) m_t << "\\par\n";
720 m_t << rtf_Style_Reset;
721 int level = indentLevel();
722 if (m_listItemInfo[level].isEnum)
723 {
724 m_t << getStyle("ListEnum") << "\n";
725 m_t << m_listItemInfo[level].number << ".\\tab ";
726 m_listItemInfo[level].number++;
727 }
728 else
729 {
730 m_t << getStyle("ListBullet") << "\n";
731 }
732 incIndentLevel();
733 m_lastIsPara=FALSE;
734 }
735
visitPost(DocAutoListItem *)736 void RTFDocVisitor::visitPost(DocAutoListItem *)
737 {
738 decIndentLevel();
739 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoListItem)}\n");
740 }
741
visitPre(DocPara *)742 void RTFDocVisitor::visitPre(DocPara *)
743 {
744 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
745 }
746
visitPost(DocPara * p)747 void RTFDocVisitor::visitPost(DocPara *p)
748 {
749 if (m_hide) return;
750 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
751 if (!m_lastIsPara &&
752 !p->isLast() && // omit <p> for last paragraph
753 !(p->parent() && // and for parameters & sections
754 p->parent()->kind()==DocNode::Kind_ParamSect
755 )
756 )
757 {
758 m_t << "\\par\n";
759 m_lastIsPara=TRUE;
760 }
761 }
762
visitPre(DocRoot * r)763 void RTFDocVisitor::visitPre(DocRoot *r)
764 {
765 if (m_hide) return;
766 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRoot)}\n");
767 if (r->indent()) incIndentLevel();
768 m_t << "{" << rtf_Style["BodyText"].reference() << "\n";
769 }
770
visitPost(DocRoot * r)771 void RTFDocVisitor::visitPost(DocRoot *r)
772 {
773 if (m_hide) return;
774 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRoot)}\n");
775 if (!m_lastIsPara && !r->singleLine()) m_t << "\\par\n";
776 m_t << "}";
777 m_lastIsPara=TRUE;
778 if (r->indent()) decIndentLevel();
779 }
780
visitPre(DocSimpleSect * s)781 void RTFDocVisitor::visitPre(DocSimpleSect *s)
782 {
783 if (m_hide) return;
784 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
785 if (!m_lastIsPara) m_t << "\\par\n";
786 m_t << "{"; // start desc
787 //m_t << "{\\b "; // start bold
788 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
789 switch(s->type())
790 {
791 case DocSimpleSect::See:
792 m_t << theTranslator->trSeeAlso(); break;
793 case DocSimpleSect::Return:
794 m_t << theTranslator->trReturns(); break;
795 case DocSimpleSect::Author:
796 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
797 case DocSimpleSect::Authors:
798 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
799 case DocSimpleSect::Version:
800 m_t << theTranslator->trVersion(); break;
801 case DocSimpleSect::Since:
802 m_t << theTranslator->trSince(); break;
803 case DocSimpleSect::Date:
804 m_t << theTranslator->trDate(); break;
805 case DocSimpleSect::Note:
806 m_t << theTranslator->trNote(); break;
807 case DocSimpleSect::Warning:
808 m_t << theTranslator->trWarning(); break;
809 case DocSimpleSect::Pre:
810 m_t << theTranslator->trPrecondition(); break;
811 case DocSimpleSect::Post:
812 m_t << theTranslator->trPostcondition(); break;
813 case DocSimpleSect::Copyright:
814 m_t << theTranslator->trCopyright(); break;
815 case DocSimpleSect::Invar:
816 m_t << theTranslator->trInvariant(); break;
817 case DocSimpleSect::Remark:
818 m_t << theTranslator->trRemarks(); break;
819 case DocSimpleSect::Attention:
820 m_t << theTranslator->trAttention(); break;
821 case DocSimpleSect::User: break;
822 case DocSimpleSect::Rcs: break;
823 case DocSimpleSect::Unknown: break;
824 }
825
826 // special case 1: user defined title
827 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
828 {
829 m_t << "\\par";
830 m_t << "}"; // end bold
831 incIndentLevel();
832 m_t << rtf_Style_Reset << getStyle("DescContinue");
833 m_t << "{\\s17 \\sa60 \\sb30\n";
834 }
835 m_lastIsPara=FALSE;
836 }
837
visitPost(DocSimpleSect * s)838 void RTFDocVisitor::visitPost(DocSimpleSect *s)
839 {
840 if (m_hide) return;
841 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
842 if (!m_lastIsPara) m_t << "\\par\n";
843 decIndentLevel();
844 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) m_t << "}";
845 m_t << "}"; // end desc
846 m_lastIsPara=TRUE;
847 }
848
visitPre(DocTitle *)849 void RTFDocVisitor::visitPre(DocTitle *)
850 {
851 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocTitle)}\n");
852 }
853
visitPost(DocTitle *)854 void RTFDocVisitor::visitPost(DocTitle *)
855 {
856 if (m_hide) return;
857 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocTitle)}\n");
858 m_t << "\\par\n";
859 m_t << "}"; // end bold
860 incIndentLevel();
861 m_t << rtf_Style_Reset << getStyle("DescContinue");
862 m_lastIsPara=FALSE;
863 }
864
visitPre(DocSimpleList *)865 void RTFDocVisitor::visitPre(DocSimpleList *)
866 {
867 if (m_hide) return;
868 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
869 m_t << "{\n";
870 m_listItemInfo[indentLevel()].isEnum = FALSE;
871 m_lastIsPara=FALSE;
872 }
873
visitPost(DocSimpleList *)874 void RTFDocVisitor::visitPost(DocSimpleList *)
875 {
876 if (m_hide) return;
877 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
878 if (!m_lastIsPara) m_t << "\\par\n";
879 m_t << "}\n";
880 m_lastIsPara=TRUE;
881 }
882
visitPre(DocSimpleListItem *)883 void RTFDocVisitor::visitPre(DocSimpleListItem *)
884 {
885 if (m_hide) return;
886 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleListItem)}\n");
887 m_t << "\\par" << rtf_Style_Reset << getStyle("ListBullet") << "\n";
888 m_lastIsPara=FALSE;
889 incIndentLevel();
890 }
891
visitPost(DocSimpleListItem *)892 void RTFDocVisitor::visitPost(DocSimpleListItem *)
893 {
894 decIndentLevel();
895 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleListItem)}\n");
896 }
897
visitPre(DocSection * s)898 void RTFDocVisitor::visitPre(DocSection *s)
899 {
900 if (m_hide) return;
901 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSection)}\n");
902 if (!m_lastIsPara) m_t << "\\par\n";
903 m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(s->file())+"_"+s->anchor()) << "}\n";
904 m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(s->file())+"_"+s->anchor()) << "}\n";
905 m_t << "{{" // start section
906 << rtf_Style_Reset;
907 QCString heading;
908 int level = std::min(s->level()+1,4);
909 heading.sprintf("Heading%d",level);
910 // set style
911 m_t << rtf_Style[heading.str()].reference() << "\n";
912 // make table of contents entry
913 filter(s->title());
914 m_t << "\n\\par" << "}\n";
915 m_t << "{\\tc\\tcl" << level << " \\v ";
916 filter(s->title());
917 m_t << "}\n";
918 m_lastIsPara=TRUE;
919 }
920
visitPost(DocSection *)921 void RTFDocVisitor::visitPost(DocSection *)
922 {
923 if (m_hide) return;
924 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSection)}\n");
925 m_t << "\\par}\n"; // end section
926 m_lastIsPara=TRUE;
927 }
928
visitPre(DocHtmlList * l)929 void RTFDocVisitor::visitPre(DocHtmlList *l)
930 {
931 if (m_hide) return;
932 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlList)}\n");
933 m_t << "{\n";
934 int level = indentLevel();
935 m_listItemInfo[level].isEnum = l->type()==DocHtmlList::Ordered;
936 m_listItemInfo[level].number = 1;
937 m_listItemInfo[level].type = '1';
938 for (const auto &opt : l->attribs())
939 {
940 if (opt.name=="type")
941 {
942 m_listItemInfo[level].type = opt.value[0];
943 }
944 if (opt.name=="start")
945 {
946 bool ok;
947 int val = opt.value.toInt(&ok);
948 if (ok) m_listItemInfo[level].number = val;
949 }
950 }
951 m_lastIsPara=FALSE;
952 }
953
visitPost(DocHtmlList *)954 void RTFDocVisitor::visitPost(DocHtmlList *)
955 {
956 if (m_hide) return;
957 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlList)}\n");
958 m_t << "\\par" << "}\n";
959 m_lastIsPara=TRUE;
960 }
961
visitPre(DocHtmlListItem * l)962 void RTFDocVisitor::visitPre(DocHtmlListItem *l)
963 {
964 if (m_hide) return;
965 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlListItem)}\n");
966 m_t << "\\par\n";
967 m_t << rtf_Style_Reset;
968 int level = indentLevel();
969 if (m_listItemInfo[level].isEnum)
970 {
971 for (const auto &opt : l->attribs())
972 {
973 if (opt.name=="value")
974 {
975 bool ok;
976 int val = opt.value.toInt(&ok);
977 if (ok) m_listItemInfo[level].number = val;
978 }
979 }
980 m_t << getStyle("ListEnum") << "\n";
981 switch (m_listItemInfo[level].type)
982 {
983 case '1':
984 m_t << m_listItemInfo[level].number;
985 break;
986 case 'a':
987 m_t << integerToAlpha(m_listItemInfo[level].number,false);
988 break;
989 case 'A':
990 m_t << integerToAlpha(m_listItemInfo[level].number);
991 break;
992 case 'i':
993 m_t << integerToRoman(m_listItemInfo[level].number,false);
994 break;
995 case 'I':
996 m_t << integerToRoman(m_listItemInfo[level].number);
997 break;
998 default:
999 m_t << m_listItemInfo[level].number;
1000 break;
1001 }
1002 m_t << ".\\tab ";
1003 m_listItemInfo[level].number++;
1004 }
1005 else
1006 {
1007 m_t << getStyle("ListBullet") << "\n";
1008 }
1009 incIndentLevel();
1010 m_lastIsPara=FALSE;
1011 }
1012
visitPost(DocHtmlListItem *)1013 void RTFDocVisitor::visitPost(DocHtmlListItem *)
1014 {
1015 decIndentLevel();
1016 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlListItem)}\n");
1017 }
1018
visitPre(DocHtmlDescList *)1019 void RTFDocVisitor::visitPre(DocHtmlDescList *)
1020 {
1021 if (m_hide) return;
1022 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescList)}\n");
1023 //m_t << "{\n";
1024 //m_t << rtf_Style_Reset << getStyle("ListContinue");
1025 //m_lastIsPara=FALSE;
1026 }
1027
visitPost(DocHtmlDescList *)1028 void RTFDocVisitor::visitPost(DocHtmlDescList *)
1029 {
1030 if (m_hide) return;
1031 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescList)}\n");
1032 //m_t << "}\n";
1033 //m_t << "\\par\n";
1034 //m_lastIsPara=TRUE;
1035 }
1036
visitPre(DocHtmlDescTitle *)1037 void RTFDocVisitor::visitPre(DocHtmlDescTitle *)
1038 {
1039 if (m_hide) return;
1040 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescTitle)}\n");
1041 //m_t << "\\par\n";
1042 //m_t << "{\\b ";
1043 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
1044 m_lastIsPara=FALSE;
1045 }
1046
visitPost(DocHtmlDescTitle *)1047 void RTFDocVisitor::visitPost(DocHtmlDescTitle *)
1048 {
1049 if (m_hide) return;
1050 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescTitle)}\n");
1051 m_t << "\\par\n";
1052 m_t << "}\n";
1053 m_lastIsPara=TRUE;
1054 }
1055
visitPre(DocHtmlDescData *)1056 void RTFDocVisitor::visitPre(DocHtmlDescData *)
1057 {
1058 if (m_hide) return;
1059 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescData)}\n");
1060 incIndentLevel();
1061 m_t << "{" << rtf_Style_Reset << getStyle("DescContinue");
1062 }
1063
visitPost(DocHtmlDescData *)1064 void RTFDocVisitor::visitPost(DocHtmlDescData *)
1065 {
1066 if (m_hide) return;
1067 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescData)}\n");
1068 m_t << "\\par";
1069 m_t << "}\n";
1070 decIndentLevel();
1071 m_lastIsPara=TRUE;
1072 }
1073
visitPre(DocHtmlTable * t)1074 void RTFDocVisitor::visitPre(DocHtmlTable *t)
1075 {
1076 if (m_hide) return;
1077 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlTable)}\n");
1078 if (!m_lastIsPara) m_t << "\\par\n";
1079 m_lastIsPara=TRUE;
1080 if (t->hasCaption())
1081 {
1082 DocHtmlCaption *c = t->caption();
1083 m_t << "\\pard \\qc \\b";
1084 if (!c->file().isEmpty())
1085 {
1086 m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(c->file())+"_"+c->anchor()) << "}\n";
1087 m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(c->file())+"_"+c->anchor()) << "}\n";
1088 }
1089 m_t << "{Table \\field\\flddirty{\\*\\fldinst { SEQ Table \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
1090 }
1091 }
1092
visitPost(DocHtmlTable *)1093 void RTFDocVisitor::visitPost(DocHtmlTable *)
1094 {
1095 if (m_hide) return;
1096 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlTable)}\n");
1097 m_t << "\\pard\\plain\n";
1098 m_t << "\\par\n";
1099 m_lastIsPara=TRUE;
1100 }
1101
visitPre(DocHtmlCaption *)1102 void RTFDocVisitor::visitPre(DocHtmlCaption *)
1103 {
1104 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCaption)}\n");
1105 // start of caption is handled in the RTFDocVisitor::visitPre(DocHtmlTable *t)
1106 }
1107
visitPost(DocHtmlCaption *)1108 void RTFDocVisitor::visitPost(DocHtmlCaption *)
1109 {
1110 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCaption)}\n");
1111 m_t << "}\n\\par\n";
1112 }
1113
visitPre(DocHtmlRow * r)1114 void RTFDocVisitor::visitPre(DocHtmlRow *r)
1115 {
1116 if (m_hide) return;
1117 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlRow)}\n");
1118 uint i,columnWidth=(uint)r->numCells()>0 ? rtf_pageWidth/(uint)r->numCells() : 10;
1119 m_t << "\\trowd \\trgaph108\\trleft-108"
1120 "\\trbrdrt\\brdrs\\brdrw10 "
1121 "\\trbrdrl\\brdrs\\brdrw10 "
1122 "\\trbrdrb\\brdrs\\brdrw10 "
1123 "\\trbrdrr\\brdrs\\brdrw10 "
1124 "\\trbrdrh\\brdrs\\brdrw10 "
1125 "\\trbrdrv\\brdrs\\brdrw10 \n";
1126 for (i=0;i<r->numCells();i++)
1127 {
1128 if (r->isHeading())
1129 {
1130 m_t << "\\clcbpat16"; // set cell shading to light grey (color 16 in the clut)
1131 }
1132 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 "
1133 "\\clbrdrl\\brdrs\\brdrw10 "
1134 "\\clbrdrb\\brdrs\\brdrw10 "
1135 "\\clbrdrr \\brdrs\\brdrw10 "
1136 "\\cltxlrtb "
1137 "\\cellx" << ((i+1)*columnWidth) << "\n";
1138 }
1139 m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1140 m_lastIsPara=FALSE;
1141 }
1142
visitPost(DocHtmlRow *)1143 void RTFDocVisitor::visitPost(DocHtmlRow *)
1144 {
1145 if (m_hide) return;
1146 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlRow)}\n");
1147 m_t << "\n";
1148 m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1149 m_t << "{\\row }\n";
1150 m_lastIsPara=FALSE;
1151 }
1152
visitPre(DocHtmlCell * c)1153 void RTFDocVisitor::visitPre(DocHtmlCell *c)
1154 {
1155 if (m_hide) return;
1156 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCell)}\n");
1157 m_t << "{" << align(c);
1158 m_lastIsPara=FALSE;
1159 }
1160
visitPost(DocHtmlCell *)1161 void RTFDocVisitor::visitPost(DocHtmlCell *)
1162 {
1163 if (m_hide) return;
1164 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCell)}\n");
1165 m_t << "\\cell }";
1166 m_lastIsPara=FALSE;
1167 }
1168
visitPre(DocInternal *)1169 void RTFDocVisitor::visitPre(DocInternal *)
1170 {
1171 if (m_hide) return;
1172 //DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternal)}\n");
1173 //m_t << "{"; // start desc
1174 //m_t << "{\\b "; // start bold
1175 //m_t << theTranslator->trForInternalUseOnly();
1176 //m_t << "}"; // end bold
1177 //m_t << "\\par\n";
1178 //incIndentLevel();
1179 //m_t << rtf_Style_Reset << getStyle("DescContinue");
1180 //m_lastIsPara=FALSE;
1181 }
1182
visitPost(DocInternal *)1183 void RTFDocVisitor::visitPost(DocInternal *)
1184 {
1185 if (m_hide) return;
1186 //DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternal)}\n");
1187 //m_t << "\\par";
1188 //decIndentLevel();
1189 //m_t << "}"; // end desc
1190 //m_lastIsPara=TRUE;
1191 }
1192
visitPre(DocHRef * href)1193 void RTFDocVisitor::visitPre(DocHRef *href)
1194 {
1195 if (m_hide) return;
1196 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHRef)}\n");
1197 if (Config_getBool(RTF_HYPERLINKS))
1198 {
1199 if (href->url().startsWith("#"))
1200 {
1201 // when starting with # so a local link
1202 QCString cite;
1203 cite = href->file() + "_" + href->url().right(href->url().length()-1);
1204 m_t << "{\\field "
1205 "{\\*\\fldinst "
1206 "{ HYPERLINK \\\\l \"" << rtfFormatBmkStr(cite) << "\" "
1207 "}{}"
1208 "}"
1209 "{\\fldrslt "
1210 "{\\cs37\\ul\\cf2 ";
1211 }
1212 else
1213 {
1214 m_t << "{\\field "
1215 "{\\*\\fldinst "
1216 "{ HYPERLINK \"" << href->url() << "\" "
1217 "}{}"
1218 "}"
1219 "{\\fldrslt "
1220 "{\\cs37\\ul\\cf2 ";
1221 }
1222 }
1223 else
1224 {
1225 m_t << "{\\f2 ";
1226 }
1227 m_lastIsPara=FALSE;
1228 }
1229
visitPost(DocHRef *)1230 void RTFDocVisitor::visitPost(DocHRef *)
1231 {
1232 if (m_hide) return;
1233 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHRef)}\n");
1234 if (Config_getBool(RTF_HYPERLINKS))
1235 {
1236 m_t << "}"
1237 "}"
1238 "}";
1239 }
1240 else
1241 {
1242 m_t << "}";
1243 }
1244 m_lastIsPara=FALSE;
1245 }
1246
visitPre(DocHtmlHeader * header)1247 void RTFDocVisitor::visitPre(DocHtmlHeader *header)
1248 {
1249 if (m_hide) return;
1250 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlHeader)}\n");
1251 m_t << "{" // start section
1252 << rtf_Style_Reset;
1253 QCString heading;
1254 int level = std::min(header->level(),5);
1255 heading.sprintf("Heading%d",level);
1256 // set style
1257 m_t << rtf_Style[heading.str()].reference();
1258 // make open table of contents entry that will be closed in visitPost method
1259 m_t << "{\\tc\\tcl" << level << " ";
1260 m_lastIsPara=FALSE;
1261 }
1262
visitPost(DocHtmlHeader *)1263 void RTFDocVisitor::visitPost(DocHtmlHeader *)
1264 {
1265 if (m_hide) return;
1266 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlHeader)}\n");
1267 // close open table of contents entry
1268 m_t << "} \\par";
1269 m_t << "}\n"; // end section
1270 m_lastIsPara=TRUE;
1271 }
1272
visitPre(DocImage * img)1273 void RTFDocVisitor::visitPre(DocImage *img)
1274 {
1275 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocImage)}\n");
1276 includePicturePreRTF(img->name(), img->type()==DocImage::Rtf, img->hasCaption(), img->isInlineImage());
1277 }
includePicturePreRTF(const QCString & name,bool isTypeRTF,bool hasCaption,bool inlineImage)1278 void RTFDocVisitor::includePicturePreRTF(const QCString &name, bool isTypeRTF, bool hasCaption, bool inlineImage)
1279 {
1280 if (isTypeRTF)
1281 {
1282 if (!inlineImage)
1283 {
1284 m_t << "\\par\n";
1285 m_t << "{\n";
1286 m_t << rtf_Style_Reset << "\n";
1287 if (hasCaption || m_lastIsPara) m_t << "\\par\n";
1288 m_t << "\\pard \\qc ";
1289 }
1290 m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1291 m_t << name;
1292 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}\n";
1293 if (!inlineImage)
1294 {
1295 m_t << "\\par\n";
1296 if (hasCaption)
1297 {
1298 m_t << "\\pard \\qc \\b";
1299 m_t << "{Image \\field\\flddirty{\\*\\fldinst { SEQ Image \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
1300 }
1301 m_lastIsPara=TRUE;
1302 }
1303 else
1304 {
1305 if (hasCaption) m_t << "{\\comment "; // to prevent caption to be shown
1306 }
1307 }
1308 else // other format -> skip
1309 {
1310 pushHidden(m_hide);
1311 m_hide=TRUE;
1312 }
1313 }
1314
visitPost(DocImage * img)1315 void RTFDocVisitor::visitPost(DocImage *img)
1316 {
1317 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocImage)}\n");
1318 includePicturePostRTF(img->type()==DocImage::Rtf, img->hasCaption(), img->isInlineImage());
1319 }
1320
includePicturePostRTF(bool isTypeRTF,bool hasCaption,bool inlineImage)1321 void RTFDocVisitor::includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool inlineImage)
1322 {
1323 if (isTypeRTF)
1324 {
1325 if (m_hide) return;
1326 if (inlineImage)
1327 {
1328 if (hasCaption) m_t << " }";
1329 }
1330 else
1331 {
1332 if (hasCaption)
1333 {
1334 m_t << "}\n";
1335 m_t << "\\par}\n";
1336 }
1337 else
1338 {
1339 m_t << "}\n";
1340 }
1341 }
1342 }
1343 else
1344 {
1345 m_hide = popHidden();
1346 }
1347 }
1348
visitPre(DocDotFile * df)1349 void RTFDocVisitor::visitPre(DocDotFile *df)
1350 {
1351 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDotFile)}\n");
1352 if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file()));
1353 writeDotFile(df);
1354 }
1355
visitPost(DocDotFile * df)1356 void RTFDocVisitor::visitPost(DocDotFile *df)
1357 {
1358 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDotFile)}\n");
1359 includePicturePostRTF(true, df->hasCaption());
1360 }
visitPre(DocMscFile * df)1361 void RTFDocVisitor::visitPre(DocMscFile *df)
1362 {
1363 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocMscFile)}\n");
1364 if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file()));
1365 writeMscFile(df);
1366 }
1367
visitPost(DocMscFile * df)1368 void RTFDocVisitor::visitPost(DocMscFile *df)
1369 {
1370 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocMscFile)}\n");
1371 includePicturePostRTF(true, df->hasCaption());
1372 }
1373
visitPre(DocDiaFile * df)1374 void RTFDocVisitor::visitPre(DocDiaFile *df)
1375 {
1376 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDiaFile)}\n");
1377 if (!Config_getBool(DOT_CLEANUP)) copyFile(df->file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df->file()));
1378 writeDiaFile(df);
1379 }
1380
visitPost(DocDiaFile * df)1381 void RTFDocVisitor::visitPost(DocDiaFile *df)
1382 {
1383 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDiaFile)}\n");
1384 includePicturePostRTF(true, df->hasCaption());
1385 }
1386
visitPre(DocLink * lnk)1387 void RTFDocVisitor::visitPre(DocLink *lnk)
1388 {
1389 if (m_hide) return;
1390 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocLink)}\n");
1391 startLink(lnk->ref(),lnk->file(),lnk->anchor());
1392 }
1393
visitPost(DocLink * lnk)1394 void RTFDocVisitor::visitPost(DocLink *lnk)
1395 {
1396 if (m_hide) return;
1397 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLink)}\n");
1398 endLink(lnk->ref());
1399 }
1400
visitPre(DocRef * ref)1401 void RTFDocVisitor::visitPre(DocRef *ref)
1402 {
1403 if (m_hide) return;
1404 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRef)}\n");
1405 // when ref->isSubPage()==TRUE we use ref->file() for HTML and
1406 // ref->anchor() for LaTeX/RTF
1407 if (ref->isSubPage())
1408 {
1409 startLink(ref->ref(),QCString(),ref->anchor());
1410 }
1411 else
1412 {
1413 if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
1414 }
1415 if (!ref->hasLinkText()) filter(ref->targetTitle());
1416 }
1417
visitPost(DocRef * ref)1418 void RTFDocVisitor::visitPost(DocRef *ref)
1419 {
1420 if (m_hide) return;
1421 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRef)}\n");
1422 if (!ref->file().isEmpty()) endLink(ref->ref());
1423 //m_t << " ";
1424 }
1425
1426
visitPre(DocSecRefItem *)1427 void RTFDocVisitor::visitPre(DocSecRefItem *)
1428 {
1429 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefItem)}\n");
1430 }
1431
visitPost(DocSecRefItem *)1432 void RTFDocVisitor::visitPost(DocSecRefItem *)
1433 {
1434 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefItem)}\n");
1435 }
1436
visitPre(DocSecRefList *)1437 void RTFDocVisitor::visitPre(DocSecRefList *)
1438 {
1439 if (m_hide) return;
1440 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefList)}\n");
1441 m_t << "{\n";
1442 incIndentLevel();
1443 m_t << rtf_Style_Reset << getStyle("LatexTOC") << "\n";
1444 m_t << "\\par\n";
1445 m_lastIsPara=TRUE;
1446 }
1447
visitPost(DocSecRefList *)1448 void RTFDocVisitor::visitPost(DocSecRefList *)
1449 {
1450 if (m_hide) return;
1451 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefList)}\n");
1452 decIndentLevel();
1453 m_t << "\\par";
1454 m_t << "}\n";
1455 m_lastIsPara=TRUE;
1456 }
1457
visitPre(DocParamSect * s)1458 void RTFDocVisitor::visitPre(DocParamSect *s)
1459 {
1460 if (m_hide) return;
1461 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamSect)}\n");
1462 m_t << "{"; // start param list
1463 if (!m_lastIsPara) m_t << "\\par\n";
1464 //m_t << "{\\b "; // start bold
1465 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
1466 switch(s->type())
1467 {
1468 case DocParamSect::Param:
1469 m_t << theTranslator->trParameters(); break;
1470 case DocParamSect::RetVal:
1471 m_t << theTranslator->trReturnValues(); break;
1472 case DocParamSect::Exception:
1473 m_t << theTranslator->trExceptions(); break;
1474 case DocParamSect::TemplateParam:
1475 m_t << theTranslator->trTemplateParameters(); break;
1476 default:
1477 ASSERT(0);
1478 }
1479 m_t << "\\par";
1480 m_t << "}\n";
1481 bool useTable = s->type()==DocParamSect::Param ||
1482 s->type()==DocParamSect::RetVal ||
1483 s->type()==DocParamSect::Exception ||
1484 s->type()==DocParamSect::TemplateParam;
1485 if (!useTable)
1486 {
1487 incIndentLevel();
1488 }
1489 m_t << rtf_Style_Reset << getStyle("DescContinue");
1490 m_lastIsPara=TRUE;
1491 }
1492
visitPost(DocParamSect * s)1493 void RTFDocVisitor::visitPost(DocParamSect *s)
1494 {
1495 if (m_hide) return;
1496 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamSect)}\n");
1497 //m_t << "\\par\n";
1498 bool useTable = s->type()==DocParamSect::Param ||
1499 s->type()==DocParamSect::RetVal ||
1500 s->type()==DocParamSect::Exception ||
1501 s->type()==DocParamSect::TemplateParam;
1502 if (!useTable)
1503 {
1504 decIndentLevel();
1505 }
1506 m_t << "}\n";
1507 }
1508
visitPre(DocParamList * pl)1509 void RTFDocVisitor::visitPre(DocParamList *pl)
1510 {
1511 static int columnPos[4][5] =
1512 { { 2, 25, 100, 100, 100 }, // no inout, no type
1513 { 3, 14, 35, 100, 100 }, // inout, no type
1514 { 3, 25, 50, 100, 100 }, // no inout, type
1515 { 4, 14, 35, 55, 100 }, // inout, type
1516 };
1517 int config=0;
1518 if (m_hide) return;
1519 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamList)}\n");
1520
1521 DocParamSect::Type parentType = DocParamSect::Unknown;
1522 DocParamSect *sect = 0;
1523 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1524 {
1525 parentType = ((DocParamSect*)pl->parent())->type();
1526 sect=(DocParamSect*)pl->parent();
1527 }
1528 bool useTable = parentType==DocParamSect::Param ||
1529 parentType==DocParamSect::RetVal ||
1530 parentType==DocParamSect::Exception ||
1531 parentType==DocParamSect::TemplateParam;
1532 if (sect && sect->hasInOutSpecifier()) config+=1;
1533 if (sect && sect->hasTypeSpecifier()) config+=2;
1534 if (useTable)
1535 {
1536 int i;
1537 m_t << "\\trowd \\trgaph108\\trleft426\\tblind426"
1538 "\\trbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1539 "\\trbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1540 "\\trbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1541 "\\trbrdrr\\brdrs\\brdrw10\\brdrcf15 "
1542 "\\trbrdrh\\brdrs\\brdrw10\\brdrcf15 "
1543 "\\trbrdrv\\brdrs\\brdrw10\\brdrcf15 "<< "\n";
1544 for (i=0;i<columnPos[config][0];i++)
1545 {
1546 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1547 "\\clbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1548 "\\clbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1549 "\\clbrdrr \\brdrs\\brdrw10\\brdrcf15 "
1550 "\\cltxlrtb "
1551 "\\cellx" << (rtf_pageWidth*columnPos[config][i+1]/100) << "\n";
1552 }
1553 m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1554 }
1555
1556 if (sect && sect->hasInOutSpecifier())
1557 {
1558 if (useTable)
1559 {
1560 m_t << "{";
1561 }
1562
1563 // Put in the direction: in/out/in,out if specified.
1564 if (pl->direction()!=DocParamSect::Unspecified)
1565 {
1566 if (pl->direction()==DocParamSect::In)
1567 {
1568 m_t << "in";
1569 }
1570 else if (pl->direction()==DocParamSect::Out)
1571 {
1572 m_t << "out";
1573 }
1574 else if (pl->direction()==DocParamSect::InOut)
1575 {
1576 m_t << "in,out";
1577 }
1578 }
1579
1580 if (useTable)
1581 {
1582 m_t << "\\cell }";
1583 }
1584 }
1585
1586 if (sect && sect->hasTypeSpecifier())
1587 {
1588 if (useTable)
1589 {
1590 m_t << "{";
1591 }
1592 for (const auto &type : pl->paramTypes())
1593 {
1594 if (type->kind()==DocNode::Kind_Word)
1595 {
1596 visit((DocWord*)type.get());
1597 }
1598 else if (type->kind()==DocNode::Kind_LinkedWord)
1599 {
1600 visit((DocLinkedWord*)type.get());
1601 }
1602 else if (type->kind()==DocNode::Kind_Sep)
1603 {
1604 m_t << " " << ((DocSeparator *)type.get())->chars() << " ";
1605 }
1606 }
1607 if (useTable)
1608 {
1609 m_t << "\\cell }";
1610 }
1611 }
1612
1613
1614 if (useTable)
1615 {
1616 m_t << "{";
1617 }
1618
1619 m_t << "{\\i ";
1620 bool first=TRUE;
1621 for (const auto ¶m : pl->parameters())
1622 {
1623 if (!first) m_t << ","; else first=FALSE;
1624 if (param->kind()==DocNode::Kind_Word)
1625 {
1626 visit((DocWord*)param.get());
1627 }
1628 else if (param->kind()==DocNode::Kind_LinkedWord)
1629 {
1630 visit((DocLinkedWord*)param.get());
1631 }
1632 }
1633 m_t << "} ";
1634
1635 if (useTable)
1636 {
1637 m_t << "\\cell }{";
1638 }
1639 m_lastIsPara=TRUE;
1640 }
1641
visitPost(DocParamList * pl)1642 void RTFDocVisitor::visitPost(DocParamList *pl)
1643 {
1644 if (m_hide) return;
1645 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamList)}\n");
1646
1647 DocParamSect::Type parentType = DocParamSect::Unknown;
1648 //DocParamSect *sect = 0;
1649 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1650 {
1651 parentType = ((DocParamSect*)pl->parent())->type();
1652 //sect=(DocParamSect*)pl->parent();
1653 }
1654 bool useTable = parentType==DocParamSect::Param ||
1655 parentType==DocParamSect::RetVal ||
1656 parentType==DocParamSect::Exception ||
1657 parentType==DocParamSect::TemplateParam;
1658 if (useTable)
1659 {
1660 m_t << "\\cell }\n";
1661 //m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1662 m_t << "{\\row }\n";
1663 }
1664 else
1665 {
1666 m_t << "\\par\n";
1667 }
1668
1669 m_lastIsPara=TRUE;
1670 }
1671
visitPre(DocXRefItem * x)1672 void RTFDocVisitor::visitPre(DocXRefItem *x)
1673 {
1674 if (m_hide) return;
1675 if (x->title().isEmpty()) return;
1676 bool anonymousEnum = x->file()=="@";
1677 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocXRefItem)}\n");
1678 if (!m_lastIsPara)
1679 {
1680 m_t << "\\par\n";
1681 m_lastIsPara=TRUE;
1682 }
1683 m_t << "{"; // start param list
1684 //m_t << "{\\b "; // start bold
1685 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
1686 if (Config_getBool(RTF_HYPERLINKS) && !anonymousEnum)
1687 {
1688 QCString refName;
1689 if (!x->file().isEmpty())
1690 {
1691 refName+=stripPath(x->file());
1692 }
1693 if (!x->file().isEmpty() && !x->anchor().isEmpty())
1694 {
1695 refName+="_";
1696 }
1697 if (!x->anchor().isEmpty())
1698 {
1699 refName+=x->anchor();
1700 }
1701
1702 m_t << "{\\field "
1703 "{\\*\\fldinst "
1704 "{ HYPERLINK \\\\l \"" << rtfFormatBmkStr(refName) << "\" "
1705 "}{}"
1706 "}"
1707 "{\\fldrslt "
1708 "{\\cs37\\ul\\cf2 ";
1709 filter(x->title());
1710 m_t << "}"
1711 "}"
1712 "}";
1713 }
1714 else
1715 {
1716 filter(x->title());
1717 }
1718 m_t << ":";
1719 m_t << "\\par";
1720 m_t << "}"; // end bold
1721 incIndentLevel();
1722 m_t << rtf_Style_Reset << getStyle("DescContinue");
1723 m_lastIsPara=FALSE;
1724 }
1725
visitPost(DocXRefItem * x)1726 void RTFDocVisitor::visitPost(DocXRefItem *x)
1727 {
1728 if (m_hide) return;
1729 if (x->title().isEmpty()) return;
1730 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocXRefItem)}\n");
1731 m_t << "\\par\n";
1732 decIndentLevel();
1733 m_t << "}\n"; // end xref item
1734 m_lastIsPara=TRUE;
1735 }
1736
visitPre(DocInternalRef * ref)1737 void RTFDocVisitor::visitPre(DocInternalRef *ref)
1738 {
1739 if (m_hide) return;
1740 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternalRef)}\n");
1741 startLink("",ref->file(),ref->anchor());
1742 }
1743
visitPost(DocInternalRef *)1744 void RTFDocVisitor::visitPost(DocInternalRef *)
1745 {
1746 if (m_hide) return;
1747 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternalRef)}\n");
1748 endLink("");
1749 m_t << " ";
1750 }
1751
visitPre(DocText *)1752 void RTFDocVisitor::visitPre(DocText *)
1753 {
1754 if (m_hide) return;
1755 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocText)}\n");
1756 }
1757
visitPost(DocText *)1758 void RTFDocVisitor::visitPost(DocText *)
1759 {
1760 if (m_hide) return;
1761 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocText)}\n");
1762 }
1763
visitPre(DocHtmlBlockQuote *)1764 void RTFDocVisitor::visitPre(DocHtmlBlockQuote *)
1765 {
1766 if (m_hide) return;
1767 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlBlockQuote)}\n");
1768 if (!m_lastIsPara) m_t << "\\par\n";
1769 m_t << "{"; // start desc
1770 incIndentLevel();
1771 m_t << rtf_Style_Reset << getStyle("DescContinue");
1772 }
1773
visitPost(DocHtmlBlockQuote *)1774 void RTFDocVisitor::visitPost(DocHtmlBlockQuote *)
1775 {
1776 if (m_hide) return;
1777 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlBlockQuote)}\n");
1778 if (!m_lastIsPara) m_t << "\\par\n";
1779 decIndentLevel();
1780 m_t << "}"; // end desc
1781 m_lastIsPara=TRUE;
1782 }
1783
visitPre(DocVhdlFlow *)1784 void RTFDocVisitor::visitPre(DocVhdlFlow *)
1785 {
1786 if (m_hide) return;
1787 }
1788
visitPost(DocVhdlFlow *)1789 void RTFDocVisitor::visitPost(DocVhdlFlow *)
1790 {
1791 if (m_hide) return;
1792 }
1793
visitPre(DocParBlock *)1794 void RTFDocVisitor::visitPre(DocParBlock *)
1795 {
1796 if (m_hide) return;
1797 }
1798
visitPost(DocParBlock *)1799 void RTFDocVisitor::visitPost(DocParBlock *)
1800 {
1801 if (m_hide) return;
1802 }
1803
1804
1805 //static char* getMultiByte(int c)
1806 //{
1807 // static char s[10];
1808 // sprintf(s,"\\'%X",c);
1809 // return s;
1810 //}
1811
filter(const QCString & str,bool verbatim)1812 void RTFDocVisitor::filter(const QCString &str,bool verbatim)
1813 {
1814 if (!str.isEmpty())
1815 {
1816 const unsigned char *p=(const unsigned char *)str.data();
1817 unsigned char c;
1818 //unsigned char pc='\0';
1819 while (*p)
1820 {
1821 //static bool MultiByte = FALSE;
1822 c=*p++;
1823
1824 //if ( MultiByte )
1825 //{
1826 // m_t << getMultiByte( c );
1827 // MultiByte = FALSE;
1828 // continue;
1829 //}
1830 //if ( c >= 0x80 )
1831 //{
1832 // MultiByte = TRUE;
1833 // m_t << getMultiByte( c );
1834 // continue;
1835 //}
1836
1837 switch (c)
1838 {
1839 case '{': m_t << "\\{"; break;
1840 case '}': m_t << "\\}"; break;
1841 case '\\': m_t << "\\\\"; break;
1842 case '\n': if (verbatim)
1843 {
1844 m_t << "\\par\n";
1845 }
1846 else
1847 {
1848 m_t << '\n';
1849 }
1850 break;
1851 default: m_t << (char)c;
1852 }
1853 //pc = c;
1854 }
1855 }
1856 }
1857
startLink(const QCString & ref,const QCString & file,const QCString & anchor)1858 void RTFDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
1859 {
1860 if (ref.isEmpty() && Config_getBool(RTF_HYPERLINKS))
1861 {
1862 QCString refName;
1863 if (!file.isEmpty())
1864 {
1865 refName+=stripPath(file);
1866 }
1867 if (!file.isEmpty() && !anchor.isEmpty())
1868 {
1869 refName+='_';
1870 }
1871 if (!anchor.isEmpty())
1872 {
1873 refName+=anchor;
1874 }
1875
1876 m_t << "{\\field {\\*\\fldinst { HYPERLINK \\\\l \"";
1877 m_t << rtfFormatBmkStr(refName);
1878 m_t << "\" }{}";
1879 m_t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
1880 }
1881 else
1882 {
1883 m_t << "{\\b ";
1884 }
1885 m_lastIsPara=FALSE;
1886 }
1887
endLink(const QCString & ref)1888 void RTFDocVisitor::endLink(const QCString &ref)
1889 {
1890 if (ref.isEmpty() && Config_getBool(RTF_HYPERLINKS))
1891 {
1892 m_t << "}}}";
1893 }
1894 else
1895 {
1896 m_t << "}";
1897 }
1898 m_lastIsPara=FALSE;
1899 }
1900
writeDotFile(DocDotFile * df)1901 void RTFDocVisitor::writeDotFile(DocDotFile *df)
1902 {
1903 writeDotFile(df->file(), df->hasCaption(), df->srcFile(), df->srcLine());
1904 }
writeDotFile(const QCString & filename,bool hasCaption,const QCString & srcFile,int srcLine)1905 void RTFDocVisitor::writeDotFile(const QCString &filename, bool hasCaption,
1906 const QCString &srcFile, int srcLine)
1907 {
1908 QCString baseName=filename;
1909 int i;
1910 if ((i=baseName.findRev('/'))!=-1)
1911 {
1912 baseName=baseName.right(baseName.length()-i-1);
1913 }
1914 QCString outDir = Config_getString(RTF_OUTPUT);
1915 writeDotGraphFromFile(filename,outDir,baseName,GOF_BITMAP,srcFile,srcLine);
1916 QCString imgExt = getDotImageExtension();
1917 includePicturePreRTF(baseName + "." + imgExt, true, hasCaption);
1918 }
1919
writeMscFile(DocMscFile * df)1920 void RTFDocVisitor::writeMscFile(DocMscFile *df)
1921 {
1922 writeMscFile(df->file(), df->hasCaption(), df->srcFile(), df->srcLine());
1923 }
writeMscFile(const QCString & fileName,bool hasCaption,const QCString & srcFile,int srcLine)1924 void RTFDocVisitor::writeMscFile(const QCString &fileName, bool hasCaption,
1925 const QCString &srcFile, int srcLine)
1926 {
1927 QCString baseName=fileName;
1928 int i;
1929 if ((i=baseName.findRev('/'))!=-1)
1930 {
1931 baseName=baseName.right(baseName.length()-i-1);
1932 }
1933 QCString outDir = Config_getString(RTF_OUTPUT);
1934 writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP,srcFile,srcLine);
1935 includePicturePreRTF(baseName + ".png", true, hasCaption);
1936 }
1937
writeDiaFile(DocDiaFile * df)1938 void RTFDocVisitor::writeDiaFile(DocDiaFile *df)
1939 {
1940 QCString baseName=df->file();
1941 int i;
1942 if ((i=baseName.findRev('/'))!=-1)
1943 {
1944 baseName=baseName.right(baseName.length()-i-1);
1945 }
1946 QCString outDir = Config_getString(RTF_OUTPUT);
1947 writeDiaGraphFromFile(df->file(),outDir,baseName,DIA_BITMAP,df->srcFile(),df->srcLine());
1948 includePicturePreRTF(baseName + ".png", true, df->hasCaption());
1949 }
1950
writePlantUMLFile(const QCString & fileName,bool hasCaption)1951 void RTFDocVisitor::writePlantUMLFile(const QCString &fileName, bool hasCaption)
1952 {
1953 QCString baseName=fileName;
1954 int i;
1955 if ((i=baseName.findRev('/'))!=-1)
1956 {
1957 baseName=baseName.right(baseName.length()-i-1);
1958 }
1959 QCString outDir = Config_getString(RTF_OUTPUT);
1960 PlantumlManager::instance().generatePlantUMLOutput(fileName,outDir,PlantumlManager::PUML_BITMAP);
1961 includePicturePreRTF(baseName + ".png", true, hasCaption);
1962 }
1963