1 /******************************************************************************
6 * Copyright (C) 1997-2015 by Dimitri van Heesch.
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation under the terms of the GNU General Public License is hereby
10 * granted. No representations are made about the suitability of this software
11 * for any purpose. It is provided "as is" without express or implied warranty.
12 * See the GNU General Public License for more details.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
19 #include <qfileinfo.h>
21 #include "rtfdocvisitor.h"
22 #include "docparser.h"
25 #include "outputgen.h"
31 #include "parserintf.h"
36 #include "htmlentity.h"
40 //#define DBG_RTF(x) m_t << x
41 #define DBG_RTF(x) do {} while(0)
43 static QCString align(DocHtmlCell *cell)
45 HtmlAttribList attrs = cell->attribs();
47 for (i=0; i<attrs.count(); ++i)
49 if (attrs.at(i)->name.lower()=="align")
51 if (attrs.at(i)->value.lower()=="center")
53 else if (attrs.at(i)->value.lower()=="right")
61 RTFDocVisitor::RTFDocVisitor(FTextStream &t,CodeOutputInterface &ci,
63 : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_insidePre(FALSE),
64 m_hide(FALSE), m_indentLevel(0), m_lastIsPara(FALSE), m_langExt(langExt)
68 QCString RTFDocVisitor::getStyle(const char *name)
71 n.sprintf("%s%d",name,m_indentLevel);
72 StyleData *sd = rtf_Style[n];
77 void RTFDocVisitor::incIndentLevel()
79 if (m_indentLevel<rtf_maxIndentLevels-1) m_indentLevel++;
82 void RTFDocVisitor::decIndentLevel()
84 if (m_indentLevel>0) m_indentLevel--;
87 //--------------------------------------
88 // visitor functions for leaf nodes
89 //--------------------------------------
91 void RTFDocVisitor::visit(DocWord *w)
94 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWord)}\n");
99 void RTFDocVisitor::visit(DocLinkedWord *w)
102 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLinkedWord)}\n");
103 startLink(w->ref(),w->file(),w->anchor());
109 void RTFDocVisitor::visit(DocWhiteSpace *w)
112 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWhiteSpace)}\n");
124 void RTFDocVisitor::visit(DocSymbol *s)
127 DBG_RTF("{\\comment RTFDocVisitor::visit(DocSymbol)}\n");
128 const char *res = HtmlEntityMapper::instance()->rtf(s->symbol());
135 err("RTF: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
140 void RTFDocVisitor::visit(DocEmoji *s)
143 DBG_RTF("{\\comment RTFDocVisitor::visit(DocEmoji)}\n");
144 const char *res = EmojiEntityMapper::instance()->unicode(s->index());
154 case '&': case '#': case 'x':
158 val = 0xd800 + ( ( val1 - 0x10000 ) & 0xffc00 ) / 0x400 - 0x10000;
159 m_t << "\\u" << val << "?";
160 val = 0xdC00 + ( ( val1 - 0x10000 ) & 0x3ff ) - 0x10000 ;
161 m_t << "\\u" << val << "?";
164 case '0': case '1': case '2': case '3': case '4':
165 case '5': case '6': case '7': case '8': case '9':
166 val = val * 16 + *p - '0';
168 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
169 val = val * 16 + *p - 'a' + 10;
182 void RTFDocVisitor::visit(DocURL *u)
185 DBG_RTF("{\\comment RTFDocVisitor::visit(DocURL)}\n");
186 if (Config_getBool(RTF_HYPERLINKS))
191 if (u->isEmail()) m_t << "mailto:";
212 void RTFDocVisitor::visit(DocLineBreak *)
215 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLineBreak)}\n");
216 m_t << "\\par" << endl;
220 void RTFDocVisitor::visit(DocHorRuler *)
223 DBG_RTF("{\\comment RTFDocVisitor::visit(DocHorRuler)}\n");
224 m_t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}" << endl;
228 void RTFDocVisitor::visit(DocStyleChange *s)
232 DBG_RTF("{\\comment RTFDocVisitor::visit(DocStyleChange)}\n");
235 case DocStyleChange::Bold:
236 if (s->enable()) m_t << "{\\b "; else m_t << "} ";
238 case DocStyleChange::Strike:
239 if (s->enable()) m_t << "{\\strike "; else m_t << "} ";
241 case DocStyleChange::Underline:
242 if (s->enable()) m_t << "{\\ul "; else m_t << "} ";
244 case DocStyleChange::Italic:
245 if (s->enable()) m_t << "{\\i "; else m_t << "} ";
247 case DocStyleChange::Code:
248 if (s->enable()) m_t << "{\\f2 "; else m_t << "} ";
250 case DocStyleChange::Subscript:
251 if (s->enable()) m_t << "{\\sub "; else m_t << "} ";
253 case DocStyleChange::Superscript:
254 if (s->enable()) m_t << "{\\super "; else m_t << "} ";
256 case DocStyleChange::Center:
257 if (s->enable()) m_t << "{\\qc "; else m_t << "} ";
259 case DocStyleChange::Small:
260 if (s->enable()) m_t << "{\\sub "; else m_t << "} ";
262 case DocStyleChange::Preformatted:
266 m_t << "\\par" << endl;
267 m_t << rtf_Style_Reset << getStyle("CodeExample");
278 case DocStyleChange::Div: /* HTML only */ break;
279 case DocStyleChange::Span: /* HTML only */ break;
283 static void visitCaption(RTFDocVisitor *parent, QList<DocNode> children)
285 QListIterator<DocNode> cli(children);
287 for (cli.toFirst();(n=cli.current());++cli) n->accept(parent);
290 void RTFDocVisitor::visit(DocVerbatim *s)
293 DBG_RTF("{\\comment RTFDocVisitor::visit(DocVerbatim)}\n");
294 QCString lang = m_langExt;
295 if (!s->language().isEmpty()) // explicit language setting
297 lang = s->language();
299 SrcLangExt langExt = getLanguageFromFileName(lang);
302 case DocVerbatim::Code: // fall though
304 m_t << "\\par" << endl;
305 m_t << rtf_Style_Reset << getStyle("CodeExample");
306 Doxygen::parserManager->getParser(lang)
307 ->parseCode(m_ci,s->context(),s->text(),langExt,
308 s->isExample(),s->exampleFile());
309 //m_t << "\\par" << endl;
312 case DocVerbatim::Verbatim:
314 m_t << "\\par" << endl;
315 m_t << rtf_Style_Reset << getStyle("CodeExample");
316 filter(s->text(),TRUE);
317 //m_t << "\\par" << endl;
320 case DocVerbatim::RtfOnly:
323 case DocVerbatim::HtmlOnly:
324 case DocVerbatim::LatexOnly:
325 case DocVerbatim::XmlOnly:
326 case DocVerbatim::ManOnly:
327 case DocVerbatim::DocbookOnly:
330 case DocVerbatim::Dot:
332 static int dotindex = 1;
333 QCString fileName(4096);
335 fileName.sprintf("%s%d%s",
336 (Config_getString(RTF_OUTPUT)+"/inline_dotgraph_").data(),
340 QFile file(fileName);
341 if (!file.open(IO_WriteOnly))
343 err("Could not open file %s for writing\n",fileName.data());
345 file.writeBlock( s->text(), s->text().length() );
348 writeDotFile(fileName, s->hasCaption());
349 visitCaption(this, s->children());
350 includePicturePostRTF(true, s->hasCaption());
352 if (Config_getBool(DOT_CLEANUP)) file.remove();
355 case DocVerbatim::Msc:
357 static int mscindex = 1;
358 QCString baseName(4096);
360 baseName.sprintf("%s%d%s",
361 (Config_getString(RTF_OUTPUT)+"/inline_mscgraph_").data(),
365 QFile file(baseName);
366 if (!file.open(IO_WriteOnly))
368 err("Could not open file %s for writing\n",baseName.data());
370 QCString text = "msc {";
373 file.writeBlock( text, text.length() );
376 writeMscFile(baseName, s->hasCaption());
377 visitCaption(this, s->children());
378 includePicturePostRTF(true, s->hasCaption());
380 if (Config_getBool(DOT_CLEANUP)) file.remove();
383 case DocVerbatim::PlantUML:
385 static QCString rtfOutput = Config_getString(RTF_OUTPUT);
386 QCString baseName = writePlantUMLSource(rtfOutput,s->exampleFile(),s->text());
388 writePlantUMLFile(baseName, s->hasCaption());
389 visitCaption(this, s->children());
390 includePicturePostRTF(true, s->hasCaption());
397 void RTFDocVisitor::visit(DocAnchor *anc)
400 DBG_RTF("{\\comment RTFDocVisitor::visit(DocAnchor)}\n");
402 if (!anc->file().isEmpty())
406 if (!anc->file().isEmpty() && !anc->anchor().isEmpty())
410 if (!anc->anchor().isEmpty())
412 anchor+=anc->anchor();
414 m_t << "{\\bkmkstart " << rtfFormatBmkStr(anchor) << "}" << endl;
415 m_t << "{\\bkmkend " << rtfFormatBmkStr(anchor) << "}" << endl;
419 void RTFDocVisitor::visit(DocInclude *inc)
422 SrcLangExt langExt = getLanguageFromFileName(inc->extension());
423 DBG_RTF("{\\comment RTFDocVisitor::visit(DocInclude)}\n");
426 case DocInclude::IncWithLines:
429 m_t << "\\par" << endl;
430 m_t << rtf_Style_Reset << getStyle("CodeExample");
431 QFileInfo cfi( inc->file() );
432 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
433 Doxygen::parserManager->getParser(inc->extension())
434 ->parseCode(m_ci,inc->context(),
442 FALSE, // inline fragment
444 TRUE // show line numbers
450 case DocInclude::Include:
452 m_t << "\\par" << endl;
453 m_t << rtf_Style_Reset << getStyle("CodeExample");
454 Doxygen::parserManager->getParser(inc->extension())
455 ->parseCode(m_ci,inc->context(),
456 inc->text(),langExt,inc->isExample(),
461 TRUE, // inlineFragment
463 FALSE // show line numbers
468 case DocInclude::DontInclude:
470 case DocInclude::HtmlInclude:
472 case DocInclude::LatexInclude:
474 case DocInclude::VerbInclude:
476 m_t << "\\par" << endl;
477 m_t << rtf_Style_Reset << getStyle("CodeExample");
482 case DocInclude::Snippet:
484 if (!m_lastIsPara) m_t << "\\par" << endl;
485 m_t << rtf_Style_Reset << getStyle("CodeExample");
486 Doxygen::parserManager->getParser(inc->extension())
489 extractBlock(inc->text(),inc->blockId()),
496 case DocInclude::SnipWithLines:
498 QFileInfo cfi( inc->file() );
499 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
501 if (!m_lastIsPara) m_t << "\\par" << endl;
502 m_t << rtf_Style_Reset << getStyle("CodeExample");
503 Doxygen::parserManager->getParser(inc->extension())
506 extractBlock(inc->text(),inc->blockId()),
511 lineBlock(inc->text(),inc->blockId()),
513 FALSE, // inlineFragment
515 TRUE // show line number
520 case DocInclude::SnippetDoc:
521 case DocInclude::IncludeDoc:
522 err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
523 "Please create a bug report\n",__FILE__);
529 void RTFDocVisitor::visit(DocIncOperator *op)
531 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
532 // op->type(),op->isFirst(),op->isLast(),op->text().data());
533 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIncOperator)}\n");
534 SrcLangExt langExt = getLanguageFromFileName(m_langExt);
540 m_t << "\\par" << endl;
541 m_t << rtf_Style_Reset << getStyle("CodeExample");
546 if (op->type()!=DocIncOperator::Skip)
551 Doxygen::parserManager->getParser(m_langExt)
552 ->parseCode(m_ci,op->context(),op->text(),langExt,
553 op->isExample(),op->exampleFile());
570 if (!m_hide) m_t << endl;
575 void RTFDocVisitor::visit(DocFormula *f)
578 DBG_RTF("{\\comment RTFDocVisitor::visit(DocFormula)}\n");
579 bool bDisplay = !f->isInline();
584 m_t << "\\pard\\plain";
588 m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"" << f->relPath() << f->name() << ".png\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}";
596 void RTFDocVisitor::visit(DocIndexEntry *i)
599 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIndexEntry)}\n");
600 m_t << "{\\xe \\v " << i->entry() << "}" << endl;
604 void RTFDocVisitor::visit(DocSimpleSectSep *)
608 void RTFDocVisitor::visit(DocCite *cite)
611 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCite)}\n");
612 if (!cite->file().isEmpty())
614 startLink(cite->ref(),cite->file(),cite->anchor());
620 filter(cite->text());
621 if (!cite->file().isEmpty())
623 endLink(cite->ref());
632 //--------------------------------------
633 // visitor functions for compound nodes
634 //--------------------------------------
636 void RTFDocVisitor::visitPre(DocAutoList *l)
639 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoList)}\n");
641 rtf_listItemInfo[m_indentLevel].isEnum = l->isEnumList();
642 rtf_listItemInfo[m_indentLevel].number = 1;
646 void RTFDocVisitor::visitPost(DocAutoList *)
649 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoList)}\n");
650 if (!m_lastIsPara) m_t << "\\par";
653 if (!m_indentLevel) m_t << "\\par";
656 void RTFDocVisitor::visitPre(DocAutoListItem *)
659 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoListItem)}\n");
660 if (!m_lastIsPara) m_t << "\\par" << endl;
661 m_t << rtf_Style_Reset;
662 if (rtf_listItemInfo[m_indentLevel].isEnum)
664 m_t << getStyle("ListEnum") << endl;
665 m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab ";
666 rtf_listItemInfo[m_indentLevel].number++;
670 m_t << getStyle("ListBullet") << endl;
676 void RTFDocVisitor::visitPost(DocAutoListItem *)
679 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoListItem)}\n");
682 void RTFDocVisitor::visitPre(DocPara *)
684 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
687 void RTFDocVisitor::visitPost(DocPara *p)
690 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
692 !p->isLast() && // omit <p> for last paragraph
693 !(p->parent() && // and for parameters & sections
694 p->parent()->kind()==DocNode::Kind_ParamSect
698 m_t << "\\par" << endl;
703 void RTFDocVisitor::visitPre(DocRoot *r)
706 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRoot)}\n");
707 if (r->indent()) incIndentLevel();
708 m_t << "{" << rtf_Style["BodyText"]->reference << endl;
711 void RTFDocVisitor::visitPost(DocRoot *r)
714 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRoot)}\n");
715 if (!m_lastIsPara && !r->singleLine()) m_t << "\\par" << endl;
718 if (r->indent()) decIndentLevel();
721 void RTFDocVisitor::visitPre(DocSimpleSect *s)
724 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
725 if (!m_lastIsPara) m_t << "\\par" << endl;
726 m_t << "{"; // start desc
727 //m_t << "{\\b "; // start bold
728 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
731 case DocSimpleSect::See:
732 m_t << theTranslator->trSeeAlso(); break;
733 case DocSimpleSect::Return:
734 m_t << theTranslator->trReturns(); break;
735 case DocSimpleSect::Author:
736 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
737 case DocSimpleSect::Authors:
738 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
739 case DocSimpleSect::Version:
740 m_t << theTranslator->trVersion(); break;
741 case DocSimpleSect::Since:
742 m_t << theTranslator->trSince(); break;
743 case DocSimpleSect::Date:
744 m_t << theTranslator->trDate(); break;
745 case DocSimpleSect::Note:
746 m_t << theTranslator->trNote(); break;
747 case DocSimpleSect::Warning:
748 m_t << theTranslator->trWarning(); break;
749 case DocSimpleSect::Pre:
750 m_t << theTranslator->trPrecondition(); break;
751 case DocSimpleSect::Post:
752 m_t << theTranslator->trPostcondition(); break;
753 case DocSimpleSect::Copyright:
754 m_t << theTranslator->trCopyright(); break;
755 case DocSimpleSect::Invar:
756 m_t << theTranslator->trInvariant(); break;
757 case DocSimpleSect::Remark:
758 m_t << theTranslator->trRemarks(); break;
759 case DocSimpleSect::Attention:
760 m_t << theTranslator->trAttention(); break;
761 case DocSimpleSect::User: break;
762 case DocSimpleSect::Rcs: break;
763 case DocSimpleSect::Unknown: break;
766 // special case 1: user defined title
767 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
771 m_t << "}"; // end bold
773 m_t << rtf_Style_Reset << getStyle("DescContinue");
778 void RTFDocVisitor::visitPost(DocSimpleSect *)
781 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
782 if (!m_lastIsPara) m_t << "\\par" << endl;
784 m_t << "}"; // end desc
788 void RTFDocVisitor::visitPre(DocTitle *)
790 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocTitle)}\n");
793 void RTFDocVisitor::visitPost(DocTitle *)
796 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocTitle)}\n");
797 m_t << "\\par" << endl;
798 m_t << "}"; // end bold
800 m_t << rtf_Style_Reset << getStyle("DescContinue");
804 void RTFDocVisitor::visitPre(DocSimpleList *)
807 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
809 rtf_listItemInfo[m_indentLevel].isEnum = FALSE;
813 void RTFDocVisitor::visitPost(DocSimpleList *)
816 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
817 if (!m_lastIsPara) m_t << "\\par" << endl;
822 void RTFDocVisitor::visitPre(DocSimpleListItem *)
825 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleListItem)}\n");
826 m_t << "\\par" << rtf_Style_Reset << getStyle("ListBullet") << endl;
831 void RTFDocVisitor::visitPost(DocSimpleListItem *)
834 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleListItem)}\n");
837 void RTFDocVisitor::visitPre(DocSection *s)
840 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSection)}\n");
841 if (!m_lastIsPara) m_t << "\\par" << endl;
842 m_t << "{\\bkmkstart " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}" << endl;
843 m_t << "{\\bkmkend " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}" << endl;
844 m_t << "{{" // start section
847 int level = QMIN(s->level()+1,4);
848 heading.sprintf("Heading%d",level);
850 m_t << rtf_Style[heading]->reference << endl;
851 // make table of contents entry
853 m_t << endl << "\\par" << "}" << endl;
854 m_t << "{\\tc\\tcl" << level << " \\v ";
860 void RTFDocVisitor::visitPost(DocSection *)
863 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSection)}\n");
864 m_t << "\\par}" << endl; // end section
868 void RTFDocVisitor::visitPre(DocHtmlList *l)
871 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlList)}\n");
873 rtf_listItemInfo[m_indentLevel].isEnum = l->type()==DocHtmlList::Ordered;
874 rtf_listItemInfo[m_indentLevel].number = 1;
878 void RTFDocVisitor::visitPost(DocHtmlList *)
881 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlList)}\n");
882 m_t << "\\par" << "}" << endl;
886 void RTFDocVisitor::visitPre(DocHtmlListItem *)
889 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlListItem)}\n");
890 m_t << "\\par" << endl;
891 m_t << rtf_Style_Reset;
892 if (rtf_listItemInfo[m_indentLevel].isEnum)
894 m_t << getStyle("ListEnum") << endl;
895 m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab ";
896 rtf_listItemInfo[m_indentLevel].number++;
900 m_t << getStyle("ListBullet") << endl;
906 void RTFDocVisitor::visitPost(DocHtmlListItem *)
909 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlListItem)}\n");
912 void RTFDocVisitor::visitPre(DocHtmlDescList *)
915 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescList)}\n");
916 //m_t << "{" << endl;
917 //m_t << rtf_Style_Reset << getStyle("ListContinue");
918 //m_lastIsPara=FALSE;
921 void RTFDocVisitor::visitPost(DocHtmlDescList *)
924 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescList)}\n");
925 //m_t << "}" << endl;
926 //m_t << "\\par" << endl;
930 void RTFDocVisitor::visitPre(DocHtmlDescTitle *)
933 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescTitle)}\n");
934 //m_t << "\\par" << endl;
936 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
940 void RTFDocVisitor::visitPost(DocHtmlDescTitle *)
943 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescTitle)}\n");
944 m_t << "\\par" << endl;
949 void RTFDocVisitor::visitPre(DocHtmlDescData *)
952 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescData)}\n");
954 m_t << "{" << rtf_Style_Reset << getStyle("DescContinue");
957 void RTFDocVisitor::visitPost(DocHtmlDescData *)
960 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescData)}\n");
967 void RTFDocVisitor::visitPre(DocHtmlTable *)
970 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlTable)}\n");
971 if (!m_lastIsPara) m_t << "\\par" << endl;
975 void RTFDocVisitor::visitPost(DocHtmlTable *)
978 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlTable)}\n");
979 m_t << "\\pard\\plain" << endl;
980 m_t << "\\par" << endl;
984 void RTFDocVisitor::visitPre(DocHtmlCaption *)
986 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCaption)}\n");
989 void RTFDocVisitor::visitPost(DocHtmlCaption *)
991 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCaption)}\n");
994 void RTFDocVisitor::visitPre(DocHtmlRow *r)
997 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlRow)}\n");
998 uint i,columnWidth=r->numCells()>0 ? rtf_pageWidth/r->numCells() : 10;
999 m_t << "\\trowd \\trgaph108\\trleft-108"
1000 "\\trbrdrt\\brdrs\\brdrw10 "
1001 "\\trbrdrl\\brdrs\\brdrw10 "
1002 "\\trbrdrb\\brdrs\\brdrw10 "
1003 "\\trbrdrr\\brdrs\\brdrw10 "
1004 "\\trbrdrh\\brdrs\\brdrw10 "
1005 "\\trbrdrv\\brdrs\\brdrw10 "<< endl;
1006 for (i=0;i<r->numCells();i++)
1010 m_t << "\\clcbpat16"; // set cell shading to light grey (color 16 in the clut)
1012 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 "
1013 "\\clbrdrl\\brdrs\\brdrw10 "
1014 "\\clbrdrb\\brdrs\\brdrw10 "
1015 "\\clbrdrr \\brdrs\\brdrw10 "
1017 "\\cellx" << ((i+1)*columnWidth) << endl;
1019 m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
1023 void RTFDocVisitor::visitPost(DocHtmlRow *)
1026 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlRow)}\n");
1028 m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
1029 m_t << "{\\row }" << endl;
1033 void RTFDocVisitor::visitPre(DocHtmlCell *c)
1036 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCell)}\n");
1037 m_t << "{" << align(c);
1041 void RTFDocVisitor::visitPost(DocHtmlCell *)
1044 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCell)}\n");
1049 void RTFDocVisitor::visitPre(DocInternal *)
1052 //DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternal)}\n");
1053 //m_t << "{"; // start desc
1054 //m_t << "{\\b "; // start bold
1055 //m_t << theTranslator->trForInternalUseOnly();
1056 //m_t << "}"; // end bold
1057 //m_t << "\\par" << endl;
1059 //m_t << rtf_Style_Reset << getStyle("DescContinue");
1060 //m_lastIsPara=FALSE;
1063 void RTFDocVisitor::visitPost(DocInternal *)
1066 //DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternal)}\n");
1069 //m_t << "}"; // end desc
1070 //m_lastIsPara=TRUE;
1073 void RTFDocVisitor::visitPre(DocHRef *href)
1076 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHRef)}\n");
1077 if (Config_getBool(RTF_HYPERLINKS))
1081 "{ HYPERLINK \"" << href->url() << "\" "
1085 "{\\cs37\\ul\\cf2 ";
1095 void RTFDocVisitor::visitPost(DocHRef *)
1098 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHRef)}\n");
1099 if (Config_getBool(RTF_HYPERLINKS))
1112 void RTFDocVisitor::visitPre(DocHtmlHeader *header)
1115 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlHeader)}\n");
1116 m_t << "{" // start section
1119 int level = QMIN(header->level(),5);
1120 heading.sprintf("Heading%d",level);
1122 m_t << rtf_Style[heading]->reference;
1123 // make open table of contents entry that will be closed in visitPost method
1124 m_t << "{\\tc\\tcl" << level << " ";
1128 void RTFDocVisitor::visitPost(DocHtmlHeader *)
1131 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlHeader)}\n");
1132 // close open table of contents entry
1134 m_t << "}" << endl; // end section
1138 void RTFDocVisitor::visitPre(DocImage *img)
1140 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocImage)}\n");
1141 includePicturePreRTF(img->name(), img->type()==DocImage::Rtf, img->hasCaption(), img->isInlineImage());
1143 void RTFDocVisitor::includePicturePreRTF(const QCString name, bool isTypeRTF, bool hasCaption, bool inlineImage)
1149 m_t << "\\par" << endl;
1151 m_t << rtf_Style_Reset << endl;
1152 if (hasCaption || m_lastIsPara) m_t << "\\par" << endl;
1153 m_t << "\\pard \\qc ";
1155 m_t << "{ \\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1157 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt Image}}" << endl;
1160 m_t << "\\par" << endl;
1163 m_t << "\\pard \\qc \\b";
1164 m_t << "{Image \\field\\flddirty{\\*\\fldinst { SEQ Image \\\\*Arabic }}{\\fldrslt {\\noproof 1}} ";
1170 if (hasCaption) m_t << "{\\comment "; // to prevent caption to be shown
1173 else // other format -> skip
1180 void RTFDocVisitor::visitPost(DocImage *img)
1182 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocImage)}\n");
1183 includePicturePostRTF(img->type()==DocImage::Rtf, img->hasCaption(), img->isInlineImage());
1186 void RTFDocVisitor::includePicturePostRTF(bool isTypeRTF, bool hasCaption, bool inlineImage)
1193 if (hasCaption) m_t << " }";
1200 m_t << "\\par}" <<endl;
1214 void RTFDocVisitor::visitPre(DocDotFile *df)
1216 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDotFile)}\n");
1220 void RTFDocVisitor::visitPost(DocDotFile *df)
1222 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDotFile)}\n");
1223 includePicturePostRTF(true, df->hasCaption());
1225 void RTFDocVisitor::visitPre(DocMscFile *df)
1227 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocMscFile)}\n");
1231 void RTFDocVisitor::visitPost(DocMscFile *df)
1233 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocMscFile)}\n");
1234 includePicturePostRTF(true, df->hasCaption());
1237 void RTFDocVisitor::visitPre(DocDiaFile *df)
1239 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDiaFile)}\n");
1243 void RTFDocVisitor::visitPost(DocDiaFile *df)
1245 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDiaFile)}\n");
1246 includePicturePostRTF(true, df->hasCaption());
1249 void RTFDocVisitor::visitPre(DocLink *lnk)
1252 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocLink)}\n");
1253 startLink(lnk->ref(),lnk->file(),lnk->anchor());
1256 void RTFDocVisitor::visitPost(DocLink *lnk)
1259 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLink)}\n");
1260 endLink(lnk->ref());
1263 void RTFDocVisitor::visitPre(DocRef *ref)
1266 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRef)}\n");
1267 // when ref->isSubPage()==TRUE we use ref->file() for HTML and
1268 // ref->anchor() for LaTeX/RTF
1269 if (ref->isSubPage())
1271 startLink(ref->ref(),0,ref->anchor());
1275 if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
1277 if (!ref->hasLinkText()) filter(ref->targetTitle());
1280 void RTFDocVisitor::visitPost(DocRef *ref)
1283 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRef)}\n");
1284 if (!ref->file().isEmpty()) endLink(ref->ref());
1289 void RTFDocVisitor::visitPre(DocSecRefItem *)
1291 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefItem)}\n");
1294 void RTFDocVisitor::visitPost(DocSecRefItem *)
1296 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefItem)}\n");
1299 void RTFDocVisitor::visitPre(DocSecRefList *)
1302 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefList)}\n");
1305 m_t << rtf_Style_Reset << getStyle("LatexTOC") << endl;
1306 m_t << "\\par" << endl;
1310 void RTFDocVisitor::visitPost(DocSecRefList *)
1313 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefList)}\n");
1320 //void RTFDocVisitor::visitPre(DocLanguage *l)
1322 // DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocLanguage)}\n");
1323 // QCString langId = Config_getEnum(OUTPUT_LANGUAGE);
1324 // if (l->id().lower()!=langId.lower())
1331 //void RTFDocVisitor::visitPost(DocLanguage *l)
1333 // DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLanguage)}\n");
1334 // QCString langId = Config_getEnum(OUTPUT_LANGUAGE);
1335 // if (l->id().lower()!=langId.lower())
1341 void RTFDocVisitor::visitPre(DocParamSect *s)
1344 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamSect)}\n");
1345 m_t << "{"; // start param list
1346 if (!m_lastIsPara) m_t << "\\par" << endl;
1347 //m_t << "{\\b "; // start bold
1348 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
1351 case DocParamSect::Param:
1352 m_t << theTranslator->trParameters(); break;
1353 case DocParamSect::RetVal:
1354 m_t << theTranslator->trReturnValues(); break;
1355 case DocParamSect::Exception:
1356 m_t << theTranslator->trExceptions(); break;
1357 case DocParamSect::TemplateParam:
1358 m_t << theTranslator->trTemplateParameters(); break;
1365 bool useTable = s->type()==DocParamSect::Param ||
1366 s->type()==DocParamSect::RetVal ||
1367 s->type()==DocParamSect::Exception ||
1368 s->type()==DocParamSect::TemplateParam;
1373 m_t << rtf_Style_Reset << getStyle("DescContinue");
1377 void RTFDocVisitor::visitPost(DocParamSect *s)
1380 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamSect)}\n");
1381 //m_t << "\\par" << endl;
1382 bool useTable = s->type()==DocParamSect::Param ||
1383 s->type()==DocParamSect::RetVal ||
1384 s->type()==DocParamSect::Exception ||
1385 s->type()==DocParamSect::TemplateParam;
1393 void RTFDocVisitor::visitPre(DocParamList *pl)
1395 static int columnPos[4][5] =
1396 { { 2, 25, 100, 100, 100 }, // no inout, no type
1397 { 3, 14, 35, 100, 100 }, // inout, no type
1398 { 3, 25, 50, 100, 100 }, // no inout, type
1399 { 4, 14, 35, 55, 100 }, // inout, type
1403 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamList)}\n");
1405 DocParamSect::Type parentType = DocParamSect::Unknown;
1406 DocParamSect *sect = 0;
1407 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1409 parentType = ((DocParamSect*)pl->parent())->type();
1410 sect=(DocParamSect*)pl->parent();
1412 bool useTable = parentType==DocParamSect::Param ||
1413 parentType==DocParamSect::RetVal ||
1414 parentType==DocParamSect::Exception ||
1415 parentType==DocParamSect::TemplateParam;
1416 if (sect && sect->hasInOutSpecifier()) config+=1;
1417 if (sect && sect->hasTypeSpecifier()) config+=2;
1421 m_t << "\\trowd \\trgaph108\\trleft426\\tblind426"
1422 "\\trbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1423 "\\trbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1424 "\\trbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1425 "\\trbrdrr\\brdrs\\brdrw10\\brdrcf15 "
1426 "\\trbrdrh\\brdrs\\brdrw10\\brdrcf15 "
1427 "\\trbrdrv\\brdrs\\brdrw10\\brdrcf15 "<< endl;
1428 for (i=0;i<columnPos[config][0];i++)
1430 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1431 "\\clbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1432 "\\clbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1433 "\\clbrdrr \\brdrs\\brdrw10\\brdrcf15 "
1435 "\\cellx" << (rtf_pageWidth*columnPos[config][i+1]/100) << endl;
1437 m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
1440 if (sect && sect->hasInOutSpecifier())
1447 // Put in the direction: in/out/in,out if specified.
1448 if (pl->direction()!=DocParamSect::Unspecified)
1450 if (pl->direction()==DocParamSect::In)
1454 else if (pl->direction()==DocParamSect::Out)
1458 else if (pl->direction()==DocParamSect::InOut)
1470 if (sect && sect->hasTypeSpecifier())
1476 QListIterator<DocNode> li(pl->paramTypes());
1479 for (li.toFirst();(type=li.current());++li)
1481 if (!first) m_t << " | "; else first=FALSE;
1482 if (type->kind()==DocNode::Kind_Word)
1484 visit((DocWord*)type);
1486 else if (type->kind()==DocNode::Kind_LinkedWord)
1488 visit((DocLinkedWord*)type);
1504 //QStrListIterator li(pl->parameters());
1506 QListIterator<DocNode> li(pl->parameters());
1509 for (li.toFirst();(param=li.current());++li)
1511 if (!first) m_t << ","; else first=FALSE;
1512 if (param->kind()==DocNode::Kind_Word)
1514 visit((DocWord*)param);
1516 else if (param->kind()==DocNode::Kind_LinkedWord)
1518 visit((DocLinkedWord*)param);
1530 void RTFDocVisitor::visitPost(DocParamList *pl)
1533 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamList)}\n");
1535 DocParamSect::Type parentType = DocParamSect::Unknown;
1536 //DocParamSect *sect = 0;
1537 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1539 parentType = ((DocParamSect*)pl->parent())->type();
1540 //sect=(DocParamSect*)pl->parent();
1542 bool useTable = parentType==DocParamSect::Param ||
1543 parentType==DocParamSect::RetVal ||
1544 parentType==DocParamSect::Exception ||
1545 parentType==DocParamSect::TemplateParam;
1548 m_t << "\\cell }" << endl;
1549 //m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
1550 m_t << "{\\row }" << endl;
1554 m_t << "\\par" << endl;
1560 void RTFDocVisitor::visitPre(DocXRefItem *x)
1563 if (x->title().isEmpty()) return;
1564 bool anonymousEnum = x->file()=="@";
1565 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocXRefItem)}\n");
1568 m_t << "\\par" << endl;
1571 m_t << "{"; // start param list
1572 //m_t << "{\\b "; // start bold
1573 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
1574 if (Config_getBool(RTF_HYPERLINKS) && !anonymousEnum)
1577 if (!x->file().isEmpty())
1581 if (!x->file().isEmpty() && !x->anchor().isEmpty())
1585 if (!x->anchor().isEmpty())
1587 refName+=x->anchor();
1592 "{ HYPERLINK \\\\l \"" << refName << "\" "
1596 "{\\cs37\\ul\\cf2 ";
1608 m_t << "}"; // end bold
1610 m_t << rtf_Style_Reset << getStyle("DescContinue");
1614 void RTFDocVisitor::visitPost(DocXRefItem *x)
1617 if (x->title().isEmpty()) return;
1618 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocXRefItem)}\n");
1619 m_t << "\\par" << endl;
1621 m_t << "}" << endl; // end xref item
1625 void RTFDocVisitor::visitPre(DocInternalRef *ref)
1628 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternalRef)}\n");
1629 startLink("",ref->file(),ref->anchor());
1632 void RTFDocVisitor::visitPost(DocInternalRef *)
1635 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternalRef)}\n");
1640 void RTFDocVisitor::visitPre(DocCopy *)
1643 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCopy)}\n");
1646 void RTFDocVisitor::visitPost(DocCopy *)
1649 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocCopy)}\n");
1652 void RTFDocVisitor::visitPre(DocText *)
1655 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocText)}\n");
1658 void RTFDocVisitor::visitPost(DocText *)
1661 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocText)}\n");
1664 void RTFDocVisitor::visitPre(DocHtmlBlockQuote *)
1667 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlBlockQuote)}\n");
1668 if (!m_lastIsPara) m_t << "\\par" << endl;
1669 m_t << "{"; // start desc
1671 m_t << rtf_Style_Reset << getStyle("DescContinue");
1674 void RTFDocVisitor::visitPost(DocHtmlBlockQuote *)
1677 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlBlockQuote)}\n");
1678 if (!m_lastIsPara) m_t << "\\par" << endl;
1680 m_t << "}"; // end desc
1684 void RTFDocVisitor::visitPre(DocVhdlFlow *)
1689 void RTFDocVisitor::visitPost(DocVhdlFlow *)
1694 void RTFDocVisitor::visitPre(DocParBlock *)
1699 void RTFDocVisitor::visitPost(DocParBlock *)
1705 //static char* getMultiByte(int c)
1707 // static char s[10];
1708 // sprintf(s,"\\'%X",c);
1712 void RTFDocVisitor::filter(const char *str,bool verbatim)
1716 const unsigned char *p=(const unsigned char *)str;
1718 //unsigned char pc='\0';
1721 //static bool MultiByte = FALSE;
1726 // m_t << getMultiByte( c );
1727 // MultiByte = FALSE;
1732 // MultiByte = TRUE;
1733 // m_t << getMultiByte( c );
1739 case '{': m_t << "\\{"; break;
1740 case '}': m_t << "\\}"; break;
1741 case '\\': m_t << "\\\\"; break;
1742 case '\n': if (verbatim)
1744 m_t << "\\par" << endl;
1751 default: m_t << (char)c;
1758 void RTFDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
1760 if (ref.isEmpty() && Config_getBool(RTF_HYPERLINKS))
1763 if (!file.isEmpty())
1767 if (!file.isEmpty() && anchor)
1776 m_t << "{\\field {\\*\\fldinst { HYPERLINK \\\\l \"";
1777 m_t << rtfFormatBmkStr(refName);
1779 m_t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
1788 void RTFDocVisitor::endLink(const QCString &ref)
1790 if (ref.isEmpty() && Config_getBool(RTF_HYPERLINKS))
1801 void RTFDocVisitor::pushEnabled()
1803 m_enabled.push(new bool(m_hide));
1806 void RTFDocVisitor::popEnabled()
1808 bool *v=m_enabled.pop();
1814 void RTFDocVisitor::writeDotFile(DocDotFile *df)
1816 writeDotFile(df->file(), df->hasCaption());
1818 void RTFDocVisitor::writeDotFile(const QCString &filename, bool hasCaption)
1820 QCString baseName=filename;
1822 if ((i=baseName.findRev('/'))!=-1)
1824 baseName=baseName.right(baseName.length()-i-1);
1826 QCString outDir = Config_getString(RTF_OUTPUT);
1827 writeDotGraphFromFile(filename,outDir,baseName,GOF_BITMAP);
1828 QCString imgExt = getDotImageExtension();
1829 includePicturePreRTF(baseName + "." + imgExt, true, hasCaption);
1832 void RTFDocVisitor::writeMscFile(DocMscFile *df)
1834 writeMscFile(df->file(), df->hasCaption());
1836 void RTFDocVisitor::writeMscFile(const QCString &fileName, bool hasCaption)
1838 QCString baseName=fileName;
1840 if ((i=baseName.findRev('/'))!=-1)
1842 baseName=baseName.right(baseName.length()-i-1);
1844 QCString outDir = Config_getString(RTF_OUTPUT);
1845 writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP);
1846 includePicturePreRTF(baseName + ".png", true, hasCaption);
1849 void RTFDocVisitor::writeDiaFile(DocDiaFile *df)
1851 QCString baseName=df->file();
1853 if ((i=baseName.findRev('/'))!=-1)
1855 baseName=baseName.right(baseName.length()-i-1);
1857 QCString outDir = Config_getString(RTF_OUTPUT);
1858 writeDiaGraphFromFile(df->file(),outDir,baseName,DIA_BITMAP);
1859 includePicturePreRTF(baseName + ".png", true, df->hasCaption());
1862 void RTFDocVisitor::writePlantUMLFile(const QCString &fileName, bool hasCaption)
1864 QCString baseName=fileName;
1866 if ((i=baseName.findRev('/'))!=-1)
1868 baseName=baseName.right(baseName.length()-i-1);
1870 QCString outDir = Config_getString(RTF_OUTPUT);
1871 generatePlantUMLOutput(fileName,outDir,PUML_BITMAP);
1872 includePicturePreRTF(baseName + ".png", true, hasCaption);