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 "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:
216 void ManDocVisitor::visit(DocAnchor *)
218 /* no support for anchors in man pages */
221 void ManDocVisitor::visit(DocInclude *inc)
224 SrcLangExt langExt = getLanguageFromFileName(inc->extension());
227 case DocInclude::IncWithLines:
229 if (!m_firstCol) m_t << endl;
230 m_t << ".PP" << endl;
231 m_t << ".nf" << endl;
232 QFileInfo cfi( inc->file() );
233 FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
234 Doxygen::parserManager->getParser(inc->extension())
235 ->parseCode(m_ci,inc->context(),
239 inc->exampleFile(), &fd);
240 if (!m_firstCol) m_t << endl;
241 m_t << ".fi" << endl;
242 m_t << ".PP" << endl;
246 case DocInclude::Include:
247 if (!m_firstCol) m_t << endl;
248 m_t << ".PP" << endl;
249 m_t << ".nf" << endl;
250 Doxygen::parserManager->getParser(inc->extension())
251 ->parseCode(m_ci,inc->context(),
256 if (!m_firstCol) m_t << endl;
257 m_t << ".fi" << endl;
258 m_t << ".PP" << endl;
261 case DocInclude::DontInclude:
263 case DocInclude::HtmlInclude:
265 case DocInclude::LatexInclude:
267 case DocInclude::VerbInclude:
268 if (!m_firstCol) m_t << endl;
269 m_t << ".PP" << endl;
270 m_t << ".nf" << endl;
272 if (!m_firstCol) m_t << endl;
273 m_t << ".fi" << endl;
274 m_t << ".PP" << endl;
277 case DocInclude::Snippet:
278 if (!m_firstCol) m_t << endl;
279 m_t << ".PP" << endl;
280 m_t << ".nf" << endl;
281 Doxygen::parserManager->getParser(inc->extension())
284 extractBlock(inc->text(),inc->blockId()),
289 if (!m_firstCol) m_t << endl;
290 m_t << ".fi" << endl;
291 m_t << ".PP" << endl;
297 void ManDocVisitor::visit(DocIncOperator *op)
299 SrcLangExt langExt = getLanguageFromFileName(m_langExt);
300 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
301 // op->type(),op->isFirst(),op->isLast(),op->text().data());
306 if (!m_firstCol) m_t << endl;
307 m_t << ".PP" << endl;
308 m_t << ".nf" << endl;
313 if (op->type()!=DocIncOperator::Skip)
318 Doxygen::parserManager->getParser(m_langExt)
319 ->parseCode(m_ci,op->context(),op->text(),langExt,
320 op->isExample(),op->exampleFile());
330 if (!m_firstCol) m_t << endl;
331 m_t << ".fi" << endl;
332 m_t << ".PP" << endl;
338 if (!m_hide) m_t << endl;
342 void ManDocVisitor::visit(DocFormula *f)
348 void ManDocVisitor::visit(DocIndexEntry *)
352 void ManDocVisitor::visit(DocSimpleSectSep *)
356 void ManDocVisitor::visit(DocCite *cite)
360 if (cite->file().isEmpty()) m_t << "[";
361 filter(cite->text());
362 if (cite->file().isEmpty()) m_t << "]";
367 //--------------------------------------
368 // visitor functions for compound nodes
369 //--------------------------------------
371 void ManDocVisitor::visitPre(DocAutoList *)
377 void ManDocVisitor::visitPost(DocAutoList *)
381 m_t << ".PP" << endl;
384 void ManDocVisitor::visitPre(DocAutoListItem *li)
388 ws.fill(' ',m_indent-2);
389 if (!m_firstCol) m_t << endl;
390 m_t << ".IP \"" << ws;
391 if (((DocAutoList *)li->parent())->isEnumList())
393 m_t << li->itemNumber() << ".\" " << m_indent+2;
397 m_t << "\\(bu\" " << m_indent;
403 void ManDocVisitor::visitPost(DocAutoListItem *)
410 void ManDocVisitor::visitPre(DocPara *)
414 void ManDocVisitor::visitPost(DocPara *p)
417 if (!p->isLast() && // omit <p> for last paragraph
418 !(p->parent() && // and for parameter sections
419 p->parent()->kind()==DocNode::Kind_ParamSect
423 if (!m_firstCol) m_t << endl;
424 m_t << ".PP" << endl;
429 void ManDocVisitor::visitPre(DocRoot *)
433 void ManDocVisitor::visitPost(DocRoot *)
437 void ManDocVisitor::visitPre(DocSimpleSect *s)
443 m_t << ".PP" << endl;
448 case DocSimpleSect::See:
449 m_t << theTranslator->trSeeAlso(); break;
450 case DocSimpleSect::Return:
451 m_t << theTranslator->trReturns(); break;
452 case DocSimpleSect::Author:
453 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
454 case DocSimpleSect::Authors:
455 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
456 case DocSimpleSect::Version:
457 m_t << theTranslator->trVersion(); break;
458 case DocSimpleSect::Since:
459 m_t << theTranslator->trSince(); break;
460 case DocSimpleSect::Date:
461 m_t << theTranslator->trDate(); break;
462 case DocSimpleSect::Note:
463 m_t << theTranslator->trNote(); break;
464 case DocSimpleSect::Warning:
465 m_t << theTranslator->trWarning(); break;
466 case DocSimpleSect::Pre:
467 m_t << theTranslator->trPrecondition(); break;
468 case DocSimpleSect::Post:
469 m_t << theTranslator->trPostcondition(); break;
470 case DocSimpleSect::Copyright:
471 m_t << theTranslator->trCopyright(); break;
472 case DocSimpleSect::Invar:
473 m_t << theTranslator->trInvariant(); break;
474 case DocSimpleSect::Remark:
475 m_t << theTranslator->trRemarks(); break;
476 case DocSimpleSect::Attention:
477 m_t << theTranslator->trAttention(); break;
478 case DocSimpleSect::User: break;
479 case DocSimpleSect::Rcs: break;
480 case DocSimpleSect::Unknown: break;
483 // special case 1: user defined title
484 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
486 m_t << ":\\fP" << endl;
487 m_t << ".RS 4" << endl;
491 void ManDocVisitor::visitPost(DocSimpleSect *)
494 if (!m_firstCol) m_t << endl;
495 m_t << ".RE" << endl;
496 m_t << ".PP" << endl;
500 void ManDocVisitor::visitPre(DocTitle *)
504 void ManDocVisitor::visitPost(DocTitle *)
507 m_t << "\\fP" << endl;
508 m_t << ".RS 4" << endl;
511 void ManDocVisitor::visitPre(DocSimpleList *)
515 if (!m_firstCol) m_t << endl;
516 m_t << ".PD 0" << endl;
519 void ManDocVisitor::visitPost(DocSimpleList *)
523 m_t << ".PP" << endl;
526 void ManDocVisitor::visitPre(DocSimpleListItem *)
530 ws.fill(' ',m_indent-2);
531 if (!m_firstCol) m_t << endl;
532 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
536 void ManDocVisitor::visitPost(DocSimpleListItem *)
543 void ManDocVisitor::visitPre(DocSection *s)
546 if (!m_firstCol) m_t << endl;
547 if (s->level()==1) m_t << ".SH"; else m_t << ".SS";
551 if (s->level()==1) m_t << ".PP" << endl;
555 void ManDocVisitor::visitPost(DocSection *)
559 void ManDocVisitor::visitPre(DocHtmlList *)
563 if (!m_firstCol) m_t << endl;
564 m_t << ".PD 0" << endl;
567 void ManDocVisitor::visitPost(DocHtmlList *)
571 if (!m_firstCol) m_t << endl;
572 m_t << ".PP" << endl;
575 void ManDocVisitor::visitPre(DocHtmlListItem *li)
579 ws.fill(' ',m_indent-2);
580 if (!m_firstCol) m_t << endl;
581 m_t << ".IP \"" << ws;
582 if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered)
584 m_t << li->itemNumber() << ".\" " << m_indent+2;
588 m_t << "\\(bu\" " << m_indent;
594 void ManDocVisitor::visitPost(DocHtmlListItem *)
601 //void ManDocVisitor::visitPre(DocHtmlPre *)
603 // if (!m_firstCol) m_t << endl;
604 // m_t << ".PP" << endl;
605 // m_t << ".nf" << endl;
609 //void ManDocVisitor::visitPost(DocHtmlPre *)
611 // m_insidePre=FALSE;
612 // if (!m_firstCol) m_t << endl;
613 // m_t << ".fi" << endl;
614 // m_t << ".PP" << endl;
618 void ManDocVisitor::visitPre(DocHtmlDescList *)
622 void ManDocVisitor::visitPost(DocHtmlDescList *)
625 if (!m_firstCol) m_t << endl;
626 m_t << ".PP" << endl;
630 void ManDocVisitor::visitPre(DocHtmlDescTitle *)
633 if (!m_firstCol) m_t << endl;
638 void ManDocVisitor::visitPost(DocHtmlDescTitle *)
641 m_t << "\\fP\" 1c" << endl;
645 void ManDocVisitor::visitPre(DocHtmlDescData *)
649 void ManDocVisitor::visitPost(DocHtmlDescData *)
653 void ManDocVisitor::visitPre(DocHtmlTable *)
657 void ManDocVisitor::visitPost(DocHtmlTable *)
661 void ManDocVisitor::visitPre(DocHtmlCaption *)
665 void ManDocVisitor::visitPost(DocHtmlCaption *)
669 void ManDocVisitor::visitPre(DocHtmlRow *)
673 void ManDocVisitor::visitPost(DocHtmlRow *)
677 void ManDocVisitor::visitPre(DocHtmlCell *)
681 void ManDocVisitor::visitPost(DocHtmlCell *)
685 void ManDocVisitor::visitPre(DocInternal *)
688 //if (!m_firstCol) m_t << endl;
689 //m_t << ".PP" << endl;
690 //m_t << "\\fB" << theTranslator->trForInternalUseOnly() << "\\fP" << endl;
691 //m_t << ".RS 4" << endl;
694 void ManDocVisitor::visitPost(DocInternal *)
697 //if (!m_firstCol) m_t << endl;
698 //m_t << ".RE" << endl;
699 //m_t << ".PP" << endl;
703 void ManDocVisitor::visitPre(DocHRef *)
709 void ManDocVisitor::visitPost(DocHRef *)
715 void ManDocVisitor::visitPre(DocHtmlHeader *header)
718 if (!m_firstCol) m_t << endl;
719 if (header->level()==1) m_t << ".SH"; else m_t << ".SS";
723 void ManDocVisitor::visitPost(DocHtmlHeader *header)
727 if (header->level()==1) m_t << ".PP" << endl;
731 void ManDocVisitor::visitPre(DocImage *)
735 void ManDocVisitor::visitPost(DocImage *)
739 void ManDocVisitor::visitPre(DocDotFile *)
743 void ManDocVisitor::visitPost(DocDotFile *)
746 void ManDocVisitor::visitPre(DocMscFile *)
750 void ManDocVisitor::visitPost(DocMscFile *)
754 void ManDocVisitor::visitPre(DocDiaFile *)
758 void ManDocVisitor::visitPost(DocDiaFile *)
762 void ManDocVisitor::visitPre(DocLink *)
768 void ManDocVisitor::visitPost(DocLink *)
774 void ManDocVisitor::visitPre(DocRef *ref)
778 if (!ref->hasLinkText()) filter(ref->targetTitle());
781 void ManDocVisitor::visitPost(DocRef *)
787 void ManDocVisitor::visitPre(DocSecRefItem *)
791 ws.fill(' ',m_indent-2);
792 if (!m_firstCol) m_t << endl;
793 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
797 void ManDocVisitor::visitPost(DocSecRefItem *)
804 void ManDocVisitor::visitPre(DocSecRefList *)
810 void ManDocVisitor::visitPost(DocSecRefList *)
814 if (!m_firstCol) m_t << endl;
815 m_t << ".PP" << endl;
818 //void ManDocVisitor::visitPre(DocLanguage *l)
820 // QString langId = Config_getEnum("OUTPUT_LANGUAGE");
821 // if (l->id().lower()!=langId.lower())
828 //void ManDocVisitor::visitPost(DocLanguage *l)
830 // QString langId = Config_getEnum("OUTPUT_LANGUAGE");
831 // if (l->id().lower()!=langId.lower())
837 void ManDocVisitor::visitPre(DocParamSect *s)
843 m_t << ".PP" << endl;
848 case DocParamSect::Param:
849 m_t << theTranslator->trParameters(); break;
850 case DocParamSect::RetVal:
851 m_t << theTranslator->trReturnValues(); break;
852 case DocParamSect::Exception:
853 m_t << theTranslator->trExceptions(); break;
854 case DocParamSect::TemplateParam:
856 m_t << theTranslator->trTemplateParam(); break;
858 m_t << "Template Parameters"; break;
862 m_t << ":\\fP" << endl;
863 m_t << ".RS 4" << endl;
866 void ManDocVisitor::visitPost(DocParamSect *)
869 if (!m_firstCol) m_t << endl;
870 m_t << ".RE" << endl;
871 m_t << ".PP" << endl;
875 void ManDocVisitor::visitPre(DocParamList *pl)
879 //QStrListIterator li(pl->parameters());
881 QListIterator<DocNode> li(pl->parameters());
884 for (li.toFirst();(param=li.current());++li)
886 if (!first) m_t << ","; else first=FALSE;
887 if (param->kind()==DocNode::Kind_Word)
889 visit((DocWord*)param);
891 else if (param->kind()==DocNode::Kind_LinkedWord)
893 visit((DocLinkedWord*)param);
899 void ManDocVisitor::visitPost(DocParamList *pl)
904 if (!m_firstCol) m_t << endl;
905 m_t << ".br" << endl;
909 void ManDocVisitor::visitPre(DocXRefItem *x)
912 if (x->title().isEmpty()) return;
916 m_t << ".PP" << endl;
920 m_t << "\\fP" << endl;
921 m_t << ".RS 4" << endl;
924 void ManDocVisitor::visitPost(DocXRefItem *x)
927 if (x->title().isEmpty()) return;
928 if (!m_firstCol) m_t << endl;
929 m_t << ".RE" << endl;
930 m_t << ".PP" << endl;
934 void ManDocVisitor::visitPre(DocInternalRef *)
940 void ManDocVisitor::visitPost(DocInternalRef *)
946 void ManDocVisitor::visitPre(DocCopy *)
950 void ManDocVisitor::visitPost(DocCopy *)
954 void ManDocVisitor::visitPre(DocText *)
958 void ManDocVisitor::visitPost(DocText *)
962 void ManDocVisitor::visitPre(DocHtmlBlockQuote *)
968 m_t << ".PP" << endl;
970 m_t << ".RS 4" << endl; // TODO: add support for nested block quotes
973 void ManDocVisitor::visitPost(DocHtmlBlockQuote *)
976 if (!m_firstCol) m_t << endl;
977 m_t << ".RE" << endl;
978 m_t << ".PP" << endl;
982 void ManDocVisitor::visitPre(DocVhdlFlow *)
986 void ManDocVisitor::visitPost(DocVhdlFlow *)
990 void ManDocVisitor::visitPre(DocParBlock *)
994 void ManDocVisitor::visitPost(DocParBlock *)
999 void ManDocVisitor::filter(const char *str)
1009 case '.': m_t << "\\&."; break; // see bug652277
1010 case '\\': m_t << "\\\\"; break;
1011 case '"': c = '\''; // fall through
1012 default: m_t << c; break;
1018 void ManDocVisitor::pushEnabled()
1020 m_enabled.push(new bool(m_hide));
1023 void ManDocVisitor::popEnabled()
1025 bool *v=m_enabled.pop();