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 "mandocvisitor.h"
22 #include "docparser.h"
25 #include "outputgen.h"
30 #include "parserintf.h"
32 #include "htmlentity.h"
35 ManDocVisitor::ManDocVisitor(FTextStream &t,CodeOutputInterface &ci,
37 : DocVisitor(DocVisitor_Man), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_firstCol(FALSE),
38 m_indent(0), m_langExt(langExt)
42 //--------------------------------------
43 // visitor functions for leaf nodes
44 //--------------------------------------
46 void ManDocVisitor::visit(DocWord *w)
53 void ManDocVisitor::visit(DocLinkedWord *w)
62 void ManDocVisitor::visit(DocWhiteSpace *w)
68 m_firstCol=w->chars().at(w->chars().length()-1)=='\n';
77 void ManDocVisitor::visit(DocSymbol *s)
80 const char *res = HtmlEntityMapper::instance()->man(s->symbol());
87 // no error or warning to be supplied
88 // err("man: non supported HTML-entity found: &%s;\n",get_symbol_item(s->symbol()));
93 void ManDocVisitor::visit(DocEmoji *s)
96 const char *res = EmojiEntityMapper::instance()->name(s->index());
108 void ManDocVisitor::visit(DocURL *u)
115 void ManDocVisitor::visit(DocLineBreak *)
118 m_t << endl << ".br" << endl;
122 void ManDocVisitor::visit(DocHorRuler *)
125 if (!m_firstCol) m_t << endl;
126 m_t << ".PP" << endl;
130 void ManDocVisitor::visit(DocStyleChange *s)
135 case DocStyleChange::Bold:
136 if (s->enable()) m_t << "\\fB"; else m_t << "\\fP";
139 case DocStyleChange::Strike:
142 case DocStyleChange::Underline: //underline is shown as emphasis
143 if (s->enable()) m_t << "\\fI"; else m_t << "\\fP";
146 case DocStyleChange::Italic:
147 if (s->enable()) m_t << "\\fI"; else m_t << "\\fP";
150 case DocStyleChange::Code:
151 if (s->enable()) m_t << "\\fC"; else m_t << "\\fP";
154 case DocStyleChange::Subscript:
155 if (s->enable()) m_t << "\\*<"; else m_t << "\\*> ";
158 case DocStyleChange::Superscript:
159 if (s->enable()) m_t << "\\*{"; else m_t << "\\*} ";
162 case DocStyleChange::Center:
165 case DocStyleChange::Small:
168 case DocStyleChange::Preformatted:
171 if (!m_firstCol) m_t << endl;
172 m_t << ".PP" << endl;
173 m_t << ".nf" << endl;
179 if (!m_firstCol) m_t << endl;
180 m_t << ".fi" << endl;
181 m_t << ".PP" << endl;
185 case DocStyleChange::Div: /* HTML only */ break;
186 case DocStyleChange::Span: /* HTML only */ break;
190 void ManDocVisitor::visit(DocVerbatim *s)
193 QCString lang = m_langExt;
194 if (!s->language().isEmpty()) // explicit language setting
196 lang = s->language();
198 SrcLangExt langExt = getLanguageFromFileName(lang);
201 case DocVerbatim::Code: // fall though
202 if (!m_firstCol) m_t << endl;
203 m_t << ".PP" << endl;
204 m_t << ".nf" << endl;
205 Doxygen::parserManager->getParser(lang)
206 ->parseCode(m_ci,s->context(),s->text(),
208 s->isExample(),s->exampleFile());
209 if (!m_firstCol) m_t << endl;
210 m_t << ".fi" << endl;
211 m_t << ".PP" << endl;
214 case DocVerbatim::Verbatim:
215 if (!m_firstCol) m_t << endl;
216 m_t << ".PP" << endl;
217 m_t << ".nf" << endl;
219 if (!m_firstCol) m_t << endl;
220 m_t << ".fi" << endl;
221 m_t << ".PP" << endl;
224 case DocVerbatim::ManOnly:
227 case DocVerbatim::HtmlOnly:
228 case DocVerbatim::XmlOnly:
229 case DocVerbatim::LatexOnly:
230 case DocVerbatim::RtfOnly:
231 case DocVerbatim::DocbookOnly:
232 case DocVerbatim::Dot:
233 case DocVerbatim::Msc:
234 case DocVerbatim::PlantUML:
240 void ManDocVisitor::visit(DocAnchor *)
242 /* no support for anchors in man pages */
245 void ManDocVisitor::visit(DocInclude *inc)
248 SrcLangExt langExt = getLanguageFromFileName(inc->extension());
251 case DocInclude::IncWithLines:
253 if (!m_firstCol) m_t << endl;
254 m_t << ".PP" << endl;
255 m_t << ".nf" << endl;
256 QFileInfo cfi( inc->file() );
257 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
258 Doxygen::parserManager->getParser(inc->extension())
259 ->parseCode(m_ci,inc->context(),
267 FALSE, // inline fragment
271 if (!m_firstCol) m_t << endl;
272 m_t << ".fi" << endl;
273 m_t << ".PP" << endl;
277 case DocInclude::Include:
278 if (!m_firstCol) m_t << endl;
279 m_t << ".PP" << endl;
280 m_t << ".nf" << endl;
281 Doxygen::parserManager->getParser(inc->extension())
282 ->parseCode(m_ci,inc->context(),
290 TRUE, // inlineFragment
294 if (!m_firstCol) m_t << endl;
295 m_t << ".fi" << endl;
296 m_t << ".PP" << endl;
299 case DocInclude::DontInclude:
301 case DocInclude::HtmlInclude:
303 case DocInclude::LatexInclude:
305 case DocInclude::VerbInclude:
306 if (!m_firstCol) m_t << endl;
307 m_t << ".PP" << endl;
308 m_t << ".nf" << endl;
310 if (!m_firstCol) m_t << endl;
311 m_t << ".fi" << endl;
312 m_t << ".PP" << endl;
315 case DocInclude::Snippet:
316 if (!m_firstCol) m_t << endl;
317 m_t << ".PP" << endl;
318 m_t << ".nf" << endl;
319 Doxygen::parserManager->getParser(inc->extension())
322 extractBlock(inc->text(),inc->blockId()),
327 if (!m_firstCol) m_t << endl;
328 m_t << ".fi" << endl;
329 m_t << ".PP" << endl;
332 case DocInclude::SnipWithLines:
334 if (!m_firstCol) m_t << endl;
335 m_t << ".PP" << endl;
336 m_t << ".nf" << endl;
337 QFileInfo cfi( inc->file() );
338 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
339 Doxygen::parserManager->getParser(inc->extension())
342 extractBlock(inc->text(),inc->blockId()),
347 lineBlock(inc->text(),inc->blockId()),
349 FALSE, // inlineFragment
351 TRUE // show line number
353 if (!m_firstCol) m_t << endl;
354 m_t << ".fi" << endl;
355 m_t << ".PP" << endl;
359 case DocInclude::SnippetDoc:
360 case DocInclude::IncludeDoc:
361 err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
362 "Please create a bug report\n",__FILE__);
367 void ManDocVisitor::visit(DocIncOperator *op)
369 SrcLangExt langExt = getLanguageFromFileName(m_langExt);
370 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
371 // op->type(),op->isFirst(),op->isLast(),op->text().data());
376 if (!m_firstCol) m_t << endl;
377 m_t << ".PP" << endl;
378 m_t << ".nf" << endl;
383 if (op->type()!=DocIncOperator::Skip)
388 Doxygen::parserManager->getParser(m_langExt)
389 ->parseCode(m_ci,op->context(),op->text(),langExt,
390 op->isExample(),op->exampleFile());
400 if (!m_firstCol) m_t << endl;
401 m_t << ".fi" << endl;
402 m_t << ".PP" << endl;
408 if (!m_hide) m_t << endl;
412 void ManDocVisitor::visit(DocFormula *f)
418 void ManDocVisitor::visit(DocIndexEntry *)
422 void ManDocVisitor::visit(DocSimpleSectSep *)
426 void ManDocVisitor::visit(DocCite *cite)
430 if (cite->file().isEmpty()) m_t << "[";
431 filter(cite->text());
432 if (cite->file().isEmpty()) m_t << "]";
437 //--------------------------------------
438 // visitor functions for compound nodes
439 //--------------------------------------
441 void ManDocVisitor::visitPre(DocAutoList *)
447 void ManDocVisitor::visitPost(DocAutoList *)
451 m_t << ".PP" << endl;
454 void ManDocVisitor::visitPre(DocAutoListItem *li)
458 ws.fill(' ',m_indent-2);
459 if (!m_firstCol) m_t << endl;
460 m_t << ".IP \"" << ws;
461 if (((DocAutoList *)li->parent())->isEnumList())
463 m_t << li->itemNumber() << ".\" " << m_indent+2;
467 m_t << "\\(bu\" " << m_indent;
473 void ManDocVisitor::visitPost(DocAutoListItem *)
480 void ManDocVisitor::visitPre(DocPara *)
484 void ManDocVisitor::visitPost(DocPara *p)
487 if (!p->isLast() && // omit <p> for last paragraph
488 !(p->parent() && // and for parameter sections
489 p->parent()->kind()==DocNode::Kind_ParamSect
493 if (!m_firstCol) m_t << endl;
494 m_t << ".PP" << endl;
499 void ManDocVisitor::visitPre(DocRoot *)
503 void ManDocVisitor::visitPost(DocRoot *)
507 void ManDocVisitor::visitPre(DocSimpleSect *s)
513 m_t << ".PP" << endl;
518 case DocSimpleSect::See:
519 m_t << theTranslator->trSeeAlso(); break;
520 case DocSimpleSect::Return:
521 m_t << theTranslator->trReturns(); break;
522 case DocSimpleSect::Author:
523 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
524 case DocSimpleSect::Authors:
525 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
526 case DocSimpleSect::Version:
527 m_t << theTranslator->trVersion(); break;
528 case DocSimpleSect::Since:
529 m_t << theTranslator->trSince(); break;
530 case DocSimpleSect::Date:
531 m_t << theTranslator->trDate(); break;
532 case DocSimpleSect::Note:
533 m_t << theTranslator->trNote(); break;
534 case DocSimpleSect::Warning:
535 m_t << theTranslator->trWarning(); break;
536 case DocSimpleSect::Pre:
537 m_t << theTranslator->trPrecondition(); break;
538 case DocSimpleSect::Post:
539 m_t << theTranslator->trPostcondition(); break;
540 case DocSimpleSect::Copyright:
541 m_t << theTranslator->trCopyright(); break;
542 case DocSimpleSect::Invar:
543 m_t << theTranslator->trInvariant(); break;
544 case DocSimpleSect::Remark:
545 m_t << theTranslator->trRemarks(); break;
546 case DocSimpleSect::Attention:
547 m_t << theTranslator->trAttention(); break;
548 case DocSimpleSect::User: break;
549 case DocSimpleSect::Rcs: break;
550 case DocSimpleSect::Unknown: break;
553 // special case 1: user defined title
554 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
556 m_t << ":\\fP" << endl;
557 m_t << ".RS 4" << endl;
561 void ManDocVisitor::visitPost(DocSimpleSect *)
564 if (!m_firstCol) m_t << endl;
565 m_t << ".RE" << endl;
566 m_t << ".PP" << endl;
570 void ManDocVisitor::visitPre(DocTitle *)
574 void ManDocVisitor::visitPost(DocTitle *)
577 m_t << "\\fP" << endl;
578 m_t << ".RS 4" << endl;
581 void ManDocVisitor::visitPre(DocSimpleList *)
585 if (!m_firstCol) m_t << endl;
586 m_t << ".PD 0" << endl;
589 void ManDocVisitor::visitPost(DocSimpleList *)
593 m_t << ".PP" << endl;
596 void ManDocVisitor::visitPre(DocSimpleListItem *)
600 ws.fill(' ',m_indent-2);
601 if (!m_firstCol) m_t << endl;
602 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
606 void ManDocVisitor::visitPost(DocSimpleListItem *)
613 void ManDocVisitor::visitPre(DocSection *s)
616 if (!m_firstCol) m_t << endl;
617 if (s->level()==1) m_t << ".SH"; else m_t << ".SS";
621 if (s->level()==1) m_t << ".PP" << endl;
625 void ManDocVisitor::visitPost(DocSection *)
629 void ManDocVisitor::visitPre(DocHtmlList *)
633 if (!m_firstCol) m_t << endl;
634 m_t << ".PD 0" << endl;
637 void ManDocVisitor::visitPost(DocHtmlList *)
641 if (!m_firstCol) m_t << endl;
642 m_t << ".PP" << endl;
645 void ManDocVisitor::visitPre(DocHtmlListItem *li)
649 ws.fill(' ',m_indent-2);
650 if (!m_firstCol) m_t << endl;
651 m_t << ".IP \"" << ws;
652 if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered)
654 m_t << li->itemNumber() << ".\" " << m_indent+2;
658 m_t << "\\(bu\" " << m_indent;
664 void ManDocVisitor::visitPost(DocHtmlListItem *)
671 //void ManDocVisitor::visitPre(DocHtmlPre *)
673 // if (!m_firstCol) m_t << endl;
674 // m_t << ".PP" << endl;
675 // m_t << ".nf" << endl;
679 //void ManDocVisitor::visitPost(DocHtmlPre *)
681 // m_insidePre=FALSE;
682 // if (!m_firstCol) m_t << endl;
683 // m_t << ".fi" << endl;
684 // m_t << ".PP" << endl;
688 void ManDocVisitor::visitPre(DocHtmlDescList *)
692 void ManDocVisitor::visitPost(DocHtmlDescList *)
695 if (!m_firstCol) m_t << endl;
696 m_t << ".PP" << endl;
700 void ManDocVisitor::visitPre(DocHtmlDescTitle *)
703 if (!m_firstCol) m_t << endl;
708 void ManDocVisitor::visitPost(DocHtmlDescTitle *)
711 m_t << "\\fP\" 1c" << endl;
715 void ManDocVisitor::visitPre(DocHtmlDescData *)
719 void ManDocVisitor::visitPost(DocHtmlDescData *)
723 void ManDocVisitor::visitPre(DocHtmlTable *)
727 void ManDocVisitor::visitPost(DocHtmlTable *)
731 void ManDocVisitor::visitPre(DocHtmlCaption *)
735 void ManDocVisitor::visitPost(DocHtmlCaption *)
739 void ManDocVisitor::visitPre(DocHtmlRow *)
743 void ManDocVisitor::visitPost(DocHtmlRow *)
747 void ManDocVisitor::visitPre(DocHtmlCell *)
751 void ManDocVisitor::visitPost(DocHtmlCell *)
755 void ManDocVisitor::visitPre(DocInternal *)
758 //if (!m_firstCol) m_t << endl;
759 //m_t << ".PP" << endl;
760 //m_t << "\\fB" << theTranslator->trForInternalUseOnly() << "\\fP" << endl;
761 //m_t << ".RS 4" << endl;
764 void ManDocVisitor::visitPost(DocInternal *)
767 //if (!m_firstCol) m_t << endl;
768 //m_t << ".RE" << endl;
769 //m_t << ".PP" << endl;
773 void ManDocVisitor::visitPre(DocHRef *)
779 void ManDocVisitor::visitPost(DocHRef *)
785 void ManDocVisitor::visitPre(DocHtmlHeader *header)
788 if (!m_firstCol) m_t << endl;
789 if (header->level()==1) m_t << ".SH"; else m_t << ".SS";
793 void ManDocVisitor::visitPost(DocHtmlHeader *header)
797 if (header->level()==1) m_t << ".PP" << endl;
801 void ManDocVisitor::visitPre(DocImage *)
805 void ManDocVisitor::visitPost(DocImage *)
809 void ManDocVisitor::visitPre(DocDotFile *)
813 void ManDocVisitor::visitPost(DocDotFile *)
816 void ManDocVisitor::visitPre(DocMscFile *)
820 void ManDocVisitor::visitPost(DocMscFile *)
824 void ManDocVisitor::visitPre(DocDiaFile *)
828 void ManDocVisitor::visitPost(DocDiaFile *)
832 void ManDocVisitor::visitPre(DocLink *)
838 void ManDocVisitor::visitPost(DocLink *)
844 void ManDocVisitor::visitPre(DocRef *ref)
848 if (!ref->hasLinkText()) filter(ref->targetTitle());
851 void ManDocVisitor::visitPost(DocRef *)
857 void ManDocVisitor::visitPre(DocSecRefItem *)
861 ws.fill(' ',m_indent-2);
862 if (!m_firstCol) m_t << endl;
863 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
867 void ManDocVisitor::visitPost(DocSecRefItem *)
874 void ManDocVisitor::visitPre(DocSecRefList *)
880 void ManDocVisitor::visitPost(DocSecRefList *)
884 if (!m_firstCol) m_t << endl;
885 m_t << ".PP" << endl;
888 //void ManDocVisitor::visitPre(DocLanguage *l)
890 // QString langId = Config_getEnum(OUTPUT_LANGUAGE);
891 // if (l->id().lower()!=langId.lower())
898 //void ManDocVisitor::visitPost(DocLanguage *l)
900 // QString langId = Config_getEnum(OUTPUT_LANGUAGE);
901 // if (l->id().lower()!=langId.lower())
907 void ManDocVisitor::visitPre(DocParamSect *s)
913 m_t << ".PP" << endl;
918 case DocParamSect::Param:
919 m_t << theTranslator->trParameters(); break;
920 case DocParamSect::RetVal:
921 m_t << theTranslator->trReturnValues(); break;
922 case DocParamSect::Exception:
923 m_t << theTranslator->trExceptions(); break;
924 case DocParamSect::TemplateParam:
925 m_t << theTranslator->trTemplateParameters(); break;
929 m_t << ":\\fP" << endl;
930 m_t << ".RS 4" << endl;
933 void ManDocVisitor::visitPost(DocParamSect *)
936 if (!m_firstCol) m_t << endl;
937 m_t << ".RE" << endl;
938 m_t << ".PP" << endl;
942 void ManDocVisitor::visitPre(DocParamList *pl)
946 //QStrListIterator li(pl->parameters());
948 QListIterator<DocNode> li(pl->parameters());
951 for (li.toFirst();(param=li.current());++li)
953 if (!first) m_t << ","; else first=FALSE;
954 if (param->kind()==DocNode::Kind_Word)
956 visit((DocWord*)param);
958 else if (param->kind()==DocNode::Kind_LinkedWord)
960 visit((DocLinkedWord*)param);
966 void ManDocVisitor::visitPost(DocParamList *pl)
971 if (!m_firstCol) m_t << endl;
972 m_t << ".br" << endl;
976 void ManDocVisitor::visitPre(DocXRefItem *x)
979 if (x->title().isEmpty()) return;
983 m_t << ".PP" << endl;
987 m_t << "\\fP" << endl;
988 m_t << ".RS 4" << endl;
991 void ManDocVisitor::visitPost(DocXRefItem *x)
994 if (x->title().isEmpty()) return;
995 if (!m_firstCol) m_t << endl;
996 m_t << ".RE" << endl;
997 m_t << ".PP" << endl;
1001 void ManDocVisitor::visitPre(DocInternalRef *)
1007 void ManDocVisitor::visitPost(DocInternalRef *)
1013 void ManDocVisitor::visitPre(DocCopy *)
1017 void ManDocVisitor::visitPost(DocCopy *)
1021 void ManDocVisitor::visitPre(DocText *)
1025 void ManDocVisitor::visitPost(DocText *)
1029 void ManDocVisitor::visitPre(DocHtmlBlockQuote *)
1035 m_t << ".PP" << endl;
1037 m_t << ".RS 4" << endl; // TODO: add support for nested block quotes
1040 void ManDocVisitor::visitPost(DocHtmlBlockQuote *)
1043 if (!m_firstCol) m_t << endl;
1044 m_t << ".RE" << endl;
1045 m_t << ".PP" << endl;
1049 void ManDocVisitor::visitPre(DocVhdlFlow *)
1053 void ManDocVisitor::visitPost(DocVhdlFlow *)
1057 void ManDocVisitor::visitPre(DocParBlock *)
1061 void ManDocVisitor::visitPost(DocParBlock *)
1066 void ManDocVisitor::filter(const char *str)
1076 case '.': m_t << "\\&."; break; // see bug652277
1077 case '\\': m_t << "\\\\"; break;
1078 case '"': c = '\''; // fall through
1079 default: m_t << c; break;
1085 void ManDocVisitor::pushEnabled()
1087 m_enabled.push(new bool(m_hide));
1090 void ManDocVisitor::popEnabled()
1092 bool *v=m_enabled.pop();