Doxygen
Loading...
Searching...
No Matches
rtfdocvisitor.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2022 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16// own header
17#include "rtfdocvisitor.h"
18
19// standard includes
20#include <algorithm>
21
22// other includes
23#include "cite.h"
24#include "codefragment.h"
25#include "config.h"
26#include "dia.h"
27#include "docparser.h"
28#include "dot.h"
29#include "doxygen.h"
30#include "emoji.h"
31#include "filedef.h"
32#include "fileinfo.h"
33#include "htmlentity.h"
34#include "language.h"
35#include "mermaid.h"
36#include "message.h"
37#include "msc.h"
38#include "outputgen.h"
39#include "parserintf.h"
40#include "plantuml.h"
41#include "portable.h"
42#include "rtfgen.h"
43#include "rtfstyle.h"
44#include "util.h"
45
46//#define DBG_RTF(x) m_t << x
47#define DBG_RTF(x) do {} while(0)
48
49static DString align(const DocHtmlCell &cell)
50{
51 for (const auto &attr : cell.attribs())
52 {
53 if (attr.name.lower()=="align")
54 {
55 if (attr.value.lower()=="center") return "\\qc ";
56 else if (attr.value.lower()=="right") return "\\qr ";
57 else return "";
58 }
59 }
60 return "";
61}
62
64 const DString &langExt, int hierarchyLevel)
65 : m_t(t), m_ci(ci), m_langExt(langExt), m_hierarchyLevel(hierarchyLevel)
66{
67}
68
70{
71 DString n = name + DString().setNum(indentLevel());
72 StyleData &sd = rtf_Style[n.str()];
73 return sd.reference();
74}
75
77{
78 for (int i=0 ; rtf_Table_Default[i].definition ; i++ )
79 {
80 if ((id == rtf_Table_Default[i].id) && (m_indentLevel == rtf_Table_Default[i].lvl))
81 {
82 return rtf_Table_Default[i].place;
83 }
84 }
85 ASSERT(0);
86 return "";
87}
88
90{
91 return std::min(m_indentLevel,maxIndentLevels-1);
92}
93
95{
98 {
99 err("Maximum indent level ({}) exceeded while generating RTF output!\n",maxIndentLevels-1);
100 }
101}
102
107
108 //------------------------------------
109 // visitor functions for leaf nodes
110 //--------------------------------------
111
113{
114 if (m_hide) return;
115 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWord)}\n");
116 filter(w.word());
117 m_lastIsPara=false;
118}
119
121{
122 if (m_hide) return;
123 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLinkedWord)}\n");
124 startLink(w.ref(),w.file(),w.anchor());
125 filter(w.word());
126 endLink(w.ref());
127 m_lastIsPara=false;
128}
129
131{
132 if (m_hide) return;
133 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWhiteSpace)}\n");
134 if (m_insidePre)
135 {
136 m_t << w.chars();
137 }
138 else
139 {
140 m_t << " ";
141 }
142 m_lastIsPara=false;
143}
144
146{
147 if (m_hide) return;
148 DBG_RTF("{\\comment RTFDocVisitor::visit(DocSymbol)}\n");
149 const char *res = HtmlEntityMapper::instance().rtf(s.symbol());
150 if (res)
151 {
152 m_t << res;
153 }
154 else
155 {
156 err("RTF: non supported HTML-entity found: {}\n",HtmlEntityMapper::instance().html(s.symbol(),true));
157 }
158 m_lastIsPara=false;
159}
160
162{
163 if (m_hide) return;
164 DBG_RTF("{\\comment RTFDocVisitor::visit(DocEmoji)}\n");
165 const char *res = EmojiEntityMapper::instance().unicode(s.index());
166 if (res)
167 {
168 const char *p = res;
169 int val = 0;
170 int val1 = 0;
171 while (*p)
172 {
173 switch(*p)
174 {
175 case '&': case '#': case 'x':
176 break;
177 case ';':
178 val1 = val;
179 val = 0xd800 + ( ( val1 - 0x10000 ) & 0xffc00 ) / 0x400 - 0x10000;
180 m_t << "\\u" << val << "?";
181 val = 0xdC00 + ( ( val1 - 0x10000 ) & 0x3ff ) - 0x10000 ;
182 m_t << "\\u" << val << "?";
183 val = 0;
184 break;
185 case '0': case '1': case '2': case '3': case '4':
186 case '5': case '6': case '7': case '8': case '9':
187 val = val * 16 + *p - '0';
188 break;
189 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
190 val = val * 16 + *p - 'a' + 10;
191 break;
192 }
193 p++;
194 }
195 }
196 else
197 {
198 m_t << s.name();
199 }
200 m_lastIsPara=false;
201}
202
204{
205 if (m_hide) return;
206 DBG_RTF("{\\comment RTFDocVisitor::visit(DocURL)}\n");
207 if (Config_getBool(RTF_HYPERLINKS))
208 {
209 m_t << "{\\field "
210 "{\\*\\fldinst "
211 "{ HYPERLINK \"";
212 if (u.isEmail()) m_t << "mailto:";
213 m_t << u.url();
214 m_t << "\" }"
215 "{}";
216 m_t << "}"
217 "{\\fldrslt "
218 "{\\cs37\\ul\\cf2 ";
219 filter(u.url());
220 m_t << "}"
221 "}"
222 "}\n";
223 }
224 else
225 {
226 m_t << "{\\f2 ";
227 filter(u.url());
228 m_t << "}";
229 }
230 m_lastIsPara=false;
231}
232
234{
235 if (m_hide) return;
236 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLineBreak)}\n");
237 m_t << "\\par\n";
238 m_lastIsPara=true;
239}
240
242{
243 if (m_hide) return;
244 DBG_RTF("{\\comment RTFDocVisitor::visit(DocHorRuler)}\n");
245 m_t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}\n";
246 m_lastIsPara=true;
247}
248
250{
251 if (m_hide) return;
252 m_lastIsPara=false;
253 DBG_RTF("{\\comment RTFDocVisitor::visit(DocStyleChange)}\n");
254 switch (s.style())
255 {
257 if (s.enable()) m_t << "{\\b "; else m_t << "} ";
258 break;
262 if (s.enable()) m_t << "{\\strike "; else m_t << "} ";
263 break;
266 if (s.enable()) m_t << "{\\ul "; else m_t << "} ";
267 break;
269 if (s.enable()) m_t << "{\\i "; else m_t << "} ";
270 break;
274 if (s.enable()) m_t << "{\\f2 "; else m_t << "} ";
275 break;
277 if (s.enable()) m_t << "{\\sub "; else m_t << "} ";
278 break;
280 if (s.enable()) m_t << "{\\super "; else m_t << "} ";
281 break;
283 if (s.enable()) m_t << "{\\qc "; else m_t << "} ";
284 break;
286 if (s.enable()) m_t << "{\\sub "; else m_t << "} ";
287 break;
289 if (s.enable()) m_t << "{\\i "; else m_t << "} ";
290 break;
292 if (s.enable())
293 {
294 m_t << "{\n";
295 m_t << "\\par\n";
296 m_t << rtf_Style_Reset << getStyle("CodeExample");
297 m_insidePre=true;
298 }
299 else
300 {
301 m_insidePre=false;
302 m_t << "\\par";
303 m_t << "}\n";
304 }
305 m_lastIsPara=true;
306 break;
307 case DocStyleChange::Div: /* HTML only */ break;
308 case DocStyleChange::Span: /* HTML only */ break;
309 }
310}
311
313{
314 if (m_hide) return;
315 DBG_RTF("{\\comment RTFDocVisitor::visit(DocVerbatim)}\n");
316 DString lang = m_langExt;
317 if (!s.language().empty()) // explicit language setting
318 {
319 lang = s.language();
320 }
321 SrcLangExt langExt = getLanguageFromCodeLang(lang);
322 switch(s.type())
323 {
325 m_t << "{\n";
326 m_t << "\\par\n";
327 m_t << rtf_Style_Reset << getStyle("CodeExample");
328 getCodeParser(lang).parseCode(m_ci,s.context(),s.text(),langExt,
329 Config_getBool(STRIP_CODE_COMMENTS),
330 CodeParserOptions().setExample(s.isExample(),s.exampleFile()));
331 //m_t << "\\par\n";
332 m_t << "}\n";
333 break;
335 filter(s.text(),true);
336 break;
338 m_t << "{\n";
339 m_t << "{\\f2 ";
340 filter(s.text(),true);
341 m_t << "}";
342 m_t << "}\n";
343 break;
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;
353 m_t << s.text();
354 break;
360 /* nothing */
361 break;
362 case DocVerbatim::Dot:
363 {
364 bool exists = false;
365 auto fileName = writeInlineGraph(Config_getString(RTF_OUTPUT)+"/inline_dotgraph_", // baseName
366 ".dot", // extension
367 s.text(), // contents
368 exists);
369 if (!fileName.empty())
370 {
371 writeDotFile(fileName, s.hasCaption(), s.srcFile(), s.srcLine(), !exists);
372 visitChildren(s);
374 }
375 }
376 break;
377 case DocVerbatim::Msc:
378 {
379 bool exists = false;
380 auto fileName = writeInlineGraph(Config_getString(RTF_OUTPUT)+"/inline_mscgraph_", // baseName
381 ".msc", // extension
382 "msc {"+s.text()+"}", // contents
383 exists);
384 if (!fileName.empty())
385 {
386 writeMscFile(fileName, s.hasCaption(), s.srcFile(), s.srcLine(), !exists);
387 visitChildren(s);
389 }
390 }
391 break;
393 {
394 DString rtfOutput = Config_getString(RTF_OUTPUT);
395 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
397 s.engine(),s.srcFile(),s.srcLine(),true);
398
399 for (const auto &baseName: baseNameVector)
400 {
401 writePlantUMLFile(baseName, s.hasCaption());
402 visitChildren(s);
404 }
405 }
406 break;
408 if (Config_getBool(MERMAID_RENDER_MODE)!=MERMAID_RENDER_MODE_t::CLIENT_SIDE)
409 {
410 auto rtfOutput = Config_getString(RTF_OUTPUT);
411 auto outputFormat = MermaidManager::OutputFormat::RTF;
412 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
414 rtfOutput,s.exampleFile(),s.text(),imageFormat,
415 s.srcFile(),s.srcLine());
416 writeMermaidFile(baseName, s.hasCaption());
417 visitChildren(s);
419 }
420 break;
421 }
422 m_lastIsPara=false;
423}
424
426{
427 if (m_hide) return;
428 DBG_RTF("{\\comment RTFDocVisitor::visit(DocAnchor)}\n");
429 DString anchor;
430 if (!anc.file().empty())
431 {
432 anchor+=stripPath(anc.file());
433 }
434 if (!anc.file().empty() && !anc.anchor().empty())
435 {
436 anchor+="_";
437 }
438 if (!anc.anchor().empty())
439 {
440 anchor+=anc.anchor();
441 }
442 m_t << "{\\bkmkstart " << rtfFormatBmkStr(anchor) << "}\n";
443 m_t << "{\\bkmkend " << rtfFormatBmkStr(anchor) << "}\n";
444 m_lastIsPara=false;
445}
446
448{
449 if (m_hide) return;
451 DBG_RTF("{\\comment RTFDocVisitor::visit(DocInclude)}\n");
452 switch(inc.type())
453 {
455 {
456 m_t << "{\n";
457 m_t << "\\par\n";
458 m_t << rtf_Style_Reset << getStyle("CodeExample");
459 FileInfo cfi( inc.file().str() );
460 auto fd = createFileDef( cfi.dirPath(), cfi.fileName() );
462 inc.text(),
463 langExt,
464 inc.stripCodeComments(),
466 .setExample(inc.isExample(),inc.exampleFile())
467 .setFileDef(fd.get())
468 .setInlineFragment(true)
469 );
470 m_t << "\\par";
471 m_t << "}\n";
472 }
473 break;
475 m_t << "{\n";
476 m_t << "\\par\n";
477 m_t << rtf_Style_Reset << getStyle("CodeExample");
479 inc.text(),langExt,
480 inc.stripCodeComments(),
482 .setExample(inc.isExample(),inc.exampleFile())
483 .setInlineFragment(true)
484 .setShowLineNumbers(false)
485 );
486 m_t << "\\par";
487 m_t << "}\n";
488 break;
496 break;
498 m_t << inc.text();
499 break;
501 m_t << "{\n";
502 m_t << "\\par\n";
503 m_t << rtf_Style_Reset << getStyle("CodeExample");
504 filter(inc.text());
505 m_t << "\\par";
506 m_t << "}\n";
507 break;
510 m_t << "{\n";
511 if (!m_lastIsPara) m_t << "\\par\n";
512 m_t << rtf_Style_Reset << getStyle("CodeExample");
514 inc.file(),
515 inc.blockId(),
516 inc.context(),
518 inc.trimLeft(),
520 );
521 m_t << "}";
522 break;
523 }
524 m_lastIsPara=true;
525}
526
528{
529 //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n",
530 // op.type(),op.isFirst(),op.isLast(),qPrint(op.text()));
531 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIncOperator)}\n");
533 if (locLangExt.empty()) locLangExt = m_langExt;
534 SrcLangExt langExt = getLanguageFromFileName(locLangExt);
535 if (op.isFirst())
536 {
537 if (!m_hide)
538 {
539 m_t << "{\n";
540 m_t << "\\par\n";
541 m_t << rtf_Style_Reset << getStyle("CodeExample");
542 }
544 m_hide = true;
545 }
546 if (op.type()!=DocIncOperator::Skip)
547 {
548 m_hide = popHidden();
549 if (!m_hide)
550 {
551 std::unique_ptr<FileDef> fd = nullptr;
552 if (!op.includeFileName().empty())
553 {
554 FileInfo cfi( op.includeFileName().str() );
555 fd = createFileDef( cfi.dirPath(), cfi.fileName() );
556 }
557
558 getCodeParser(locLangExt).parseCode(m_ci,op.context(),op.text(),langExt,
561 .setExample(op.isExample(),op.exampleFile())
562 .setFileDef(fd.get())
563 .setStartLine(op.line())
565 );
566 }
568 m_hide=true;
569 }
570 if (op.isLast())
571 {
572 m_hide = popHidden();
573 if (!m_hide)
574 {
575 m_t << "\\par";
576 m_t << "}\n";
577 }
578 m_lastIsPara=true;
579 }
580 else
581 {
582 if (!m_hide) m_t << "\n";
583 m_lastIsPara=false;
584 }
585}
586
588{
589 if (m_hide) return;
590 DBG_RTF("{\\comment RTFDocVisitor::visit(DocFormula)}\n");
591 bool bDisplay = !f.isInline();
592 if (bDisplay)
593 {
594 m_t << "\\par";
595 m_t << "{";
596 m_t << "\\pard\\plain";
597 m_t << "\\pard";
598 m_t << "\\qc";
599 }
600 m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"" << f.relPath() << f.name() << ".png\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}";
601 if (bDisplay)
602 {
603 m_t << "\\par}";
604 }
605 m_lastIsPara=false;
606}
607
609{
610 if (m_hide) return;
611 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIndexEntry)}\n");
612 m_t << "{\\xe \\v " << i.entry() << "}\n";
613 m_lastIsPara=false;
614}
615
619
621{
622 if (m_hide) return;
623 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocCite &)}\n");
624 auto opt = cite.option();
625 if (!cite.file().empty())
626 {
627 if (!opt.noCite()) startLink(cite.ref(),cite.file(),cite.anchor());
628
629 filter(cite.getText(),false, true);
630
631 if (!opt.noCite()) endLink(cite.ref());
632 }
633 else
634 {
635 m_t << "{\\b";
636 if (!opt.noPar()) filter("[");
637 filter(cite.target());
638 if (!opt.noPar()) filter("]");
639 m_t << "}";
640 }
641}
642
643
644//--------------------------------------
645// visitor functions for compound nodes
646//--------------------------------------
647
649{
650 if (m_hide) return;
651 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocAutoList &)}\n");
652 m_t << "{\n";
653 int level = indentLevel();
654 m_listItemInfo[level].isEnum = l.isEnumList();
656 m_listItemInfo[level].type = '1';
657 m_listItemInfo[level].number = 1;
658 m_lastIsPara=false;
659 visitChildren(l);
660 if (!m_lastIsPara) m_t << "\\par";
661 m_t << "}\n";
662 m_lastIsPara=true;
663 if (!l.isCheckedList() && indentLevel()==0) m_t << "\\par\n";
664}
665
667{
668 static int prevLevel = -1;
669 if (m_hide) return;
670 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocAutoListItem &)}\n");
671 int level = indentLevel();
672 if ((level != prevLevel-1) &&
673 (!(level==prevLevel && level != 0 && m_listItemInfo[level].isCheck)) &&
674 (!m_lastIsPara))
675 m_t << "\\par\n";
676 prevLevel= level;
678 if (m_listItemInfo[level].isEnum)
679 {
680 m_t << getStyle("ListEnum") << "\n";
681 m_t << m_listItemInfo[level].number << ".\\tab ";
682 m_listItemInfo[level].number++;
683 }
684 else
685 {
686 switch (li.itemNumber())
687 {
688 case DocAutoList::Unchecked: // unchecked
689 m_t << getListTable(2) << "\n";
690 break;
691 case DocAutoList::Checked_x: // checked with x
692 case DocAutoList::Checked_X: // checked with X
693 m_t << getListTable(3) << "\n";
694 break;
695 default:
696 m_t << getListTable(1) << "\n";
697 break;
698 }
699 }
701 m_lastIsPara=false;
702 visitChildren(li);
704}
705
707{
708 if (m_hide) return;
709 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocPara &)}\n");
710 visitChildren(p);
711 if (!m_lastIsPara &&
712 !p.isLast() && // omit <p> for last paragraph
713 !(p.parent() && // and for parameters & sections
714 std::get_if<DocParamSect>(p.parent())
715 )
716 )
717 {
718 m_t << "\\par\n";
719 m_lastIsPara=true;
720 }
721}
722
724{
725 if (m_hide) return;
726 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocRoot &)}\n");
727 if (r.indent()) incIndentLevel();
728 m_t << "{" << rtf_Style["BodyText"].reference() << "\n";
729 visitChildren(r);
730 if (!m_lastIsPara && !r.singleLine()) m_t << "\\par\n";
731 m_t << "}";
732 m_lastIsPara=true;
733 if (r.indent()) decIndentLevel();
734}
735
737{
738 if (m_hide) return;
739 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocSimpleSect &)}\n");
740 if (!m_lastIsPara) m_t << "\\par\n";
741 m_t << "{"; // start desc
742 //m_t << "{\\b "; // start bold
743 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
744 switch(s.type())
745 {
747 m_t << theTranslator->trSeeAlso(); break;
749 m_t << theTranslator->trReturns(); break;
751 m_t << theTranslator->trAuthor(true,true); break;
753 m_t << theTranslator->trAuthor(true,false); break;
755 m_t << theTranslator->trVersion(); break;
757 m_t << theTranslator->trSince(); break;
759 m_t << theTranslator->trDate(); break;
761 m_t << theTranslator->trNote(); break;
763 m_t << theTranslator->trWarning(); break;
765 m_t << theTranslator->trPrecondition(); break;
767 m_t << theTranslator->trPostcondition(); break;
769 m_t << theTranslator->trCopyright(); break;
771 m_t << theTranslator->trInvariant(); break;
773 m_t << theTranslator->trRemarks(); break;
775 m_t << theTranslator->trAttention(); break;
777 m_t << theTranslator->trImportant(); break;
778 case DocSimpleSect::User: break;
779 case DocSimpleSect::Rcs: break;
780 case DocSimpleSect::Unknown: break;
781 }
782
785 {
786 m_t << "\\par";
787 m_t << "}"; // end bold
788 m_t << rtf_Style_Reset << getStyle("DescContinue");
789 m_t << "{\\s17 \\sa60 \\sb30\n";
790 }
791 else
792 {
793 if (s.title())
794 {
795 std::visit(*this,*s.title());
796 }
797 m_t << "\\par\n";
798 m_t << "}"; // end bold
799 m_t << rtf_Style_Reset << getStyle("DescContinue");
800 }
801 m_lastIsPara=false;
802 visitChildren(s);
803 if (!m_lastIsPara) m_t << "\\par\n";
806 {
807 m_t << "}"; // end DescContinue
808 }
809 m_t << "}"; // end desc
810 m_lastIsPara=true;
811}
812
814{
815 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocTitle &)}\n");
816 if (m_hide) return;
817 visitChildren(t);
818}
819
821{
822 if (m_hide) return;
823 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocSimpleSect &)}\n");
824 m_t << "{\n";
827 m_lastIsPara=false;
828 visitChildren(l);
829 if (!m_lastIsPara) m_t << "\\par\n";
830 m_t << "}\n";
831 m_lastIsPara=true;
832}
833
835{
836 if (m_hide) return;
837 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocSimpleListItem &)}\n");
838 m_t << "\\par" << rtf_Style_Reset << getStyle("ListBullet") << "\n";
839 m_lastIsPara=false;
841 if (li.paragraph())
842 {
843 std::visit(*this,*li.paragraph());
844 }
846 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleListItem)}\n");
847}
848
850{
851 if (m_hide) return;
852 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocSection &)}\n");
853 if (!m_lastIsPara) m_t << "\\par\n";
854 m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(s.file())+"_"+s.anchor()) << "}\n";
855 m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(s.file())+"_"+s.anchor()) << "}\n";
856 m_t << "{{" // start section
858 DString heading;
859 int level = std::min(s.level()+2+m_hierarchyLevel,4);
860 if (level <= 0)
861 level = 1;
862 heading.sprintf("Heading%d",level);
863 // set style
864 m_t << rtf_Style[heading.str()].reference() << "\n";
865 // make table of contents entry
866 if (s.title())
867 {
868 std::visit(*this,*s.title());
869 }
870 m_t << "\n\\par" << "}\n";
871 m_t << "{\\tc\\tcl" << level << " \\v ";
872 if (s.title())
873 {
874 std::visit(*this,*s.title());
875 }
876 m_t << "}\n";
877 m_lastIsPara=true;
878 visitChildren(s);
879 m_t << "\\par}\n"; // end section
880 m_lastIsPara=true;
881}
882
884{
885 if (m_hide) return;
886 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlList &)}\n");
887 m_t << "{\n";
888 int level = indentLevel();
890 m_listItemInfo[level].isCheck = false;
891 m_listItemInfo[level].number = 1;
892 m_listItemInfo[level].type = '1';
893 for (const auto &opt : l.attribs())
894 {
895 if (opt.name=="type")
896 {
897 m_listItemInfo[level].type = opt.value[0];
898 }
899 if (opt.name=="start")
900 {
901 bool ok = false;
902 int val = opt.value.toInt(&ok);
903 if (ok) m_listItemInfo[level].number = val;
904 }
905 }
906 m_lastIsPara=false;
907 visitChildren(l);
908 m_t << "\\par" << "}\n";
909 m_lastIsPara=true;
910}
911
913{
914 if (m_hide) return;
915 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlListItem &)}\n");
916 m_t << "\\par\n";
918 int level = indentLevel();
919 if (m_listItemInfo[level].isEnum)
920 {
921 for (const auto &opt : l.attribs())
922 {
923 if (opt.name=="value")
924 {
925 bool ok = false;
926 int val = opt.value.toInt(&ok);
927 if (ok) m_listItemInfo[level].number = val;
928 }
929 }
930 m_t << getStyle("ListEnum") << "\n";
931 switch (m_listItemInfo[level].type)
932 {
933 case '1':
934 m_t << m_listItemInfo[level].number;
935 break;
936 case 'a':
937 m_t << DString::integerToAlpha(m_listItemInfo[level].number,false);
938 break;
939 case 'A':
941 break;
942 case 'i':
943 m_t << DString::integerToRoman(m_listItemInfo[level].number,false);
944 break;
945 case 'I':
947 break;
948 default:
949 m_t << m_listItemInfo[level].number;
950 break;
951 }
952 m_t << ".\\tab ";
953 m_listItemInfo[level].number++;
954 }
955 else
956 {
957 m_t << getStyle("ListBullet") << "\n";
958 }
960 m_lastIsPara=false;
961 visitChildren(l);
963 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlListItem)}\n");
964}
965
967{
968 if (m_hide) return;
969 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlDescList &)}\n");
970 //m_t << "{\n";
971 //m_t << rtf_Style_Reset << getStyle("ListContinue");
972 //m_lastIsPara=false;
973 visitChildren(dl);
974 //m_t << "}\n";
975 //m_t << "\\par\n";
976 //m_lastIsPara=true;
977}
978
980{
981 if (m_hide) return;
982 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlDescTitle &)}\n");
983 //m_t << "\\par\n";
984 //m_t << "{\\b ";
985 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
986 m_lastIsPara=false;
987 visitChildren(dt);
988 m_t << "\\par\n";
989 m_t << "}\n";
990 m_lastIsPara=true;
991}
992
994{
995 if (m_hide) return;
996 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlDescData &)}\n");
998 m_t << "{" << rtf_Style_Reset << getStyle("DescContinue");
999 visitChildren(dd);
1000 m_t << "\\par";
1001 m_t << "}\n";
1003 m_lastIsPara=true;
1004}
1005
1007{
1008 if (m_hide) return;
1009 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlTable &)}\n");
1010 if (!m_lastIsPara) m_t << "\\par\n";
1011 m_lastIsPara=true;
1012 if (t.caption())
1013 {
1014 const DocHtmlCaption &c = std::get<DocHtmlCaption>(*t.caption());
1015 m_t << "\\pard \\qc \\b";
1016 if (!c.file().empty())
1017 {
1018 m_t << "{\\bkmkstart " << rtfFormatBmkStr(stripPath(c.file())+"_"+c.anchor()) << "}\n";
1019 m_t << "{\\bkmkend " << rtfFormatBmkStr(stripPath(c.file())+"_"+c.anchor()) << "}\n";
1020 }
1021 m_t << "{Table \\field\\flddirty{\\*\\fldinst { SEQ Table \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
1022 std::visit(*this,*t.caption());
1023 }
1024 visitChildren(t);
1025 m_t << "\\pard\\plain\n";
1026 m_t << "\\par\n";
1027 m_lastIsPara=true;
1028}
1029
1031{
1032 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlCaption &)}\n");
1033 visitChildren(c);
1034 m_t << "}\n\\par\n";
1035}
1036
1038{
1039 if (m_hide) return;
1040 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlRow &)}\n");
1041 size_t columnWidth=r.numCells()>0 ? rtf_pageWidth/r.numCells() : 10;
1042 m_t << "\\trowd \\trgaph108\\trleft-108"
1043 "\\trbrdrt\\brdrs\\brdrw10 "
1044 "\\trbrdrl\\brdrs\\brdrw10 "
1045 "\\trbrdrb\\brdrs\\brdrw10 "
1046 "\\trbrdrr\\brdrs\\brdrw10 "
1047 "\\trbrdrh\\brdrs\\brdrw10 "
1048 "\\trbrdrv\\brdrs\\brdrw10 \n";
1049 for (size_t i=0;i<r.numCells();i++)
1050 {
1051 if (r.isHeading())
1052 {
1053 m_t << "\\clcbpat16"; // set cell shading to light grey (color 16 in the clut)
1054 }
1055 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 "
1056 "\\clbrdrl\\brdrs\\brdrw10 "
1057 "\\clbrdrb\\brdrs\\brdrw10 "
1058 "\\clbrdrr \\brdrs\\brdrw10 "
1059 "\\cltxlrtb "
1060 "\\cellx" << ((i+1)*columnWidth) << "\n";
1061 }
1062 m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1063 m_lastIsPara=false;
1064 visitChildren(r);
1065 m_t << "\n";
1066 m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1067 m_t << "{\\row }\n";
1068 m_lastIsPara=false;
1069}
1070
1072{
1073 if (m_hide) return;
1074 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlCell &)}\n");
1075 m_t << "{" << align(c);
1076 m_lastIsPara=false;
1077 visitChildren(c);
1078 m_t << "\\cell }";
1079 m_lastIsPara=false;
1080}
1081
1083{
1084 if (m_hide) return;
1085 visitChildren(i);
1086}
1087
1089{
1090 if (m_hide) return;
1091 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHRef &)}\n");
1092 if (Config_getBool(RTF_HYPERLINKS))
1093 {
1094 if (href.url().startsWith("#"))
1095 {
1096 // when starting with # so a local link
1097 DString cite;
1098 cite = href.file() + "_" + href.url().right(href.url().length()-1);
1099 m_t << "{\\field "
1100 "{\\*\\fldinst "
1101 "{ HYPERLINK \\\\l \"" << rtfFormatBmkStr(cite) << "\" "
1102 "}{}"
1103 "}"
1104 "{\\fldrslt "
1105 "{\\cs37\\ul\\cf2 ";
1106 }
1107 else
1108 {
1109 m_t << "{\\field "
1110 "{\\*\\fldinst "
1111 "{ HYPERLINK \"" << href.url() << "\" "
1112 "}{}"
1113 "}"
1114 "{\\fldrslt "
1115 "{\\cs37\\ul\\cf2 ";
1116 }
1117 }
1118 else
1119 {
1120 m_t << "{\\f2 ";
1121 }
1122 m_lastIsPara=false;
1123 visitChildren(href);
1124 if (Config_getBool(RTF_HYPERLINKS))
1125 {
1126 m_t << "}"
1127 "}"
1128 "}";
1129 }
1130 else
1131 {
1132 m_t << "}";
1133 }
1134 m_lastIsPara=false;
1135}
1136
1138{
1139 if (m_hide) return;
1140 m_t << "{\\b ";
1141 visitChildren(s);
1142 m_t << "}\\par ";
1143}
1144
1146{
1147 if (m_hide) return;
1148 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlDetails &)}\n");
1149 if (!m_lastIsPara) m_t << "\\par\n";
1150 auto summary = d.summary();
1151 if (summary)
1152 {
1153 std::visit(*this,*summary);
1154 m_t << "{"; // start desc
1156 m_t << rtf_Style_Reset << getStyle("DescContinue");
1157 }
1158 visitChildren(d);
1159 if (!m_lastIsPara) m_t << "\\par\n";
1160 if (summary)
1161 {
1163 m_t << "}"; // end desc
1164 }
1165 m_lastIsPara=true;
1166}
1167
1169{
1170 if (m_hide) return;
1171 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlHeader &)}\n");
1172 m_t << "{" // start section
1173 << rtf_Style_Reset;
1174 DString heading;
1175 int level = std::clamp(header.level()+m_hierarchyLevel,SectionType::MinLevel,SectionType::MaxLevel);
1176 heading.sprintf("Heading%d",level);
1177 // set style
1178 m_t << rtf_Style[heading.str()].reference();
1179 // make open table of contents entry that will be closed in visitPost method
1180 m_t << "{\\tc\\tcl" << level << " ";
1181 m_lastIsPara=false;
1182 visitChildren(header);
1183 // close open table of contents entry
1184 m_t << "} \\par";
1185 m_t << "}\n"; // end section
1186 m_lastIsPara=true;
1187}
1188
1189void RTFDocVisitor::includePicturePreRTF(const DString &name, bool isTypeRTF, bool hasCaption, bool inlineImage)
1190{
1191 if (isTypeRTF)
1192 {
1193 if (!inlineImage)
1194 {
1195 m_t << "\\par\n";
1196 m_t << "{\n";
1197 m_t << rtf_Style_Reset << "\n";
1198 if (hasCaption || m_lastIsPara) m_t << "\\par\n";
1199 m_t << "\\pard \\qc ";
1200 }
1201 m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1202 m_t << name;
1203 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}\n";
1204 if (!inlineImage)
1205 {
1206 m_t << "\\par\n";
1207 if (hasCaption)
1208 {
1209 m_t << "\\pard \\qc \\b";
1210 m_t << "{Image \\field\\flddirty{\\*\\fldinst { SEQ Image \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
1211 }
1212 m_lastIsPara=true;
1213 }
1214 else
1215 {
1216 if (hasCaption) m_t << "{\\comment "; // to prevent caption to be shown
1217 }
1218 }
1219 else // other format -> skip
1220 {
1222 m_hide=true;
1223 }
1224}
1225
1226void RTFDocVisitor::includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool inlineImage)
1227{
1228 if (isTypeRTF)
1229 {
1230 if (m_hide) return;
1231 if (inlineImage)
1232 {
1233 if (hasCaption) m_t << " }";
1234 }
1235 else
1236 {
1237 if (hasCaption)
1238 {
1239 m_t << "}\n";
1240 m_t << "\\par}\n";
1241 }
1242 else
1243 {
1244 m_t << "}\n";
1245 }
1246 }
1247 }
1248 else
1249 {
1250 m_hide = popHidden();
1251 }
1252}
1253
1255{
1256 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocImage &)}\n");
1258 visitChildren(img);
1260}
1261
1262
1264{
1265 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocDotFile &)}\n");
1266 bool exists = false;
1267 std::string inBuf;
1268 if (readInputFile(df.file(),inBuf))
1269 {
1270 auto fileName = writeInlineGraph(Config_getString(RTF_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1271 ".dot", // extension
1272 inBuf, // contents
1273 exists);
1274 if (!fileName.empty())
1275 {
1276 writeDotFile(fileName, df.hasCaption(), df.srcFile(), df.srcLine(), !exists);
1277 visitChildren(df);
1279 }
1280 }
1281}
1283{
1284 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocMscFile &)}\n");
1285 bool exists = false;
1286 std::string inBuf;
1287 if (readInputFile(df.file(),inBuf))
1288 {
1289 auto fileName = writeInlineGraph(Config_getString(RTF_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1290 ".msc", // extension
1291 inBuf, // contents
1292 exists);
1293 if (!fileName.empty())
1294 {
1295 writeMscFile(fileName, df.hasCaption(), df.srcFile(), df.srcLine(), !exists);
1296 visitChildren(df);
1298 }
1299 }
1300}
1301
1303{
1304 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocDiaFile &)}\n");
1305 bool exists = false;
1306 std::string inBuf;
1307 if (readInputFile(df.file(),inBuf))
1308 {
1309 auto fileName = writeInlineGraph(Config_getString(RTF_OUTPUT)+"/"+stripPath(df.file())+"_", // baseName
1310 ".dia", // extension
1311 inBuf, // contents
1312 exists);
1313 if (!fileName.empty())
1314 {
1315 writeDiaFile(fileName, df.hasCaption(), df.srcFile(), df.srcLine(), !exists);
1316 visitChildren(df);
1318 }
1319 }
1320}
1321
1323{
1324 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocPlantUmlFile &)}\n");
1325 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df.file()));
1326 DString rtfOutput = Config_getString(RTF_OUTPUT);
1327 std::string inBuf;
1328 readInputFile(df.file(),inBuf);
1329 auto baseNameVector = PlantumlManager::instance().writePlantUMLSource(
1330 rtfOutput,DString(),inBuf,PlantumlManager::PUML_BITMAP,
1331 DString(),df.srcFile(),df.srcLine(),false);
1332 for(const auto &baseName: baseNameVector)
1333 {
1334 writePlantUMLFile(baseName, df.hasCaption());
1335 visitChildren(df);
1337 }
1338}
1339
1341{
1342 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocMermaidFile &)}\n");
1343 if (Config_getBool(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLIENT_SIDE) return;
1344 if (!Config_getBool(DOT_CLEANUP)) copyFile(df.file(),Config_getString(RTF_OUTPUT)+"/"+stripPath(df.file()));
1345 std::string inBuf;
1346 readInputFile(df.file(),inBuf);
1347 auto rtfOutput = Config_getString(RTF_OUTPUT);
1348 auto outputFormat = MermaidManager::OutputFormat::RTF;
1349 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
1351 rtfOutput,DString(),inBuf,imageFormat,
1352 df.srcFile(),df.srcLine());
1353 writeMermaidFile(baseName, df.hasCaption());
1354 visitChildren(df);
1356}
1357
1359{
1360 if (m_hide) return;
1361 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocLink &)}\n");
1362 startLink(lnk.ref(),lnk.file(),lnk.anchor());
1363 visitChildren(lnk);
1364 endLink(lnk.ref());
1365}
1366
1368{
1369 if (m_hide) return;
1370 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocRef &)}\n");
1371 // when ref.isSubPage()==true we use ref.file() for HTML and
1372 // ref.anchor() for LaTeX/RTF
1373 if (ref.isSubPage())
1374 {
1375 startLink(ref.ref(),DString(),ref.anchor());
1376 }
1377 else
1378 {
1379 if (!ref.file().empty()) startLink(ref.ref(),ref.file(),ref.anchor());
1380 }
1381 if (!ref.hasLinkText()) filter(ref.targetTitle());
1382 visitChildren(ref);
1383 if (!ref.file().empty()) endLink(ref.ref());
1384 //m_t << " ";
1385}
1386
1387
1389{
1390 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocSecRefItem &)}\n");
1391 visitChildren(ref);
1392}
1393
1395{
1396 if (m_hide) return;
1397 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocSecRefList &)}\n");
1398 m_t << "{\n";
1400 m_t << rtf_Style_Reset << getStyle("LatexTOC") << "\n";
1401 m_t << "\\par\n";
1402 m_lastIsPara=true;
1403 visitChildren(l);
1405 m_t << "\\par";
1406 m_t << "}\n";
1407 m_lastIsPara=true;
1408}
1409
1411{
1412 if (m_hide) return;
1413 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocParamSect &)}\n");
1414 m_t << "{"; // start param list
1415 if (!m_lastIsPara) m_t << "\\par\n";
1416 //m_t << "{\\b "; // start bold
1417 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
1418 switch(s.type())
1419 {
1421 m_t << theTranslator->trParameters(); break;
1423 m_t << theTranslator->trReturnValues(); break;
1425 m_t << theTranslator->trExceptions(); break;
1428 default:
1429 ASSERT(0);
1430 }
1431 m_t << "\\par";
1432 m_t << "}\n";
1433 bool useTable = s.type()==DocParamSect::Param ||
1437 if (!useTable)
1438 {
1440 }
1441 m_t << rtf_Style_Reset << getStyle("DescContinue");
1442 m_lastIsPara=true;
1443 visitChildren(s);
1444 //m_t << "\\par\n";
1445 if (!useTable)
1446 {
1448 }
1449 m_t << "}\n";
1450}
1451
1453{
1454 m_t << " " << sep.chars() << " ";
1455}
1456
1458{
1459 static int columnPos[4][5] =
1460 { { 2, 25, 100, 100, 100 }, // no inout, no type
1461 { 3, 14, 35, 100, 100 }, // inout, no type
1462 { 3, 25, 50, 100, 100 }, // no inout, type
1463 { 4, 14, 35, 55, 100 }, // inout, type
1464 };
1465 int config=0;
1466 if (m_hide) return;
1467 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocParamList &)}\n");
1468
1470 const DocParamSect *sect = std::get_if<DocParamSect>(pl.parent());
1471 if (sect)
1472 {
1473 parentType = sect->type();
1474 }
1475 bool useTable = parentType==DocParamSect::Param ||
1476 parentType==DocParamSect::RetVal ||
1477 parentType==DocParamSect::Exception ||
1478 parentType==DocParamSect::TemplateParam;
1479 if (sect && sect->hasInOutSpecifier()) config+=1;
1480 if (sect && sect->hasTypeSpecifier()) config+=2;
1481 if (useTable)
1482 {
1483 m_t << "\\trowd \\trgaph108\\trleft426\\tblind426"
1484 "\\trbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1485 "\\trbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1486 "\\trbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1487 "\\trbrdrr\\brdrs\\brdrw10\\brdrcf15 "
1488 "\\trbrdrh\\brdrs\\brdrw10\\brdrcf15 "
1489 "\\trbrdrv\\brdrs\\brdrw10\\brdrcf15 "<< "\n";
1490 for (int i=0;i<columnPos[config][0];i++)
1491 {
1492 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1493 "\\clbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1494 "\\clbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1495 "\\clbrdrr \\brdrs\\brdrw10\\brdrcf15 "
1496 "\\cltxlrtb "
1497 "\\cellx" << (rtf_pageWidth*columnPos[config][i+1]/100) << "\n";
1498 }
1499 m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1500 }
1501
1502 if (sect && sect->hasInOutSpecifier())
1503 {
1504 if (useTable)
1505 {
1506 m_t << "{";
1507 }
1508
1509 // Put in the direction: in/out/in,out if specified.
1511 {
1512 if (pl.direction()==DocParamSect::In)
1513 {
1514 m_t << "in";
1515 }
1516 else if (pl.direction()==DocParamSect::Out)
1517 {
1518 m_t << "out";
1519 }
1520 else if (pl.direction()==DocParamSect::InOut)
1521 {
1522 m_t << "in,out";
1523 }
1524 }
1525
1526 if (useTable)
1527 {
1528 m_t << "\\cell }";
1529 }
1530 }
1531
1532 if (sect && sect->hasTypeSpecifier())
1533 {
1534 if (useTable)
1535 {
1536 m_t << "{";
1537 }
1538 for (const auto &type : pl.paramTypes())
1539 {
1540 std::visit(*this,type);
1541 }
1542 if (useTable)
1543 {
1544 m_t << "\\cell }";
1545 }
1546 }
1547
1548
1549 if (useTable)
1550 {
1551 m_t << "{";
1552 }
1553
1554 m_t << "{\\i ";
1555 bool first=true;
1556 for (const auto &param : pl.parameters())
1557 {
1558 if (!first) m_t << ","; else first=false;
1559 std::visit(*this,param);
1560 }
1561 m_t << "} ";
1562
1563 if (useTable)
1564 {
1565 m_t << "\\cell }{";
1566 }
1567 m_lastIsPara=true;
1568
1569 for (const auto &par : pl.paragraphs())
1570 {
1571 std::visit(*this,par);
1572 }
1573
1574 if (useTable)
1575 {
1576 m_t << "\\cell }\n";
1577 //m_t << "\\pard \\widctlpar\\intbl\\adjustright\n";
1578 m_t << "{\\row }\n";
1579 }
1580 else
1581 {
1582 m_t << "\\par\n";
1583 }
1584
1585 m_lastIsPara=true;
1586}
1587
1589{
1590 if (m_hide) return;
1591 if (x.title().empty()) return;
1592 bool anonymousEnum = x.file()=="@";
1593 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocXRefItem &)}\n");
1594 if (!m_lastIsPara)
1595 {
1596 m_t << "\\par\n";
1597 m_lastIsPara=true;
1598 }
1599 m_t << "{"; // start param list
1600 //m_t << "{\\b "; // start bold
1601 m_t << "{" << rtf_Style["Heading5"].reference() << "\n";
1602 if (Config_getBool(RTF_HYPERLINKS) && !anonymousEnum)
1603 {
1604 DString refName;
1605 if (!x.file().empty())
1606 {
1607 refName+=stripPath(x.file());
1608 }
1609 if (!x.file().empty() && !x.anchor().empty())
1610 {
1611 refName+="_";
1612 }
1613 if (!x.anchor().empty())
1614 {
1615 refName+=x.anchor();
1616 }
1617
1618 m_t << "{\\field "
1619 "{\\*\\fldinst "
1620 "{ HYPERLINK \\\\l \"" << rtfFormatBmkStr(refName) << "\" "
1621 "}{}"
1622 "}"
1623 "{\\fldrslt "
1624 "{\\cs37\\ul\\cf2 ";
1625 filter(x.title());
1626 m_t << "}"
1627 "}"
1628 "}";
1629 }
1630 else
1631 {
1632 filter(x.title());
1633 }
1634 m_t << ":";
1635 m_t << "\\par";
1636 m_t << "}"; // end bold
1638 m_t << rtf_Style_Reset << getStyle("DescContinue");
1639 m_lastIsPara=false;
1640 visitChildren(x);
1641 if (x.title().empty()) return;
1642 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocXRefItem)}\n");
1643 m_t << "\\par\n";
1645 m_t << "}\n"; // end xref item
1646 m_lastIsPara=true;
1647}
1648
1650{
1651 if (m_hide) return;
1652 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocInternalRef &)}\n");
1653 startLink("",ref.file(),ref.anchor());
1654 visitChildren(ref);
1655 endLink("");
1656 m_t << " ";
1657}
1658
1660{
1661 if (m_hide) return;
1662 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocText &)}\n");
1663 visitChildren(t);
1664}
1665
1667{
1668 if (m_hide) return;
1669 DBG_RTF("{\\comment RTFDocVisitor::operator()(const DocHtmlBlockQuote &)}\n");
1670 if (!m_lastIsPara) m_t << "\\par\n";
1671 m_t << "{"; // start desc
1673 m_t << rtf_Style_Reset << getStyle("DescContinue");
1674 visitChildren(q);
1675 if (!m_lastIsPara) m_t << "\\par\n";
1677 m_t << "}"; // end desc
1678 m_lastIsPara=true;
1679}
1680
1682{
1683}
1684
1686{
1687 if (m_hide) return;
1688 visitChildren(pb);
1689}
1690
1691
1692//static char* getMultiByte(int c)
1693//{
1694// static char s[10];
1695// sprintf(s,"\\'%X",c);
1696// return s;
1697//}
1698
1699void RTFDocVisitor::filter(const DString &str,bool verbatim, const bool citeEntry)
1700{
1701 if (!str.empty())
1702 {
1703 const char *p=str.data();
1704 while (*p)
1705 {
1706 char c=*p++;
1707 switch (c)
1708 {
1709 case '{': m_t << "\\{"; break;
1710 case '}': m_t << "\\}"; break;
1711 case '\\': m_t << "\\\\"; break;
1712 case '&': // possibility to have a special symbol
1713 if (!citeEntry) { m_t << c; break;}
1715 m_t,
1716 p-1,
1717 [](HtmlEntityMapper::SymType symType) { return HtmlEntityMapper::instance().rtf(symType); },
1718 "&");
1719 break;
1720 case '\n': if (verbatim)
1721 {
1722 m_t << "\\par\n";
1723 }
1724 else
1725 {
1726 m_t << '\n';
1727 }
1728 break;
1729 default: m_t << c;
1730 }
1731 }
1732 }
1733}
1734
1735void RTFDocVisitor::startLink(const DString &ref,const DString &file,const DString &anchor)
1736{
1737 if (ref.empty() && Config_getBool(RTF_HYPERLINKS))
1738 {
1739 DString refName;
1740 if (!file.empty())
1741 {
1742 refName+=stripPath(file);
1743 }
1744 if (!file.empty() && !anchor.empty())
1745 {
1746 refName+='_';
1747 }
1748 if (!anchor.empty())
1749 {
1750 refName+=anchor;
1751 }
1752
1753 m_t << "{\\field {\\*\\fldinst { HYPERLINK \\\\l \"";
1754 m_t << rtfFormatBmkStr(refName);
1755 m_t << "\" }{}";
1756 m_t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
1757 }
1758 else
1759 {
1760 m_t << "{\\b ";
1761 }
1762 m_lastIsPara=false;
1763}
1764
1766{
1767 if (ref.empty() && Config_getBool(RTF_HYPERLINKS))
1768 {
1769 m_t << "}}}";
1770 }
1771 else
1772 {
1773 m_t << "}";
1774 }
1775 m_lastIsPara=false;
1776}
1777
1778void RTFDocVisitor::writeDotFile(const DString &filename, bool hasCaption,
1779 const DString &srcFile, int srcLine, bool newFile)
1780{
1781 DString baseName=makeBaseName(filename,".dot");
1782 DString outDir = Config_getString(RTF_OUTPUT);
1783 if (newFile) writeDotGraphFromFile(filename,outDir,baseName,GraphOutputFormat::BITMAP,srcFile,srcLine,false);
1784 DString imgExt = getDotImageExtension();
1785 includePicturePreRTF(baseName + "." + imgExt, true, hasCaption);
1786}
1787
1788void RTFDocVisitor::writeMscFile(const DString &fileName, bool hasCaption,
1789 const DString &srcFile, int srcLine, bool newFile)
1790{
1791 DString baseName=makeBaseName(fileName,".msc");
1792 DString outDir = Config_getString(RTF_OUTPUT);
1793 if (newFile) writeMscGraphFromFile(fileName,outDir,baseName,MscOutputFormat::BITMAP,srcFile,srcLine,false);
1794 includePicturePreRTF(baseName + ".png", true, hasCaption);
1795}
1796
1797void RTFDocVisitor::writeDiaFile(const DString &fileName, bool hasCaption,
1798 const DString &srcFile, int srcLine, bool newFile)
1799{
1800 DString baseName=makeBaseName(fileName,".dia");
1801 DString outDir = Config_getString(RTF_OUTPUT);
1802 if (newFile) writeDiaGraphFromFile(fileName,outDir,baseName,DiaOutputFormat::BITMAP,srcFile,srcLine,false);
1803 includePicturePreRTF(baseName + ".png", true, hasCaption);
1804}
1805
1806void RTFDocVisitor::writePlantUMLFile(const DString &fileName, bool hasCaption)
1807{
1808 DString baseName=makeBaseName(fileName,".pu");
1809 DString outDir = Config_getString(RTF_OUTPUT);
1811 includePicturePreRTF(baseName + ".png", true, hasCaption);
1812}
1813
1814void RTFDocVisitor::writeMermaidFile(const DString &fileName, bool hasCaption)
1815{
1816 if (Config_getBool(MERMAID_RENDER_MODE)==MERMAID_RENDER_MODE_t::CLIENT_SIDE) return;
1817 auto baseName = makeBaseName(fileName,".mmd");
1818 auto outDir = Config_getString(RTF_OUTPUT);
1819 auto outputFormat = MermaidManager::OutputFormat::RTF;
1820 auto imageFormat = MermaidManager::convertToImageFormat(outputFormat);
1821 auto imgExt = MermaidManager::imageExtension(imageFormat);
1822 MermaidManager::instance().generateMermaidOutput(fileName,outDir,imageFormat,false);
1823 includePicturePreRTF(baseName + "." + imgExt, true, hasCaption);
1824}
static CodeFragmentManager & instance()
void parseCodeFragment(OutputCodeList &codeOutList, const DString &fileName, const DString &blockId, const DString &scopeName, bool showLineNumbers, bool trimLeft, bool stripCodeComments)
virtual void parseCode(OutputCodeList &codeOutList, const DString &scopeName, const DString &input, SrcLangExt lang, bool stripCodeComments, const CodeParserOptions &options)=0
Parses a source file or fragment with the goal to produce highlighted and cross-referenced output.
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
static DString integerToAlpha(int n, bool upper=true)
Definition dstring.cpp:622
DString & setNum(short n)
Definition dstring.h:552
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
static DString integerToRoman(int n, bool upper=true)
Definition dstring.cpp:638
DString right(size_t len) const
Definition dstring.h:311
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
const std::string & str() const
Definition dstring.h:645
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
bool startsWith(const char *s) const
Definition dstring.h:600
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
Node representing an anchor.
Definition docnode.h:229
DString anchor() const
Definition docnode.h:232
DString file() const
Definition docnode.h:233
Node representing an auto List.
Definition docnode.h:571
bool isCheckedList() const
Definition docnode.h:582
bool isEnumList() const
Definition docnode.h:580
Node representing an item of a auto list.
Definition docnode.h:595
int itemNumber() const
Definition docnode.h:598
Node representing a citation of some bibliographic reference.
Definition docnode.h:245
DString ref() const
Definition docnode.h:250
DString getText() const
Definition docnode.cpp:979
DString anchor() const
Definition docnode.h:251
CiteInfoOption option() const
Definition docnode.h:253
DString target() const
Definition docnode.h:252
DString file() const
Definition docnode.h:248
Node representing a dia file.
Definition docnode.h:731
DString file() const
Definition docnode.h:685
DString srcFile() const
Definition docnode.h:691
int srcLine() const
Definition docnode.h:692
bool hasCaption() const
Definition docnode.h:687
Node representing a dot file.
Definition docnode.h:713
Node representing an emoji.
Definition docnode.h:341
int index() const
Definition docnode.h:345
DString name() const
Definition docnode.h:344
Node representing an item of a cross-referenced list.
Definition docnode.h:529
DString relPath() const
Definition docnode.h:534
bool isInline() const
Definition docnode.h:536
DString name() const
Definition docnode.h:532
Node representing a Hypertext reference.
Definition docnode.h:832
DString file() const
Definition docnode.h:840
DString url() const
Definition docnode.h:839
Node representing a horizontal ruler.
Definition docnode.h:216
Node representing an HTML blockquote.
Definition docnode.h:1296
Node representing a HTML table caption.
Definition docnode.h:1233
DString file() const
Definition docnode.h:1239
DString anchor() const
Definition docnode.h:1240
Node representing a HTML table cell.
Definition docnode.h:1198
const HtmlAttribList & attribs() const
Definition docnode.h:1210
Node representing a HTML description data.
Definition docnode.h:1186
Node representing a Html description list.
Definition docnode.h:910
Node representing a Html description item.
Definition docnode.h:897
Node Html details.
Definition docnode.h:866
const DocNodeVariant * summary() const
Definition docnode.h:873
Node Html heading.
Definition docnode.h:882
int level() const
Definition docnode.h:886
Node representing a Html list.
Definition docnode.h:1009
const HtmlAttribList & attribs() const
Definition docnode.h:1015
Type type() const
Definition docnode.h:1014
Node representing a HTML list item.
Definition docnode.h:1170
const HtmlAttribList & attribs() const
Definition docnode.h:1175
Node representing a HTML table row.
Definition docnode.h:1251
bool isHeading() const
Definition docnode.cpp:2007
size_t numCells() const
Definition docnode.h:1256
Node Html summary.
Definition docnode.h:853
Node representing a HTML table.
Definition docnode.h:1274
const DocNodeVariant * caption() const
Definition docnode.cpp:2255
Node representing an image.
Definition docnode.h:642
Type type() const
Definition docnode.h:647
DString name() const
Definition docnode.h:648
bool isInlineImage() const
Definition docnode.h:654
bool hasCaption() const
Definition docnode.h:649
Node representing a include/dontinclude operator block.
Definition docnode.h:477
bool stripCodeComments() const
Definition docnode.h:506
bool isLast() const
Definition docnode.h:503
DString text() const
Definition docnode.h:499
DString context() const
Definition docnode.h:501
DString exampleFile() const
Definition docnode.h:508
DString includeFileName() const
Definition docnode.h:509
int line() const
Definition docnode.h:497
Type type() const
Definition docnode.h:485
bool isFirst() const
Definition docnode.h:502
bool showLineNo() const
Definition docnode.h:498
bool isExample() const
Definition docnode.h:507
Node representing an included text block from file.
Definition docnode.h:435
bool stripCodeComments() const
Definition docnode.h:455
DString blockId() const
Definition docnode.h:454
@ LatexInclude
Definition docnode.h:437
@ SnippetWithLines
Definition docnode.h:438
@ DontIncWithLines
Definition docnode.h:439
@ IncWithLines
Definition docnode.h:438
@ HtmlInclude
Definition docnode.h:437
@ VerbInclude
Definition docnode.h:437
@ DontInclude
Definition docnode.h:437
@ DocbookInclude
Definition docnode.h:439
DString context() const
Definition docnode.h:453
Type type() const
Definition docnode.h:451
DString exampleFile() const
Definition docnode.h:457
DString text() const
Definition docnode.h:452
DString file() const
Definition docnode.h:449
DString extension() const
Definition docnode.h:450
bool trimLeft() const
Definition docnode.h:459
bool isExample() const
Definition docnode.h:456
Node representing an entry in the index.
Definition docnode.h:552
DString entry() const
Definition docnode.h:559
Node representing an internal section of documentation.
Definition docnode.h:978
Node representing an internal reference to some item.
Definition docnode.h:816
DString anchor() const
Definition docnode.h:822
DString file() const
Definition docnode.h:820
Node representing a line break.
Definition docnode.h:202
Node representing a word that can be linked to something.
Definition docnode.h:165
DString word() const
Definition docnode.h:170
DString anchor() const
Definition docnode.h:174
DString ref() const
Definition docnode.h:173
DString file() const
Definition docnode.h:171
Node representing a mermaid file.
Definition docnode.h:749
Node representing a msc file.
Definition docnode.h:722
DocNodeVariant * parent()
Definition docnode.h:89
Node representing an block of paragraphs.
Definition docnode.h:988
Node representing a paragraph in the documentation tree.
Definition docnode.h:1089
bool isLast() const
Definition docnode.h:1097
Node representing a parameter list.
Definition docnode.h:1130
const DocNodeList & parameters() const
Definition docnode.h:1134
const DocNodeList & paramTypes() const
Definition docnode.h:1135
DocParamSect::Direction direction() const
Definition docnode.h:1138
const DocNodeList & paragraphs() const
Definition docnode.h:1136
Node representing a parameter section.
Definition docnode.h:1062
bool hasInOutSpecifier() const
Definition docnode.h:1078
bool hasTypeSpecifier() const
Definition docnode.h:1079
Type type() const
Definition docnode.h:1077
Node representing a uml file.
Definition docnode.h:740
Node representing a reference to some item.
Definition docnode.h:787
DString ref() const
Definition docnode.h:793
DString file() const
Definition docnode.h:791
bool isSubPage() const
Definition docnode.h:801
DString anchor() const
Definition docnode.h:794
bool hasLinkText() const
Definition docnode.h:797
DString targetTitle() const
Definition docnode.h:795
Root node of documentation tree.
Definition docnode.h:1318
bool singleLine() const
Definition docnode.h:1324
bool indent() const
Definition docnode.h:1323
Node representing a reference to a section.
Definition docnode.h:944
Node representing a list of section references.
Definition docnode.h:968
Node representing a normal section.
Definition docnode.h:923
DString file() const
Definition docnode.h:931
int level() const
Definition docnode.h:927
DString anchor() const
Definition docnode.h:929
const DocNodeVariant * title() const
Definition docnode.h:928
Node representing a separator.
Definition docnode.h:365
DString chars() const
Definition docnode.h:369
Node representing a simple list.
Definition docnode.h:999
Node representing a simple list item.
Definition docnode.h:1158
const DocNodeVariant * paragraph() const
Definition docnode.h:1162
Node representing a simple section.
Definition docnode.h:1026
Type type() const
Definition docnode.h:1035
const DocNodeVariant * title() const
Definition docnode.h:1042
Node representing a separator between two simple sections of the same type.
Definition docnode.h:1053
Node representing a style change.
Definition docnode.h:268
Style style() const
Definition docnode.h:307
bool enable() const
Definition docnode.h:309
Node representing a special symbol.
Definition docnode.h:328
HtmlEntityMapper::SymType symbol() const
Definition docnode.h:332
Root node of a text fragment.
Definition docnode.h:1309
Node representing a simple section title.
Definition docnode.h:608
Node representing a URL (or email address).
Definition docnode.h:188
DString url() const
Definition docnode.h:192
bool isEmail() const
Definition docnode.h:193
Node representing a verbatim, unparsed text fragment.
Definition docnode.h:376
DString text() const
Definition docnode.h:383
int srcLine() const
Definition docnode.h:398
bool hasCaption() const
Definition docnode.h:390
DString language() const
Definition docnode.h:388
bool isExample() const
Definition docnode.h:385
Type type() const
Definition docnode.h:382
DString exampleFile() const
Definition docnode.h:386
DString srcFile() const
Definition docnode.h:397
DString context() const
Definition docnode.h:384
DString engine() const
Definition docnode.h:393
@ JavaDocLiteral
Definition docnode.h:378
Node representing a VHDL flow chart.
Definition docnode.h:758
void pushHidden(bool hide)
CodeParserInterface & getCodeParser(const DString &langExt)
bool popHidden()
Node representing some amount of white space.
Definition docnode.h:354
DString chars() const
Definition docnode.h:358
Node representing a word.
Definition docnode.h:153
DString word() const
Definition docnode.h:156
Node representing an item of a cross-referenced list.
Definition docnode.h:621
DString anchor() const
Definition docnode.h:625
DString file() const
Definition docnode.h:624
DString title() const
Definition docnode.h:626
const char * unicode(int index) const
Access routine to the unicode sequence for the Emoji entity.
Definition emoji.cpp:2019
static EmojiEntityMapper & instance()
Returns the one and only instance of the Emoji entity mapper.
Definition emoji.cpp:1981
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
std::string fileName() const
Definition fileinfo.cpp:122
std::string dirPath(bool absPath=true) const
Definition fileinfo.cpp:141
const char * writeHtmlEntity(T &result, const char *s, HtmlEntityMapperFunc &&mapper, const char *fallback)
Definition htmlentity.h:127
static HtmlEntityMapper & instance()
Returns the one and only instance of the HTML entity mapper.
const char * rtf(SymType symb) const
Access routine to the RTF code of the HTML entity.
static MermaidManager & instance()
Definition mermaid.cpp:38
static DString imageExtension(ImageFormat imageFormat)
Definition mermaid.cpp:48
static ImageFormat convertToImageFormat(OutputFormat outputFormat)
Definition mermaid.cpp:59
void generateMermaidOutput(const DString &baseName, const DString &outDir, ImageFormat format, bool toIndex)
Register a generated Mermaid image with the index.
Definition mermaid.cpp:121
DString writeMermaidSource(const DString &outDirArg, const DString &fileName, const DString &content, ImageFormat format, const DString &srcFile, int srcLine)
Write a Mermaid source file and register it for CLI rendering.
Definition mermaid.cpp:75
Class representing a list of different code generators.
Definition outputlist.h:162
void generatePlantUMLOutput(const DString &baseName, const DString &outDir, OutputFormat format, bool toIndex)
Convert a PlantUML file to an image.
Definition plantuml.cpp:207
StringVector writePlantUMLSource(const DString &outDirArg, const DString &fileName, const DString &content, OutputFormat format, const DString &engine, const DString &srcFile, int srcLine, bool inlineCode)
Write a PlantUML compatible file.
Definition plantuml.cpp:37
static PlantumlManager & instance()
Definition plantuml.cpp:236
int indentLevel() const
void writeDotFile(const DString &fileName, bool hasCaption, const DString &srcFile, int srcLine, bool newFile=true)
RTFDocVisitor(TextStream &t, OutputCodeList &ci, const DString &langExt, int hierarchyLevel=0)
void visitChildren(const T &t)
void writeMscFile(const DString &fileName, bool hasCaption, const DString &srcFile, int srcLine, bool newFile=true)
DString getListTable(const int id)
void writeDiaFile(const DString &fileName, bool hasCaption, const DString &srcFile, int srcLine, bool newFile=true)
void startLink(const DString &ref, const DString &file, const DString &anchor)
OutputCodeList & m_ci
void includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool inlineImage=false)
void writeMermaidFile(const DString &fileName, bool hasCaption)
DString getStyle(const DString &name)
void endLink(const DString &ref)
void includePicturePreRTF(const DString &name, bool isTypeRTF, bool hasCaption, bool inlineImage=false)
static const int maxIndentLevels
void writePlantUMLFile(const DString &fileName, bool hasCaption)
void filter(const DString &str, bool verbatim=false, const bool citeEntry=false)
TextStream & m_t
RTFListItemInfo m_listItemInfo[maxIndentLevels]
void operator()(const DocWord &)
static constexpr int MaxLevel
Definition section.h:39
static constexpr int MinLevel
Definition section.h:32
Text streaming class that buffers data.
Definition textstream.h:36
virtual DString trExceptions()=0
virtual DString trReturns()=0
virtual DString trParameters()=0
virtual DString trCopyright()=0
virtual DString trWarning()=0
virtual DString trSince()=0
virtual DString trNote()=0
virtual DString trAuthor(bool first_capital, bool singular)=0
virtual DString trReturnValues()=0
virtual DString trVersion()=0
virtual DString trTemplateParameters()=0
virtual DString trImportant()=0
virtual DString trPrecondition()=0
virtual DString trAttention()=0
virtual DString trInvariant()=0
virtual DString trRemarks()=0
virtual DString trDate()=0
virtual DString trSeeAlso()=0
virtual DString trPostcondition()=0
#define Config_getBool(name)
Definition config.h:33
#define Config_getString(name)
Definition config.h:32
void writeDiaGraphFromFile(const DString &inFile, const DString &outDir, const DString &outFile, DiaOutputFormat format, const DString &srcFile, int srcLine, bool toIndex)
Definition dia.cpp:29
void writeDotGraphFromFile(const DString &inFile, const DString &outDir, const DString &outFile, GraphOutputFormat format, const DString &srcFile, int srcLine, bool toIndex)
Definition dot.cpp:196
std::unique_ptr< FileDef > createFileDef(const DString &p, const DString &n, const DString &ref, const DString &dn)
Definition filedef.cpp:267
Translator * theTranslator
Definition language.cpp:76
#define err(fmt,...)
Definition message.h:127
#define ASSERT(x)
Definition message.h:142
void writeMscGraphFromFile(const DString &inFile, const DString &outDir, const DString &outFile, MscOutputFormat format, const DString &srcFile, int srcLine, bool toIndex)
Definition msc.cpp:160
Portable versions of functions that are platform dependent.
static DString align(const DocHtmlCell &cell)
#define DBG_RTF(x)
DString rtfFormatBmkStr(const DString &name)
Definition rtfgen.cpp:2879
StyleDataMap rtf_Style
Definition rtfstyle.cpp:366
char rtf_Style_Reset[]
Definition rtfstyle.cpp:54
Rtf_Table_Default rtf_Table_Default[]
Definition rtfstyle.cpp:250
const int rtf_pageWidth
Definition rtfstyle.h:26
Options to configure the code parser.
Definition parserintf.h:77
CodeParserOptions & setStartLine(int lineNr)
Definition parserintf.h:100
CodeParserOptions & setInlineFragment(bool enable)
Definition parserintf.h:106
CodeParserOptions & setShowLineNumbers(bool enable)
Definition parserintf.h:112
CodeParserOptions & setFileDef(const FileDef *fd)
Definition parserintf.h:97
const char * definition
Definition rtfstyle.h:50
const char * place
Definition rtfstyle.h:51
DString reference() const
Definition rtfstyle.h:69
SrcLangExt
Definition types.h:207
DString writeInlineGraph(const DString &baseName, const DString &extension, const DString &content, bool &exists)
Definition util.cpp:5358
DString getFileNameExtension(const DString &fn)
Definition util.cpp:4210
bool readInputFile(const DString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:4374
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4168
bool copyFile(const DString &src, const DString &dest)
Copies the contents of file with name src to the newly created file with name dest.
Definition util.cpp:4619
DString getDotImageExtension()
Definition util.cpp:4964
DString makeBaseName(const DString &name, const DString &ext)
Definition util.cpp:3974
DString stripPath(const DString &s)
Definition util.cpp:3960
SrcLangExt getLanguageFromCodeLang(DString &fileName)
Routine to handle the language attribute of the \code command.
Definition util.cpp:4186
A bunch of utility functions.