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"
34 ManDocVisitor::ManDocVisitor(FTextStream &t,CodeOutputInterface &ci,
36 : DocVisitor(DocVisitor_Man), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_firstCol(FALSE),
37 m_indent(0), m_langExt(langExt)
41 //--------------------------------------
42 // visitor functions for leaf nodes
43 //--------------------------------------
45 void ManDocVisitor::visit(DocWord *w)
52 void ManDocVisitor::visit(DocLinkedWord *w)
61 void ManDocVisitor::visit(DocWhiteSpace *w)
67 m_firstCol=w->chars().at(w->chars().length()-1)=='\n';
76 void ManDocVisitor::visit(DocSymbol *s)
79 const char *res = HtmlEntityMapper::instance()->man(s->symbol());
86 // no error or warning to be supplied
87 // err("man: non supported HTML-entity found: &%s;\n",get_symbol_item(s->symbol()));
92 void ManDocVisitor::visit(DocURL *u)
99 void ManDocVisitor::visit(DocLineBreak *)
102 m_t << endl << ".br" << endl;
106 void ManDocVisitor::visit(DocHorRuler *)
109 if (!m_firstCol) m_t << endl;
110 m_t << ".PP" << endl;
114 void ManDocVisitor::visit(DocStyleChange *s)
119 case DocStyleChange::Bold:
120 if (s->enable()) m_t << "\\fB"; else m_t << "\\fP";
123 case DocStyleChange::Italic:
124 if (s->enable()) m_t << "\\fI"; else m_t << "\\fP";
127 case DocStyleChange::Code:
128 if (s->enable()) m_t << "\\fC"; else m_t << "\\fP";
131 case DocStyleChange::Subscript:
132 if (s->enable()) m_t << "\\*<"; else m_t << "\\*> ";
135 case DocStyleChange::Superscript:
136 if (s->enable()) m_t << "\\*{"; else m_t << "\\*} ";
139 case DocStyleChange::Center:
142 case DocStyleChange::Small:
145 case DocStyleChange::Preformatted:
148 if (!m_firstCol) m_t << endl;
149 m_t << ".PP" << endl;
150 m_t << ".nf" << endl;
156 if (!m_firstCol) m_t << endl;
157 m_t << ".fi" << endl;
158 m_t << ".PP" << endl;
162 case DocStyleChange::Div: /* HTML only */ break;
163 case DocStyleChange::Span: /* HTML only */ break;
167 void ManDocVisitor::visit(DocVerbatim *s)
170 QCString lang = m_langExt;
171 if (!s->language().isEmpty()) // explicit language setting
173 lang = s->language();
175 SrcLangExt langExt = getLanguageFromFileName(lang);
178 case DocVerbatim::Code: // fall though
179 if (!m_firstCol) m_t << endl;
180 m_t << ".PP" << endl;
181 m_t << ".nf" << endl;
182 Doxygen::parserManager->getParser(lang)
183 ->parseCode(m_ci,s->context(),s->text(),
185 s->isExample(),s->exampleFile());
186 if (!m_firstCol) m_t << endl;
187 m_t << ".fi" << endl;
188 m_t << ".PP" << endl;
191 case DocVerbatim::Verbatim:
192 if (!m_firstCol) m_t << endl;
193 m_t << ".PP" << endl;
194 m_t << ".nf" << endl;
196 if (!m_firstCol) m_t << endl;
197 m_t << ".fi" << endl;
198 m_t << ".PP" << endl;
201 case DocVerbatim::ManOnly:
204 case DocVerbatim::HtmlOnly:
205 case DocVerbatim::XmlOnly:
206 case DocVerbatim::LatexOnly:
207 case DocVerbatim::RtfOnly:
208 case DocVerbatim::DocbookOnly:
209 case DocVerbatim::Dot:
210 case DocVerbatim::Msc:
211 case DocVerbatim::PlantUML:
217 void ManDocVisitor::visit(DocAnchor *)
219 /* no support for anchors in man pages */
222 void ManDocVisitor::visit(DocInclude *inc)
225 SrcLangExt langExt = getLanguageFromFileName(inc->extension());
228 case DocInclude::IncWithLines:
230 if (!m_firstCol) m_t << endl;
231 m_t << ".PP" << endl;
232 m_t << ".nf" << endl;
233 QFileInfo cfi( inc->file() );
234 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
235 Doxygen::parserManager->getParser(inc->extension())
236 ->parseCode(m_ci,inc->context(),
244 FALSE, // inline fragment
248 if (!m_firstCol) m_t << endl;
249 m_t << ".fi" << endl;
250 m_t << ".PP" << endl;
254 case DocInclude::Include:
255 if (!m_firstCol) m_t << endl;
256 m_t << ".PP" << endl;
257 m_t << ".nf" << endl;
258 Doxygen::parserManager->getParser(inc->extension())
259 ->parseCode(m_ci,inc->context(),
267 TRUE, // inlineFragment
271 if (!m_firstCol) m_t << endl;
272 m_t << ".fi" << endl;
273 m_t << ".PP" << endl;
276 case DocInclude::DontInclude:
278 case DocInclude::HtmlInclude:
280 case DocInclude::LatexInclude:
282 case DocInclude::VerbInclude:
283 if (!m_firstCol) m_t << endl;
284 m_t << ".PP" << endl;
285 m_t << ".nf" << endl;
287 if (!m_firstCol) m_t << endl;
288 m_t << ".fi" << endl;
289 m_t << ".PP" << endl;
292 case DocInclude::Snippet:
293 if (!m_firstCol) m_t << endl;
294 m_t << ".PP" << endl;
295 m_t << ".nf" << endl;
296 Doxygen::parserManager->getParser(inc->extension())
299 extractBlock(inc->text(),inc->blockId()),
304 if (!m_firstCol) m_t << endl;
305 m_t << ".fi" << endl;
306 m_t << ".PP" << endl;
309 case DocInclude::SnipWithLines:
311 if (!m_firstCol) m_t << endl;
312 m_t << ".PP" << endl;
313 m_t << ".nf" << endl;
314 QFileInfo cfi( inc->file() );
315 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
316 Doxygen::parserManager->getParser(inc->extension())
319 extractBlock(inc->text(),inc->blockId()),
324 lineBlock(inc->text(),inc->blockId()),
326 FALSE, // inlineFragment
328 TRUE // show line number
330 if (!m_firstCol) m_t << endl;
331 m_t << ".fi" << endl;
332 m_t << ".PP" << endl;
336 case DocInclude::SnippetDoc:
337 case DocInclude::IncludeDoc:
338 err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
339 "Please create a bug report\n",__FILE__);
344 void ManDocVisitor::visit(DocIncOperator *op)
346 SrcLangExt langExt = getLanguageFromFileName(m_langExt);
347 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
348 // op->type(),op->isFirst(),op->isLast(),op->text().data());
353 if (!m_firstCol) m_t << endl;
354 m_t << ".PP" << endl;
355 m_t << ".nf" << endl;
360 if (op->type()!=DocIncOperator::Skip)
365 Doxygen::parserManager->getParser(m_langExt)
366 ->parseCode(m_ci,op->context(),op->text(),langExt,
367 op->isExample(),op->exampleFile());
377 if (!m_firstCol) m_t << endl;
378 m_t << ".fi" << endl;
379 m_t << ".PP" << endl;
385 if (!m_hide) m_t << endl;
389 void ManDocVisitor::visit(DocFormula *f)
395 void ManDocVisitor::visit(DocIndexEntry *)
399 void ManDocVisitor::visit(DocSimpleSectSep *)
403 void ManDocVisitor::visit(DocCite *cite)
407 if (cite->file().isEmpty()) m_t << "[";
408 filter(cite->text());
409 if (cite->file().isEmpty()) m_t << "]";
414 //--------------------------------------
415 // visitor functions for compound nodes
416 //--------------------------------------
418 void ManDocVisitor::visitPre(DocAutoList *)
424 void ManDocVisitor::visitPost(DocAutoList *)
428 m_t << ".PP" << endl;
431 void ManDocVisitor::visitPre(DocAutoListItem *li)
435 ws.fill(' ',m_indent-2);
436 if (!m_firstCol) m_t << endl;
437 m_t << ".IP \"" << ws;
438 if (((DocAutoList *)li->parent())->isEnumList())
440 m_t << li->itemNumber() << ".\" " << m_indent+2;
444 m_t << "\\(bu\" " << m_indent;
450 void ManDocVisitor::visitPost(DocAutoListItem *)
457 void ManDocVisitor::visitPre(DocPara *)
461 void ManDocVisitor::visitPost(DocPara *p)
464 if (!p->isLast() && // omit <p> for last paragraph
465 !(p->parent() && // and for parameter sections
466 p->parent()->kind()==DocNode::Kind_ParamSect
470 if (!m_firstCol) m_t << endl;
471 m_t << ".PP" << endl;
476 void ManDocVisitor::visitPre(DocRoot *)
480 void ManDocVisitor::visitPost(DocRoot *)
484 void ManDocVisitor::visitPre(DocSimpleSect *s)
490 m_t << ".PP" << endl;
495 case DocSimpleSect::See:
496 m_t << theTranslator->trSeeAlso(); break;
497 case DocSimpleSect::Return:
498 m_t << theTranslator->trReturns(); break;
499 case DocSimpleSect::Author:
500 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
501 case DocSimpleSect::Authors:
502 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
503 case DocSimpleSect::Version:
504 m_t << theTranslator->trVersion(); break;
505 case DocSimpleSect::Since:
506 m_t << theTranslator->trSince(); break;
507 case DocSimpleSect::Date:
508 m_t << theTranslator->trDate(); break;
509 case DocSimpleSect::Note:
510 m_t << theTranslator->trNote(); break;
511 case DocSimpleSect::Warning:
512 m_t << theTranslator->trWarning(); break;
513 case DocSimpleSect::Pre:
514 m_t << theTranslator->trPrecondition(); break;
515 case DocSimpleSect::Post:
516 m_t << theTranslator->trPostcondition(); break;
517 case DocSimpleSect::Copyright:
518 m_t << theTranslator->trCopyright(); break;
519 case DocSimpleSect::Invar:
520 m_t << theTranslator->trInvariant(); break;
521 case DocSimpleSect::Remark:
522 m_t << theTranslator->trRemarks(); break;
523 case DocSimpleSect::Attention:
524 m_t << theTranslator->trAttention(); break;
525 case DocSimpleSect::User: break;
526 case DocSimpleSect::Rcs: break;
527 case DocSimpleSect::Unknown: break;
530 // special case 1: user defined title
531 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
533 m_t << ":\\fP" << endl;
534 m_t << ".RS 4" << endl;
538 void ManDocVisitor::visitPost(DocSimpleSect *)
541 if (!m_firstCol) m_t << endl;
542 m_t << ".RE" << endl;
543 m_t << ".PP" << endl;
547 void ManDocVisitor::visitPre(DocTitle *)
551 void ManDocVisitor::visitPost(DocTitle *)
554 m_t << "\\fP" << endl;
555 m_t << ".RS 4" << endl;
558 void ManDocVisitor::visitPre(DocSimpleList *)
562 if (!m_firstCol) m_t << endl;
563 m_t << ".PD 0" << endl;
566 void ManDocVisitor::visitPost(DocSimpleList *)
570 m_t << ".PP" << endl;
573 void ManDocVisitor::visitPre(DocSimpleListItem *)
577 ws.fill(' ',m_indent-2);
578 if (!m_firstCol) m_t << endl;
579 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
583 void ManDocVisitor::visitPost(DocSimpleListItem *)
590 void ManDocVisitor::visitPre(DocSection *s)
593 if (!m_firstCol) m_t << endl;
594 if (s->level()==1) m_t << ".SH"; else m_t << ".SS";
598 if (s->level()==1) m_t << ".PP" << endl;
602 void ManDocVisitor::visitPost(DocSection *)
606 void ManDocVisitor::visitPre(DocHtmlList *)
610 if (!m_firstCol) m_t << endl;
611 m_t << ".PD 0" << endl;
614 void ManDocVisitor::visitPost(DocHtmlList *)
618 if (!m_firstCol) m_t << endl;
619 m_t << ".PP" << endl;
622 void ManDocVisitor::visitPre(DocHtmlListItem *li)
626 ws.fill(' ',m_indent-2);
627 if (!m_firstCol) m_t << endl;
628 m_t << ".IP \"" << ws;
629 if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered)
631 m_t << li->itemNumber() << ".\" " << m_indent+2;
635 m_t << "\\(bu\" " << m_indent;
641 void ManDocVisitor::visitPost(DocHtmlListItem *)
648 //void ManDocVisitor::visitPre(DocHtmlPre *)
650 // if (!m_firstCol) m_t << endl;
651 // m_t << ".PP" << endl;
652 // m_t << ".nf" << endl;
656 //void ManDocVisitor::visitPost(DocHtmlPre *)
658 // m_insidePre=FALSE;
659 // if (!m_firstCol) m_t << endl;
660 // m_t << ".fi" << endl;
661 // m_t << ".PP" << endl;
665 void ManDocVisitor::visitPre(DocHtmlDescList *)
669 void ManDocVisitor::visitPost(DocHtmlDescList *)
672 if (!m_firstCol) m_t << endl;
673 m_t << ".PP" << endl;
677 void ManDocVisitor::visitPre(DocHtmlDescTitle *)
680 if (!m_firstCol) m_t << endl;
685 void ManDocVisitor::visitPost(DocHtmlDescTitle *)
688 m_t << "\\fP\" 1c" << endl;
692 void ManDocVisitor::visitPre(DocHtmlDescData *)
696 void ManDocVisitor::visitPost(DocHtmlDescData *)
700 void ManDocVisitor::visitPre(DocHtmlTable *)
704 void ManDocVisitor::visitPost(DocHtmlTable *)
708 void ManDocVisitor::visitPre(DocHtmlCaption *)
712 void ManDocVisitor::visitPost(DocHtmlCaption *)
716 void ManDocVisitor::visitPre(DocHtmlRow *)
720 void ManDocVisitor::visitPost(DocHtmlRow *)
724 void ManDocVisitor::visitPre(DocHtmlCell *)
728 void ManDocVisitor::visitPost(DocHtmlCell *)
732 void ManDocVisitor::visitPre(DocInternal *)
735 //if (!m_firstCol) m_t << endl;
736 //m_t << ".PP" << endl;
737 //m_t << "\\fB" << theTranslator->trForInternalUseOnly() << "\\fP" << endl;
738 //m_t << ".RS 4" << endl;
741 void ManDocVisitor::visitPost(DocInternal *)
744 //if (!m_firstCol) m_t << endl;
745 //m_t << ".RE" << endl;
746 //m_t << ".PP" << endl;
750 void ManDocVisitor::visitPre(DocHRef *)
756 void ManDocVisitor::visitPost(DocHRef *)
762 void ManDocVisitor::visitPre(DocHtmlHeader *header)
765 if (!m_firstCol) m_t << endl;
766 if (header->level()==1) m_t << ".SH"; else m_t << ".SS";
770 void ManDocVisitor::visitPost(DocHtmlHeader *header)
774 if (header->level()==1) m_t << ".PP" << endl;
778 void ManDocVisitor::visitPre(DocImage *)
782 void ManDocVisitor::visitPost(DocImage *)
786 void ManDocVisitor::visitPre(DocDotFile *)
790 void ManDocVisitor::visitPost(DocDotFile *)
793 void ManDocVisitor::visitPre(DocMscFile *)
797 void ManDocVisitor::visitPost(DocMscFile *)
801 void ManDocVisitor::visitPre(DocDiaFile *)
805 void ManDocVisitor::visitPost(DocDiaFile *)
809 void ManDocVisitor::visitPre(DocLink *)
815 void ManDocVisitor::visitPost(DocLink *)
821 void ManDocVisitor::visitPre(DocRef *ref)
825 if (!ref->hasLinkText()) filter(ref->targetTitle());
828 void ManDocVisitor::visitPost(DocRef *)
834 void ManDocVisitor::visitPre(DocSecRefItem *)
838 ws.fill(' ',m_indent-2);
839 if (!m_firstCol) m_t << endl;
840 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
844 void ManDocVisitor::visitPost(DocSecRefItem *)
851 void ManDocVisitor::visitPre(DocSecRefList *)
857 void ManDocVisitor::visitPost(DocSecRefList *)
861 if (!m_firstCol) m_t << endl;
862 m_t << ".PP" << endl;
865 //void ManDocVisitor::visitPre(DocLanguage *l)
867 // QString langId = Config_getEnum(OUTPUT_LANGUAGE);
868 // if (l->id().lower()!=langId.lower())
875 //void ManDocVisitor::visitPost(DocLanguage *l)
877 // QString langId = Config_getEnum(OUTPUT_LANGUAGE);
878 // if (l->id().lower()!=langId.lower())
884 void ManDocVisitor::visitPre(DocParamSect *s)
890 m_t << ".PP" << endl;
895 case DocParamSect::Param:
896 m_t << theTranslator->trParameters(); break;
897 case DocParamSect::RetVal:
898 m_t << theTranslator->trReturnValues(); break;
899 case DocParamSect::Exception:
900 m_t << theTranslator->trExceptions(); break;
901 case DocParamSect::TemplateParam:
903 m_t << theTranslator->trTemplateParam(); break;
905 m_t << "Template Parameters"; break;
909 m_t << ":\\fP" << endl;
910 m_t << ".RS 4" << endl;
913 void ManDocVisitor::visitPost(DocParamSect *)
916 if (!m_firstCol) m_t << endl;
917 m_t << ".RE" << endl;
918 m_t << ".PP" << endl;
922 void ManDocVisitor::visitPre(DocParamList *pl)
926 //QStrListIterator li(pl->parameters());
928 QListIterator<DocNode> li(pl->parameters());
931 for (li.toFirst();(param=li.current());++li)
933 if (!first) m_t << ","; else first=FALSE;
934 if (param->kind()==DocNode::Kind_Word)
936 visit((DocWord*)param);
938 else if (param->kind()==DocNode::Kind_LinkedWord)
940 visit((DocLinkedWord*)param);
946 void ManDocVisitor::visitPost(DocParamList *pl)
951 if (!m_firstCol) m_t << endl;
952 m_t << ".br" << endl;
956 void ManDocVisitor::visitPre(DocXRefItem *x)
959 if (x->title().isEmpty()) return;
963 m_t << ".PP" << endl;
967 m_t << "\\fP" << endl;
968 m_t << ".RS 4" << endl;
971 void ManDocVisitor::visitPost(DocXRefItem *x)
974 if (x->title().isEmpty()) return;
975 if (!m_firstCol) m_t << endl;
976 m_t << ".RE" << endl;
977 m_t << ".PP" << endl;
981 void ManDocVisitor::visitPre(DocInternalRef *)
987 void ManDocVisitor::visitPost(DocInternalRef *)
993 void ManDocVisitor::visitPre(DocCopy *)
997 void ManDocVisitor::visitPost(DocCopy *)
1001 void ManDocVisitor::visitPre(DocText *)
1005 void ManDocVisitor::visitPost(DocText *)
1009 void ManDocVisitor::visitPre(DocHtmlBlockQuote *)
1015 m_t << ".PP" << endl;
1017 m_t << ".RS 4" << endl; // TODO: add support for nested block quotes
1020 void ManDocVisitor::visitPost(DocHtmlBlockQuote *)
1023 if (!m_firstCol) m_t << endl;
1024 m_t << ".RE" << endl;
1025 m_t << ".PP" << endl;
1029 void ManDocVisitor::visitPre(DocVhdlFlow *)
1033 void ManDocVisitor::visitPost(DocVhdlFlow *)
1037 void ManDocVisitor::visitPre(DocParBlock *)
1041 void ManDocVisitor::visitPost(DocParBlock *)
1046 void ManDocVisitor::filter(const char *str)
1056 case '.': m_t << "\\&."; break; // see bug652277
1057 case '\\': m_t << "\\\\"; break;
1058 case '"': c = '\''; // fall through
1059 default: m_t << c; break;
1065 void ManDocVisitor::pushEnabled()
1067 m_enabled.push(new bool(m_hide));
1070 void ManDocVisitor::popEnabled()
1072 bool *v=m_enabled.pop();