1 /******************************************************************************
6 * Copyright (C) 1997-2014 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"
39 //#define DBG_RTF(x) m_t << x
40 #define DBG_RTF(x) do {} while(0)
42 static QCString align(DocHtmlCell *cell)
44 HtmlAttribList attrs = cell->attribs();
46 for (i=0; i<attrs.count(); ++i)
48 if (attrs.at(i)->name.lower()=="align")
50 if (attrs.at(i)->value.lower()=="center")
52 else if (attrs.at(i)->value.lower()=="right")
60 RTFDocVisitor::RTFDocVisitor(FTextStream &t,CodeOutputInterface &ci,
62 : DocVisitor(DocVisitor_RTF), m_t(t), m_ci(ci), m_insidePre(FALSE),
63 m_hide(FALSE), m_indentLevel(0), m_lastIsPara(FALSE), m_langExt(langExt)
67 QCString RTFDocVisitor::getStyle(const char *name)
70 n.sprintf("%s%d",name,m_indentLevel);
71 StyleData *sd = rtf_Style[n];
76 void RTFDocVisitor::incIndentLevel()
78 if (m_indentLevel<rtf_maxIndentLevels-1) m_indentLevel++;
81 void RTFDocVisitor::decIndentLevel()
83 if (m_indentLevel>0) m_indentLevel--;
86 //--------------------------------------
87 // visitor functions for leaf nodes
88 //--------------------------------------
90 void RTFDocVisitor::visit(DocWord *w)
93 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWord)}\n");
98 void RTFDocVisitor::visit(DocLinkedWord *w)
101 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLinkedWord)}\n");
102 startLink(w->ref(),w->file(),w->anchor());
108 void RTFDocVisitor::visit(DocWhiteSpace *w)
111 DBG_RTF("{\\comment RTFDocVisitor::visit(DocWhiteSpace)}\n");
123 void RTFDocVisitor::visit(DocSymbol *s)
126 DBG_RTF("{\\comment RTFDocVisitor::visit(DocSymbol)}\n");
127 const char *res = HtmlEntityMapper::instance()->rtf(s->symbol());
134 err("RTF: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
139 void RTFDocVisitor::visit(DocURL *u)
142 DBG_RTF("{\\comment RTFDocVisitor::visit(DocURL)}\n");
143 if (Config_getBool("RTF_HYPERLINKS"))
148 if (u->isEmail()) m_t << "mailto:";
169 void RTFDocVisitor::visit(DocLineBreak *)
172 DBG_RTF("{\\comment RTFDocVisitor::visit(DocLineBreak)}\n");
173 m_t << "\\par" << endl;
177 void RTFDocVisitor::visit(DocHorRuler *)
180 DBG_RTF("{\\comment RTFDocVisitor::visit(DocHorRuler)}\n");
181 m_t << "{\\pard\\widctlpar\\brdrb\\brdrs\\brdrw5\\brsp20 \\adjustright \\par}" << endl;
185 void RTFDocVisitor::visit(DocStyleChange *s)
189 DBG_RTF("{\\comment RTFDocVisitor::visit(DocStyleChange)}\n");
192 case DocStyleChange::Bold:
193 if (s->enable()) m_t << "{\\b "; else m_t << "} ";
195 case DocStyleChange::Italic:
196 if (s->enable()) m_t << "{\\i "; else m_t << "} ";
198 case DocStyleChange::Code:
199 if (s->enable()) m_t << "{\\f2 "; else m_t << "} ";
201 case DocStyleChange::Subscript:
202 if (s->enable()) m_t << "{\\sub "; else m_t << "} ";
204 case DocStyleChange::Superscript:
205 if (s->enable()) m_t << "{\\super "; else m_t << "} ";
207 case DocStyleChange::Center:
208 if (s->enable()) m_t << "{\\qc "; else m_t << "} ";
210 case DocStyleChange::Small:
211 if (s->enable()) m_t << "{\\sub "; else m_t << "} ";
213 case DocStyleChange::Preformatted:
217 m_t << "\\par" << endl;
218 m_t << rtf_Style_Reset << getStyle("CodeExample");
229 case DocStyleChange::Div: /* HTML only */ break;
230 case DocStyleChange::Span: /* HTML only */ break;
234 void RTFDocVisitor::visit(DocVerbatim *s)
237 DBG_RTF("{\\comment RTFDocVisitor::visit(DocVerbatim)}\n");
238 QCString lang = m_langExt;
239 if (!s->language().isEmpty()) // explicit language setting
241 lang = s->language();
243 SrcLangExt langExt = getLanguageFromFileName(lang);
246 case DocVerbatim::Code: // fall though
248 m_t << "\\par" << endl;
249 m_t << rtf_Style_Reset << getStyle("CodeExample");
250 Doxygen::parserManager->getParser(lang)
251 ->parseCode(m_ci,s->context(),s->text(),langExt,
252 s->isExample(),s->exampleFile());
253 //m_t << "\\par" << endl;
256 case DocVerbatim::Verbatim:
258 m_t << "\\par" << endl;
259 m_t << rtf_Style_Reset << getStyle("CodeExample");
260 filter(s->text(),TRUE);
261 //m_t << "\\par" << endl;
264 case DocVerbatim::RtfOnly:
267 case DocVerbatim::HtmlOnly:
268 case DocVerbatim::LatexOnly:
269 case DocVerbatim::XmlOnly:
270 case DocVerbatim::ManOnly:
271 case DocVerbatim::DocbookOnly:
274 case DocVerbatim::Dot:
276 static int dotindex = 1;
277 QCString fileName(4096);
279 fileName.sprintf("%s%d%s",
280 (Config_getString("RTF_OUTPUT")+"/inline_dotgraph_").data(),
284 QFile file(fileName);
285 if (!file.open(IO_WriteOnly))
287 err("Could not open file %s for writing\n",fileName.data());
289 file.writeBlock( s->text(), s->text().length() );
291 m_t << "\\par{\\qc "; // center picture
292 writeDotFile(fileName);
294 if (Config_getBool("DOT_CLEANUP")) file.remove();
297 case DocVerbatim::Msc:
299 static int mscindex = 1;
300 QCString baseName(4096);
302 baseName.sprintf("%s%d",
303 (Config_getString("RTF_OUTPUT")+"/inline_mscgraph_").data(),
306 QFile file(baseName+".msc");
307 if (!file.open(IO_WriteOnly))
309 err("Could not open file %s for writing\n",baseName.data());
311 QCString text = "msc {";
314 file.writeBlock( text, text.length() );
316 m_t << "\\par{\\qc "; // center picture
317 writeMscFile(baseName);
319 if (Config_getBool("DOT_CLEANUP")) file.remove();
322 case DocVerbatim::PlantUML:
324 static QCString rtfOutput = Config_getString("RTF_OUTPUT");
325 QCString baseName = writePlantUMLSource(rtfOutput,s->exampleFile(),s->text());
327 m_t << "\\par{\\qc "; // center picture
328 writePlantUMLFile(baseName);
336 void RTFDocVisitor::visit(DocAnchor *anc)
339 DBG_RTF("{\\comment RTFDocVisitor::visit(DocAnchor)}\n");
341 if (!anc->file().isEmpty())
345 if (!anc->file().isEmpty() && !anc->anchor().isEmpty())
349 if (!anc->anchor().isEmpty())
351 anchor+=anc->anchor();
353 m_t << "{\\bkmkstart " << rtfFormatBmkStr(anchor) << "}" << endl;
354 m_t << "{\\bkmkend " << rtfFormatBmkStr(anchor) << "}" << endl;
358 void RTFDocVisitor::visit(DocInclude *inc)
361 SrcLangExt langExt = getLanguageFromFileName(inc->extension());
362 DBG_RTF("{\\comment RTFDocVisitor::visit(DocInclude)}\n");
365 case DocInclude::IncWithLines:
368 m_t << "\\par" << endl;
369 m_t << rtf_Style_Reset << getStyle("CodeExample");
370 QFileInfo cfi( inc->file() );
371 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
372 Doxygen::parserManager->getParser(inc->extension())
373 ->parseCode(m_ci,inc->context(),
377 inc->exampleFile(), &fd);
382 case DocInclude::Include:
384 m_t << "\\par" << endl;
385 m_t << rtf_Style_Reset << getStyle("CodeExample");
386 Doxygen::parserManager->getParser(inc->extension())
387 ->parseCode(m_ci,inc->context(),
388 inc->text(),langExt,inc->isExample(),
393 case DocInclude::DontInclude:
395 case DocInclude::HtmlInclude:
397 case DocInclude::LatexInclude:
399 case DocInclude::VerbInclude:
401 m_t << "\\par" << endl;
402 m_t << rtf_Style_Reset << getStyle("CodeExample");
407 case DocInclude::Snippet:
409 if (!m_lastIsPara) m_t << "\\par" << endl;
410 m_t << rtf_Style_Reset << getStyle("CodeExample");
411 Doxygen::parserManager->getParser(inc->extension())
414 extractBlock(inc->text(),inc->blockId()),
425 void RTFDocVisitor::visit(DocIncOperator *op)
427 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
428 // op->type(),op->isFirst(),op->isLast(),op->text().data());
429 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIncOperator)}\n");
430 SrcLangExt langExt = getLanguageFromFileName(m_langExt);
436 m_t << "\\par" << endl;
437 m_t << rtf_Style_Reset << getStyle("CodeExample");
442 if (op->type()!=DocIncOperator::Skip)
447 Doxygen::parserManager->getParser(m_langExt)
448 ->parseCode(m_ci,op->context(),op->text(),langExt,
449 op->isExample(),op->exampleFile());
466 if (!m_hide) m_t << endl;
471 void RTFDocVisitor::visit(DocFormula *f)
474 // TODO: do something sensible here, like including a bitmap
475 DBG_RTF("{\\comment RTFDocVisitor::visit(DocFormula)}\n");
480 void RTFDocVisitor::visit(DocIndexEntry *i)
483 DBG_RTF("{\\comment RTFDocVisitor::visit(DocIndexEntry)}\n");
484 m_t << "{\\xe \\v " << i->entry() << "}" << endl;
488 void RTFDocVisitor::visit(DocSimpleSectSep *)
492 void RTFDocVisitor::visit(DocCite *cite)
495 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCite)}\n");
496 if (!cite->file().isEmpty())
498 startLink(cite->ref(),cite->file(),cite->anchor());
504 filter(cite->text());
505 if (!cite->file().isEmpty())
507 endLink(cite->ref());
516 //--------------------------------------
517 // visitor functions for compound nodes
518 //--------------------------------------
520 void RTFDocVisitor::visitPre(DocAutoList *l)
523 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoList)}\n");
525 rtf_listItemInfo[m_indentLevel].isEnum = l->isEnumList();
526 rtf_listItemInfo[m_indentLevel].number = 1;
530 void RTFDocVisitor::visitPost(DocAutoList *)
533 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoList)}\n");
539 void RTFDocVisitor::visitPre(DocAutoListItem *)
542 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocAutoListItem)}\n");
543 if (!m_lastIsPara) m_t << "\\par" << endl;
544 m_t << rtf_Style_Reset;
545 if (rtf_listItemInfo[m_indentLevel].isEnum)
547 m_t << getStyle("ListEnum") << endl;
548 m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab ";
549 rtf_listItemInfo[m_indentLevel].number++;
553 m_t << getStyle("ListBullet") << endl;
559 void RTFDocVisitor::visitPost(DocAutoListItem *)
562 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocAutoListItem)}\n");
565 void RTFDocVisitor::visitPre(DocPara *)
567 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
570 void RTFDocVisitor::visitPost(DocPara *p)
573 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocPara)}\n");
575 !p->isLast() && // omit <p> for last paragraph
576 !(p->parent() && // and for parameters & sections
577 p->parent()->kind()==DocNode::Kind_ParamSect
581 m_t << "\\par" << endl;
586 void RTFDocVisitor::visitPre(DocRoot *r)
589 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRoot)}\n");
590 if (r->indent()) incIndentLevel();
591 m_t << "{" << rtf_Style["BodyText"]->reference << endl;
594 void RTFDocVisitor::visitPost(DocRoot *r)
597 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRoot)}\n");
598 if (!m_lastIsPara && !r->singleLine()) m_t << "\\par" << endl;
601 if (r->indent()) decIndentLevel();
604 void RTFDocVisitor::visitPre(DocSimpleSect *s)
607 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
608 if (!m_lastIsPara) m_t << "\\par" << endl;
609 m_t << "{"; // start desc
610 //m_t << "{\\b "; // start bold
611 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
614 case DocSimpleSect::See:
615 m_t << theTranslator->trSeeAlso(); break;
616 case DocSimpleSect::Return:
617 m_t << theTranslator->trReturns(); break;
618 case DocSimpleSect::Author:
619 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
620 case DocSimpleSect::Authors:
621 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
622 case DocSimpleSect::Version:
623 m_t << theTranslator->trVersion(); break;
624 case DocSimpleSect::Since:
625 m_t << theTranslator->trSince(); break;
626 case DocSimpleSect::Date:
627 m_t << theTranslator->trDate(); break;
628 case DocSimpleSect::Note:
629 m_t << theTranslator->trNote(); break;
630 case DocSimpleSect::Warning:
631 m_t << theTranslator->trWarning(); break;
632 case DocSimpleSect::Pre:
633 m_t << theTranslator->trPrecondition(); break;
634 case DocSimpleSect::Post:
635 m_t << theTranslator->trPostcondition(); break;
636 case DocSimpleSect::Copyright:
637 m_t << theTranslator->trCopyright(); break;
638 case DocSimpleSect::Invar:
639 m_t << theTranslator->trInvariant(); break;
640 case DocSimpleSect::Remark:
641 m_t << theTranslator->trRemarks(); break;
642 case DocSimpleSect::Attention:
643 m_t << theTranslator->trAttention(); break;
644 case DocSimpleSect::User: break;
645 case DocSimpleSect::Rcs: break;
646 case DocSimpleSect::Unknown: break;
649 // special case 1: user defined title
650 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
654 m_t << "}"; // end bold
656 m_t << rtf_Style_Reset << getStyle("DescContinue");
661 void RTFDocVisitor::visitPost(DocSimpleSect *)
664 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
665 if (!m_lastIsPara) m_t << "\\par" << endl;
667 m_t << "}"; // end desc
671 void RTFDocVisitor::visitPre(DocTitle *)
673 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocTitle)}\n");
676 void RTFDocVisitor::visitPost(DocTitle *)
679 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocTitle)}\n");
680 m_t << "\\par" << endl;
681 m_t << "}"; // end bold
683 m_t << rtf_Style_Reset << getStyle("DescContinue");
687 void RTFDocVisitor::visitPre(DocSimpleList *)
690 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleSect)}\n");
692 rtf_listItemInfo[m_indentLevel].isEnum = FALSE;
696 void RTFDocVisitor::visitPost(DocSimpleList *)
699 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleSect)}\n");
700 if (!m_lastIsPara) m_t << "\\par" << endl;
705 void RTFDocVisitor::visitPre(DocSimpleListItem *)
708 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSimpleListItem)}\n");
709 m_t << "\\par" << rtf_Style_Reset << getStyle("ListBullet") << endl;
714 void RTFDocVisitor::visitPost(DocSimpleListItem *)
717 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSimpleListItem)}\n");
720 void RTFDocVisitor::visitPre(DocSection *s)
723 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSection)}\n");
724 if (!m_lastIsPara) m_t << "\\par" << endl;
725 m_t << "{\\bkmkstart " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}" << endl;
726 m_t << "{\\bkmkend " << rtfFormatBmkStr(s->file()+"_"+s->anchor()) << "}" << endl;
727 m_t << "{{" // start section
730 int level = QMIN(s->level()+1,4);
731 heading.sprintf("Heading%d",level);
733 m_t << rtf_Style[heading]->reference << endl;
734 // make table of contents entry
736 m_t << endl << "\\par" << "}" << endl;
737 m_t << "{\\tc\\tcl" << level << " \\v ";
743 void RTFDocVisitor::visitPost(DocSection *)
746 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSection)}\n");
747 m_t << "\\par}" << endl; // end section
751 void RTFDocVisitor::visitPre(DocHtmlList *l)
754 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlList)}\n");
756 rtf_listItemInfo[m_indentLevel].isEnum = l->type()==DocHtmlList::Ordered;
757 rtf_listItemInfo[m_indentLevel].number = 1;
761 void RTFDocVisitor::visitPost(DocHtmlList *)
764 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlList)}\n");
765 m_t << "\\par" << "}" << endl;
769 void RTFDocVisitor::visitPre(DocHtmlListItem *)
772 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlListItem)}\n");
773 m_t << "\\par" << endl;
774 m_t << rtf_Style_Reset;
775 if (rtf_listItemInfo[m_indentLevel].isEnum)
777 m_t << getStyle("ListEnum") << endl;
778 m_t << rtf_listItemInfo[m_indentLevel].number << ".\\tab ";
779 rtf_listItemInfo[m_indentLevel].number++;
783 m_t << getStyle("ListBullet") << endl;
789 void RTFDocVisitor::visitPost(DocHtmlListItem *)
792 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlListItem)}\n");
795 void RTFDocVisitor::visitPre(DocHtmlDescList *)
798 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescList)}\n");
799 //m_t << "{" << endl;
800 //m_t << rtf_Style_Reset << getStyle("ListContinue");
801 //m_lastIsPara=FALSE;
804 void RTFDocVisitor::visitPost(DocHtmlDescList *)
807 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescList)}\n");
808 //m_t << "}" << endl;
809 //m_t << "\\par" << endl;
813 void RTFDocVisitor::visitPre(DocHtmlDescTitle *)
816 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescTitle)}\n");
817 //m_t << "\\par" << endl;
819 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
823 void RTFDocVisitor::visitPost(DocHtmlDescTitle *)
826 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescTitle)}\n");
827 m_t << "\\par" << endl;
832 void RTFDocVisitor::visitPre(DocHtmlDescData *)
835 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlDescData)}\n");
837 m_t << "{" << rtf_Style_Reset << getStyle("DescContinue");
840 void RTFDocVisitor::visitPost(DocHtmlDescData *)
843 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlDescData)}\n");
850 void RTFDocVisitor::visitPre(DocHtmlTable *)
853 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlTable)}\n");
854 if (!m_lastIsPara) m_t << "\\par" << endl;
858 void RTFDocVisitor::visitPost(DocHtmlTable *)
861 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlTable)}\n");
862 m_t << "\\pard\\plain" << endl;
863 m_t << "\\par" << endl;
867 void RTFDocVisitor::visitPre(DocHtmlCaption *)
869 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCaption)}\n");
872 void RTFDocVisitor::visitPost(DocHtmlCaption *)
874 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCaption)}\n");
877 void RTFDocVisitor::visitPre(DocHtmlRow *r)
880 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlRow)}\n");
881 uint i,columnWidth=r->numCells()>0 ? rtf_pageWidth/r->numCells() : 10;
882 m_t << "\\trowd \\trgaph108\\trleft-108"
883 "\\trbrdrt\\brdrs\\brdrw10 "
884 "\\trbrdrl\\brdrs\\brdrw10 "
885 "\\trbrdrb\\brdrs\\brdrw10 "
886 "\\trbrdrr\\brdrs\\brdrw10 "
887 "\\trbrdrh\\brdrs\\brdrw10 "
888 "\\trbrdrv\\brdrs\\brdrw10 "<< endl;
889 for (i=0;i<r->numCells();i++)
893 m_t << "\\clcbpat16"; // set cell shading to light grey (color 16 in the clut)
895 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10 "
896 "\\clbrdrl\\brdrs\\brdrw10 "
897 "\\clbrdrb\\brdrs\\brdrw10 "
898 "\\clbrdrr \\brdrs\\brdrw10 "
900 "\\cellx" << ((i+1)*columnWidth) << endl;
902 m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
906 void RTFDocVisitor::visitPost(DocHtmlRow *)
909 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlRow)}\n");
911 m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
912 m_t << "{\\row }" << endl;
916 void RTFDocVisitor::visitPre(DocHtmlCell *c)
919 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlCell)}\n");
920 m_t << "{" << align(c);
924 void RTFDocVisitor::visitPost(DocHtmlCell *)
927 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlCell)}\n");
932 void RTFDocVisitor::visitPre(DocInternal *)
935 //DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternal)}\n");
936 //m_t << "{"; // start desc
937 //m_t << "{\\b "; // start bold
938 //m_t << theTranslator->trForInternalUseOnly();
939 //m_t << "}"; // end bold
940 //m_t << "\\par" << endl;
942 //m_t << rtf_Style_Reset << getStyle("DescContinue");
943 //m_lastIsPara=FALSE;
946 void RTFDocVisitor::visitPost(DocInternal *)
949 //DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternal)}\n");
952 //m_t << "}"; // end desc
956 void RTFDocVisitor::visitPre(DocHRef *href)
959 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHRef)}\n");
960 if (Config_getBool("RTF_HYPERLINKS"))
964 "{ HYPERLINK \"" << href->url() << "\" "
978 void RTFDocVisitor::visitPost(DocHRef *)
981 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHRef)}\n");
982 if (Config_getBool("RTF_HYPERLINKS"))
995 void RTFDocVisitor::visitPre(DocHtmlHeader *header)
998 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlHeader)}\n");
999 m_t << "{" // start section
1002 int level = QMIN(header->level()+2,4);
1003 heading.sprintf("Heading%d",level);
1005 m_t << rtf_Style[heading]->reference;
1006 // make table of contents entry
1007 m_t << "{\\tc\\tcl \\v " << level << "}";
1012 void RTFDocVisitor::visitPost(DocHtmlHeader *)
1015 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlHeader)}\n");
1017 m_t << "}" << endl; // end section
1021 void RTFDocVisitor::visitPre(DocImage *img)
1023 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocImage)}\n");
1024 if (img->type()==DocImage::Rtf)
1026 m_t << "\\par" << endl;
1028 m_t << rtf_Style_Reset << endl;
1029 m_t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1031 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
1035 else // other format -> skip
1038 // hide caption since it is not supported at the moment
1043 void RTFDocVisitor::visitPost(DocImage *)
1045 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocImage)}\n");
1049 void RTFDocVisitor::visitPre(DocDotFile *df)
1051 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDotFile)}\n");
1052 writeDotFile(df->file());
1054 // hide caption since it is not supported at the moment
1059 void RTFDocVisitor::visitPost(DocDotFile *)
1061 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDotFile)}\n");
1064 void RTFDocVisitor::visitPre(DocMscFile *df)
1066 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocMscFile)}\n");
1067 writeMscFile(df->file());
1069 // hide caption since it is not supported at the moment
1074 void RTFDocVisitor::visitPost(DocMscFile *)
1076 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocMscFile)}\n");
1080 void RTFDocVisitor::visitPre(DocDiaFile *df)
1082 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocDiaFile)}\n");
1083 writeDiaFile(df->file());
1085 // hide caption since it is not supported at the moment
1090 void RTFDocVisitor::visitPost(DocDiaFile *)
1092 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocDiaFile)}\n");
1096 void RTFDocVisitor::visitPre(DocLink *lnk)
1099 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocLink)}\n");
1100 startLink(lnk->ref(),lnk->file(),lnk->anchor());
1103 void RTFDocVisitor::visitPost(DocLink *lnk)
1106 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLink)}\n");
1107 endLink(lnk->ref());
1110 void RTFDocVisitor::visitPre(DocRef *ref)
1113 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocRef)}\n");
1114 // when ref->isSubPage()==TRUE we use ref->file() for HTML and
1115 // ref->anchor() for LaTeX/RTF
1116 if (ref->isSubPage())
1118 startLink(ref->ref(),0,ref->anchor());
1122 if (!ref->file().isEmpty()) startLink(ref->ref(),ref->file(),ref->anchor());
1124 if (!ref->hasLinkText()) filter(ref->targetTitle());
1127 void RTFDocVisitor::visitPost(DocRef *ref)
1130 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocRef)}\n");
1131 if (!ref->file().isEmpty()) endLink(ref->ref());
1136 void RTFDocVisitor::visitPre(DocSecRefItem *)
1138 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefItem)}\n");
1141 void RTFDocVisitor::visitPost(DocSecRefItem *)
1143 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefItem)}\n");
1146 void RTFDocVisitor::visitPre(DocSecRefList *)
1149 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocSecRefList)}\n");
1152 m_t << rtf_Style_Reset << getStyle("LatexTOC") << endl;
1153 m_t << "\\par" << endl;
1157 void RTFDocVisitor::visitPost(DocSecRefList *)
1160 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocSecRefList)}\n");
1167 //void RTFDocVisitor::visitPre(DocLanguage *l)
1169 // DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocLanguage)}\n");
1170 // QCString langId = Config_getEnum("OUTPUT_LANGUAGE");
1171 // if (l->id().lower()!=langId.lower())
1178 //void RTFDocVisitor::visitPost(DocLanguage *l)
1180 // DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocLanguage)}\n");
1181 // QCString langId = Config_getEnum("OUTPUT_LANGUAGE");
1182 // if (l->id().lower()!=langId.lower())
1188 void RTFDocVisitor::visitPre(DocParamSect *s)
1191 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamSect)}\n");
1192 m_t << "{"; // start param list
1193 if (!m_lastIsPara) m_t << "\\par" << endl;
1194 //m_t << "{\\b "; // start bold
1195 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
1198 case DocParamSect::Param:
1199 m_t << theTranslator->trParameters(); break;
1200 case DocParamSect::RetVal:
1201 m_t << theTranslator->trReturnValues(); break;
1202 case DocParamSect::Exception:
1203 m_t << theTranslator->trExceptions(); break;
1204 case DocParamSect::TemplateParam:
1206 m_t << theTranslator->trTemplateParam(); break;
1208 m_t << "Template Parameters"; break;
1215 bool useTable = s->type()==DocParamSect::Param ||
1216 s->type()==DocParamSect::RetVal ||
1217 s->type()==DocParamSect::Exception ||
1218 s->type()==DocParamSect::TemplateParam;
1223 m_t << rtf_Style_Reset << getStyle("DescContinue");
1227 void RTFDocVisitor::visitPost(DocParamSect *s)
1230 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamSect)}\n");
1231 //m_t << "\\par" << endl;
1232 bool useTable = s->type()==DocParamSect::Param ||
1233 s->type()==DocParamSect::RetVal ||
1234 s->type()==DocParamSect::Exception ||
1235 s->type()==DocParamSect::TemplateParam;
1243 void RTFDocVisitor::visitPre(DocParamList *pl)
1245 static int columnPos[4][5] =
1246 { { 2, 25, 100, 100, 100 }, // no inout, no type
1247 { 3, 14, 35, 100, 100 }, // inout, no type
1248 { 3, 25, 50, 100, 100 }, // no inout, type
1249 { 4, 14, 35, 55, 100 }, // inout, type
1253 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocParamList)}\n");
1255 DocParamSect::Type parentType = DocParamSect::Unknown;
1256 DocParamSect *sect = 0;
1257 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1259 parentType = ((DocParamSect*)pl->parent())->type();
1260 sect=(DocParamSect*)pl->parent();
1262 bool useTable = parentType==DocParamSect::Param ||
1263 parentType==DocParamSect::RetVal ||
1264 parentType==DocParamSect::Exception ||
1265 parentType==DocParamSect::TemplateParam;
1266 if (sect && sect->hasInOutSpecifier()) config+=1;
1267 if (sect && sect->hasTypeSpecifier()) config+=2;
1271 m_t << "\\trowd \\trgaph108\\trleft426\\tblind426"
1272 "\\trbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1273 "\\trbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1274 "\\trbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1275 "\\trbrdrr\\brdrs\\brdrw10\\brdrcf15 "
1276 "\\trbrdrh\\brdrs\\brdrw10\\brdrcf15 "
1277 "\\trbrdrv\\brdrs\\brdrw10\\brdrcf15 "<< endl;
1278 for (i=0;i<columnPos[config][0];i++)
1280 m_t << "\\clvertalt\\clbrdrt\\brdrs\\brdrw10\\brdrcf15 "
1281 "\\clbrdrl\\brdrs\\brdrw10\\brdrcf15 "
1282 "\\clbrdrb\\brdrs\\brdrw10\\brdrcf15 "
1283 "\\clbrdrr \\brdrs\\brdrw10\\brdrcf15 "
1285 "\\cellx" << (rtf_pageWidth*columnPos[config][i+1]/100) << endl;
1287 m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
1290 if (sect && sect->hasInOutSpecifier())
1297 // Put in the direction: in/out/in,out if specified.
1298 if (pl->direction()!=DocParamSect::Unspecified)
1300 if (pl->direction()==DocParamSect::In)
1304 else if (pl->direction()==DocParamSect::Out)
1308 else if (pl->direction()==DocParamSect::InOut)
1320 if (sect && sect->hasTypeSpecifier())
1326 QListIterator<DocNode> li(pl->paramTypes());
1329 for (li.toFirst();(type=li.current());++li)
1331 if (!first) m_t << " | "; else first=FALSE;
1332 if (type->kind()==DocNode::Kind_Word)
1334 visit((DocWord*)type);
1336 else if (type->kind()==DocNode::Kind_LinkedWord)
1338 visit((DocLinkedWord*)type);
1354 //QStrListIterator li(pl->parameters());
1356 QListIterator<DocNode> li(pl->parameters());
1359 for (li.toFirst();(param=li.current());++li)
1361 if (!first) m_t << ","; else first=FALSE;
1362 if (param->kind()==DocNode::Kind_Word)
1364 visit((DocWord*)param);
1366 else if (param->kind()==DocNode::Kind_LinkedWord)
1368 visit((DocLinkedWord*)param);
1380 void RTFDocVisitor::visitPost(DocParamList *pl)
1383 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocParamList)}\n");
1385 DocParamSect::Type parentType = DocParamSect::Unknown;
1386 //DocParamSect *sect = 0;
1387 if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect)
1389 parentType = ((DocParamSect*)pl->parent())->type();
1390 //sect=(DocParamSect*)pl->parent();
1392 bool useTable = parentType==DocParamSect::Param ||
1393 parentType==DocParamSect::RetVal ||
1394 parentType==DocParamSect::Exception ||
1395 parentType==DocParamSect::TemplateParam;
1398 m_t << "\\cell }" << endl;
1399 //m_t << "\\pard \\widctlpar\\intbl\\adjustright" << endl;
1400 m_t << "{\\row }" << endl;
1404 m_t << "\\par" << endl;
1410 void RTFDocVisitor::visitPre(DocXRefItem *x)
1413 if (x->title().isEmpty()) return;
1414 bool anonymousEnum = x->file()=="@";
1415 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocXRefItem)}\n");
1416 m_t << "{"; // start param list
1417 //m_t << "{\\b "; // start bold
1418 m_t << "{" << rtf_Style["Heading5"]->reference << endl;
1419 if (Config_getBool("RTF_HYPERLINKS") && !anonymousEnum)
1422 if (!x->file().isEmpty())
1426 if (!x->file().isEmpty() && !x->anchor().isEmpty())
1430 if (!x->anchor().isEmpty())
1432 refName+=x->anchor();
1437 "{ HYPERLINK \\\\l \"" << refName << "\" "
1441 "{\\cs37\\ul\\cf2 ";
1453 m_t << "}"; // end bold
1455 m_t << rtf_Style_Reset << getStyle("DescContinue");
1459 void RTFDocVisitor::visitPost(DocXRefItem *x)
1462 if (x->title().isEmpty()) return;
1463 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocXRefItem)}\n");
1464 m_t << "\\par" << endl;
1466 m_t << "}" << endl; // end xref item
1470 void RTFDocVisitor::visitPre(DocInternalRef *ref)
1473 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocInternalRef)}\n");
1474 startLink("",ref->file(),ref->anchor());
1477 void RTFDocVisitor::visitPost(DocInternalRef *)
1480 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocInternalRef)}\n");
1485 void RTFDocVisitor::visitPre(DocCopy *)
1488 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCopy)}\n");
1491 void RTFDocVisitor::visitPost(DocCopy *)
1494 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocCopy)}\n");
1497 void RTFDocVisitor::visitPre(DocText *)
1500 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocText)}\n");
1503 void RTFDocVisitor::visitPost(DocText *)
1506 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocText)}\n");
1509 void RTFDocVisitor::visitPre(DocHtmlBlockQuote *)
1512 DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocHtmlBlockQuote)}\n");
1513 if (!m_lastIsPara) m_t << "\\par" << endl;
1514 m_t << "{"; // start desc
1516 m_t << rtf_Style_Reset << getStyle("DescContinue");
1519 void RTFDocVisitor::visitPost(DocHtmlBlockQuote *)
1522 DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocHtmlBlockQuote)}\n");
1523 if (!m_lastIsPara) m_t << "\\par" << endl;
1525 m_t << "}"; // end desc
1529 void RTFDocVisitor::visitPre(DocVhdlFlow *)
1534 void RTFDocVisitor::visitPost(DocVhdlFlow *)
1539 void RTFDocVisitor::visitPre(DocParBlock *)
1544 void RTFDocVisitor::visitPost(DocParBlock *)
1550 //static char* getMultiByte(int c)
1552 // static char s[10];
1553 // sprintf(s,"\\'%X",c);
1557 void RTFDocVisitor::filter(const char *str,bool verbatim)
1561 const unsigned char *p=(const unsigned char *)str;
1563 //unsigned char pc='\0';
1566 //static bool MultiByte = FALSE;
1571 // m_t << getMultiByte( c );
1572 // MultiByte = FALSE;
1577 // MultiByte = TRUE;
1578 // m_t << getMultiByte( c );
1584 case '{': m_t << "\\{"; break;
1585 case '}': m_t << "\\}"; break;
1586 case '\\': m_t << "\\\\"; break;
1587 case '\n': if (verbatim)
1589 m_t << "\\par" << endl;
1596 default: m_t << (char)c;
1603 void RTFDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
1605 if (ref.isEmpty() && Config_getBool("RTF_HYPERLINKS"))
1608 if (!file.isEmpty())
1612 if (!file.isEmpty() && anchor)
1621 m_t << "{\\field {\\*\\fldinst { HYPERLINK \\\\l \"";
1622 m_t << rtfFormatBmkStr(refName);
1624 m_t << "}{\\fldrslt {\\cs37\\ul\\cf2 ";
1633 void RTFDocVisitor::endLink(const QCString &ref)
1635 if (ref.isEmpty() && Config_getBool("RTF_HYPERLINKS"))
1646 void RTFDocVisitor::pushEnabled()
1648 m_enabled.push(new bool(m_hide));
1651 void RTFDocVisitor::popEnabled()
1653 bool *v=m_enabled.pop();
1659 void RTFDocVisitor::writeDotFile(const QCString &fileName)
1661 QCString baseName=fileName;
1663 if ((i=baseName.findRev('/'))!=-1)
1665 baseName=baseName.right(baseName.length()-i-1);
1667 QCString outDir = Config_getString("RTF_OUTPUT");
1668 writeDotGraphFromFile(fileName,outDir,baseName,GOF_BITMAP);
1669 if (!m_lastIsPara) m_t << "\\par" << endl;
1671 m_t << rtf_Style_Reset;
1672 m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1673 m_t << baseName << "." << Config_getEnum("DOT_IMAGE_FORMAT");
1674 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
1679 void RTFDocVisitor::writeMscFile(const QCString &fileName)
1681 QCString baseName=fileName;
1683 if ((i=baseName.findRev('/'))!=-1)
1685 baseName=baseName.right(baseName.length()-i-1);
1687 QCString outDir = Config_getString("RTF_OUTPUT");
1688 writeMscGraphFromFile(fileName+".msc",outDir,baseName,MSC_BITMAP);
1689 if (!m_lastIsPara) m_t << "\\par" << endl;
1691 m_t << rtf_Style_Reset;
1692 m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1693 m_t << baseName << ".png";
1694 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
1699 void RTFDocVisitor::writeDiaFile(const QCString &fileName)
1701 QCString baseName=fileName;
1703 if ((i=baseName.findRev('/'))!=-1)
1705 baseName=baseName.right(baseName.length()-i-1);
1707 QCString outDir = Config_getString("RTF_OUTPUT");
1708 writeDiaGraphFromFile(fileName+".dia",outDir,baseName,DIA_BITMAP);
1709 if (!m_lastIsPara) m_t << "\\par" << endl;
1711 m_t << rtf_Style_Reset;
1712 m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1713 m_t << baseName << ".png";
1714 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
1719 void RTFDocVisitor::writePlantUMLFile(const QCString &fileName)
1721 QCString baseName=fileName;
1723 if ((i=baseName.findRev('/'))!=-1)
1725 baseName=baseName.right(baseName.length()-i-1);
1727 QCString outDir = Config_getString("RTF_OUTPUT");
1728 generatePlantUMLOutput(fileName,outDir,PUML_BITMAP);
1729 if (!m_lastIsPara) m_t << "\\par" << endl;
1731 m_t << rtf_Style_Reset;
1732 m_t << "\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE \"";
1733 m_t << baseName << ".png";
1734 m_t << "\" \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;