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:
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(),
240 inc->exampleFile(), &fd);
241 if (!m_firstCol) m_t << endl;
242 m_t << ".fi" << endl;
243 m_t << ".PP" << endl;
247 case DocInclude::Include:
248 if (!m_firstCol) m_t << endl;
249 m_t << ".PP" << endl;
250 m_t << ".nf" << endl;
251 Doxygen::parserManager->getParser(inc->extension())
252 ->parseCode(m_ci,inc->context(),
257 if (!m_firstCol) m_t << endl;
258 m_t << ".fi" << endl;
259 m_t << ".PP" << endl;
262 case DocInclude::DontInclude:
264 case DocInclude::HtmlInclude:
266 case DocInclude::LatexInclude:
268 case DocInclude::VerbInclude:
269 if (!m_firstCol) m_t << endl;
270 m_t << ".PP" << endl;
271 m_t << ".nf" << endl;
273 if (!m_firstCol) m_t << endl;
274 m_t << ".fi" << endl;
275 m_t << ".PP" << endl;
278 case DocInclude::Snippet:
279 if (!m_firstCol) m_t << endl;
280 m_t << ".PP" << endl;
281 m_t << ".nf" << endl;
282 Doxygen::parserManager->getParser(inc->extension())
285 extractBlock(inc->text(),inc->blockId()),
290 if (!m_firstCol) m_t << endl;
291 m_t << ".fi" << endl;
292 m_t << ".PP" << endl;
298 void ManDocVisitor::visit(DocIncOperator *op)
300 SrcLangExt langExt = getLanguageFromFileName(m_langExt);
301 //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
302 // op->type(),op->isFirst(),op->isLast(),op->text().data());
307 if (!m_firstCol) m_t << endl;
308 m_t << ".PP" << endl;
309 m_t << ".nf" << endl;
314 if (op->type()!=DocIncOperator::Skip)
319 Doxygen::parserManager->getParser(m_langExt)
320 ->parseCode(m_ci,op->context(),op->text(),langExt,
321 op->isExample(),op->exampleFile());
331 if (!m_firstCol) m_t << endl;
332 m_t << ".fi" << endl;
333 m_t << ".PP" << endl;
339 if (!m_hide) m_t << endl;
343 void ManDocVisitor::visit(DocFormula *f)
349 void ManDocVisitor::visit(DocIndexEntry *)
353 void ManDocVisitor::visit(DocSimpleSectSep *)
357 void ManDocVisitor::visit(DocCite *cite)
361 if (cite->file().isEmpty()) m_t << "[";
362 filter(cite->text());
363 if (cite->file().isEmpty()) m_t << "]";
368 //--------------------------------------
369 // visitor functions for compound nodes
370 //--------------------------------------
372 void ManDocVisitor::visitPre(DocAutoList *)
378 void ManDocVisitor::visitPost(DocAutoList *)
382 m_t << ".PP" << endl;
385 void ManDocVisitor::visitPre(DocAutoListItem *li)
389 ws.fill(' ',m_indent-2);
390 if (!m_firstCol) m_t << endl;
391 m_t << ".IP \"" << ws;
392 if (((DocAutoList *)li->parent())->isEnumList())
394 m_t << li->itemNumber() << ".\" " << m_indent+2;
398 m_t << "\\(bu\" " << m_indent;
404 void ManDocVisitor::visitPost(DocAutoListItem *)
411 void ManDocVisitor::visitPre(DocPara *)
415 void ManDocVisitor::visitPost(DocPara *p)
418 if (!p->isLast() && // omit <p> for last paragraph
419 !(p->parent() && // and for parameter sections
420 p->parent()->kind()==DocNode::Kind_ParamSect
424 if (!m_firstCol) m_t << endl;
425 m_t << ".PP" << endl;
430 void ManDocVisitor::visitPre(DocRoot *)
434 void ManDocVisitor::visitPost(DocRoot *)
438 void ManDocVisitor::visitPre(DocSimpleSect *s)
444 m_t << ".PP" << endl;
449 case DocSimpleSect::See:
450 m_t << theTranslator->trSeeAlso(); break;
451 case DocSimpleSect::Return:
452 m_t << theTranslator->trReturns(); break;
453 case DocSimpleSect::Author:
454 m_t << theTranslator->trAuthor(TRUE,TRUE); break;
455 case DocSimpleSect::Authors:
456 m_t << theTranslator->trAuthor(TRUE,FALSE); break;
457 case DocSimpleSect::Version:
458 m_t << theTranslator->trVersion(); break;
459 case DocSimpleSect::Since:
460 m_t << theTranslator->trSince(); break;
461 case DocSimpleSect::Date:
462 m_t << theTranslator->trDate(); break;
463 case DocSimpleSect::Note:
464 m_t << theTranslator->trNote(); break;
465 case DocSimpleSect::Warning:
466 m_t << theTranslator->trWarning(); break;
467 case DocSimpleSect::Pre:
468 m_t << theTranslator->trPrecondition(); break;
469 case DocSimpleSect::Post:
470 m_t << theTranslator->trPostcondition(); break;
471 case DocSimpleSect::Copyright:
472 m_t << theTranslator->trCopyright(); break;
473 case DocSimpleSect::Invar:
474 m_t << theTranslator->trInvariant(); break;
475 case DocSimpleSect::Remark:
476 m_t << theTranslator->trRemarks(); break;
477 case DocSimpleSect::Attention:
478 m_t << theTranslator->trAttention(); break;
479 case DocSimpleSect::User: break;
480 case DocSimpleSect::Rcs: break;
481 case DocSimpleSect::Unknown: break;
484 // special case 1: user defined title
485 if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
487 m_t << ":\\fP" << endl;
488 m_t << ".RS 4" << endl;
492 void ManDocVisitor::visitPost(DocSimpleSect *)
495 if (!m_firstCol) m_t << endl;
496 m_t << ".RE" << endl;
497 m_t << ".PP" << endl;
501 void ManDocVisitor::visitPre(DocTitle *)
505 void ManDocVisitor::visitPost(DocTitle *)
508 m_t << "\\fP" << endl;
509 m_t << ".RS 4" << endl;
512 void ManDocVisitor::visitPre(DocSimpleList *)
516 if (!m_firstCol) m_t << endl;
517 m_t << ".PD 0" << endl;
520 void ManDocVisitor::visitPost(DocSimpleList *)
524 m_t << ".PP" << endl;
527 void ManDocVisitor::visitPre(DocSimpleListItem *)
531 ws.fill(' ',m_indent-2);
532 if (!m_firstCol) m_t << endl;
533 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
537 void ManDocVisitor::visitPost(DocSimpleListItem *)
544 void ManDocVisitor::visitPre(DocSection *s)
547 if (!m_firstCol) m_t << endl;
548 if (s->level()==1) m_t << ".SH"; else m_t << ".SS";
552 if (s->level()==1) m_t << ".PP" << endl;
556 void ManDocVisitor::visitPost(DocSection *)
560 void ManDocVisitor::visitPre(DocHtmlList *)
564 if (!m_firstCol) m_t << endl;
565 m_t << ".PD 0" << endl;
568 void ManDocVisitor::visitPost(DocHtmlList *)
572 if (!m_firstCol) m_t << endl;
573 m_t << ".PP" << endl;
576 void ManDocVisitor::visitPre(DocHtmlListItem *li)
580 ws.fill(' ',m_indent-2);
581 if (!m_firstCol) m_t << endl;
582 m_t << ".IP \"" << ws;
583 if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered)
585 m_t << li->itemNumber() << ".\" " << m_indent+2;
589 m_t << "\\(bu\" " << m_indent;
595 void ManDocVisitor::visitPost(DocHtmlListItem *)
602 //void ManDocVisitor::visitPre(DocHtmlPre *)
604 // if (!m_firstCol) m_t << endl;
605 // m_t << ".PP" << endl;
606 // m_t << ".nf" << endl;
610 //void ManDocVisitor::visitPost(DocHtmlPre *)
612 // m_insidePre=FALSE;
613 // if (!m_firstCol) m_t << endl;
614 // m_t << ".fi" << endl;
615 // m_t << ".PP" << endl;
619 void ManDocVisitor::visitPre(DocHtmlDescList *)
623 void ManDocVisitor::visitPost(DocHtmlDescList *)
626 if (!m_firstCol) m_t << endl;
627 m_t << ".PP" << endl;
631 void ManDocVisitor::visitPre(DocHtmlDescTitle *)
634 if (!m_firstCol) m_t << endl;
639 void ManDocVisitor::visitPost(DocHtmlDescTitle *)
642 m_t << "\\fP\" 1c" << endl;
646 void ManDocVisitor::visitPre(DocHtmlDescData *)
650 void ManDocVisitor::visitPost(DocHtmlDescData *)
654 void ManDocVisitor::visitPre(DocHtmlTable *)
658 void ManDocVisitor::visitPost(DocHtmlTable *)
662 void ManDocVisitor::visitPre(DocHtmlCaption *)
666 void ManDocVisitor::visitPost(DocHtmlCaption *)
670 void ManDocVisitor::visitPre(DocHtmlRow *)
674 void ManDocVisitor::visitPost(DocHtmlRow *)
678 void ManDocVisitor::visitPre(DocHtmlCell *)
682 void ManDocVisitor::visitPost(DocHtmlCell *)
686 void ManDocVisitor::visitPre(DocInternal *)
689 //if (!m_firstCol) m_t << endl;
690 //m_t << ".PP" << endl;
691 //m_t << "\\fB" << theTranslator->trForInternalUseOnly() << "\\fP" << endl;
692 //m_t << ".RS 4" << endl;
695 void ManDocVisitor::visitPost(DocInternal *)
698 //if (!m_firstCol) m_t << endl;
699 //m_t << ".RE" << endl;
700 //m_t << ".PP" << endl;
704 void ManDocVisitor::visitPre(DocHRef *)
710 void ManDocVisitor::visitPost(DocHRef *)
716 void ManDocVisitor::visitPre(DocHtmlHeader *header)
719 if (!m_firstCol) m_t << endl;
720 if (header->level()==1) m_t << ".SH"; else m_t << ".SS";
724 void ManDocVisitor::visitPost(DocHtmlHeader *header)
728 if (header->level()==1) m_t << ".PP" << endl;
732 void ManDocVisitor::visitPre(DocImage *)
736 void ManDocVisitor::visitPost(DocImage *)
740 void ManDocVisitor::visitPre(DocDotFile *)
744 void ManDocVisitor::visitPost(DocDotFile *)
747 void ManDocVisitor::visitPre(DocMscFile *)
751 void ManDocVisitor::visitPost(DocMscFile *)
755 void ManDocVisitor::visitPre(DocDiaFile *)
759 void ManDocVisitor::visitPost(DocDiaFile *)
763 void ManDocVisitor::visitPre(DocLink *)
769 void ManDocVisitor::visitPost(DocLink *)
775 void ManDocVisitor::visitPre(DocRef *ref)
779 if (!ref->hasLinkText()) filter(ref->targetTitle());
782 void ManDocVisitor::visitPost(DocRef *)
788 void ManDocVisitor::visitPre(DocSecRefItem *)
792 ws.fill(' ',m_indent-2);
793 if (!m_firstCol) m_t << endl;
794 m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
798 void ManDocVisitor::visitPost(DocSecRefItem *)
805 void ManDocVisitor::visitPre(DocSecRefList *)
811 void ManDocVisitor::visitPost(DocSecRefList *)
815 if (!m_firstCol) m_t << endl;
816 m_t << ".PP" << endl;
819 //void ManDocVisitor::visitPre(DocLanguage *l)
821 // QString langId = Config_getEnum("OUTPUT_LANGUAGE");
822 // if (l->id().lower()!=langId.lower())
829 //void ManDocVisitor::visitPost(DocLanguage *l)
831 // QString langId = Config_getEnum("OUTPUT_LANGUAGE");
832 // if (l->id().lower()!=langId.lower())
838 void ManDocVisitor::visitPre(DocParamSect *s)
844 m_t << ".PP" << endl;
849 case DocParamSect::Param:
850 m_t << theTranslator->trParameters(); break;
851 case DocParamSect::RetVal:
852 m_t << theTranslator->trReturnValues(); break;
853 case DocParamSect::Exception:
854 m_t << theTranslator->trExceptions(); break;
855 case DocParamSect::TemplateParam:
857 m_t << theTranslator->trTemplateParam(); break;
859 m_t << "Template Parameters"; break;
863 m_t << ":\\fP" << endl;
864 m_t << ".RS 4" << endl;
867 void ManDocVisitor::visitPost(DocParamSect *)
870 if (!m_firstCol) m_t << endl;
871 m_t << ".RE" << endl;
872 m_t << ".PP" << endl;
876 void ManDocVisitor::visitPre(DocParamList *pl)
880 //QStrListIterator li(pl->parameters());
882 QListIterator<DocNode> li(pl->parameters());
885 for (li.toFirst();(param=li.current());++li)
887 if (!first) m_t << ","; else first=FALSE;
888 if (param->kind()==DocNode::Kind_Word)
890 visit((DocWord*)param);
892 else if (param->kind()==DocNode::Kind_LinkedWord)
894 visit((DocLinkedWord*)param);
900 void ManDocVisitor::visitPost(DocParamList *pl)
905 if (!m_firstCol) m_t << endl;
906 m_t << ".br" << endl;
910 void ManDocVisitor::visitPre(DocXRefItem *x)
913 if (x->title().isEmpty()) return;
917 m_t << ".PP" << endl;
921 m_t << "\\fP" << endl;
922 m_t << ".RS 4" << endl;
925 void ManDocVisitor::visitPost(DocXRefItem *x)
928 if (x->title().isEmpty()) return;
929 if (!m_firstCol) m_t << endl;
930 m_t << ".RE" << endl;
931 m_t << ".PP" << endl;
935 void ManDocVisitor::visitPre(DocInternalRef *)
941 void ManDocVisitor::visitPost(DocInternalRef *)
947 void ManDocVisitor::visitPre(DocCopy *)
951 void ManDocVisitor::visitPost(DocCopy *)
955 void ManDocVisitor::visitPre(DocText *)
959 void ManDocVisitor::visitPost(DocText *)
963 void ManDocVisitor::visitPre(DocHtmlBlockQuote *)
969 m_t << ".PP" << endl;
971 m_t << ".RS 4" << endl; // TODO: add support for nested block quotes
974 void ManDocVisitor::visitPost(DocHtmlBlockQuote *)
977 if (!m_firstCol) m_t << endl;
978 m_t << ".RE" << endl;
979 m_t << ".PP" << endl;
983 void ManDocVisitor::visitPre(DocVhdlFlow *)
987 void ManDocVisitor::visitPost(DocVhdlFlow *)
991 void ManDocVisitor::visitPre(DocParBlock *)
995 void ManDocVisitor::visitPost(DocParBlock *)
1000 void ManDocVisitor::filter(const char *str)
1010 case '.': m_t << "\\&."; break; // see bug652277
1011 case '\\': m_t << "\\\\"; break;
1012 case '"': c = '\''; // fall through
1013 default: m_t << c; break;
1019 void ManDocVisitor::pushEnabled()
1021 m_enabled.push(new bool(m_hide));
1024 void ManDocVisitor::popEnabled()
1026 bool *v=m_enabled.pop();