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