2233cc66971588307341cbf4ee8a15f78fe6f7ee
[platform/upstream/doxygen.git] / src / mandocvisitor.cpp
1 /******************************************************************************
2  *
3  * 
4  *
5  *
6  * Copyright (C) 1997-2015 by Dimitri van Heesch.
7  *
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.
13  *
14  * Documents produced by Doxygen are derivative works derived from the
15  * input used in their production; they are not affected by this license.
16  *
17  */
18
19 #include <qfileinfo.h> 
20
21 #include "mandocvisitor.h"
22 #include "docparser.h"
23 #include "language.h"
24 #include "doxygen.h"
25 #include "outputgen.h"
26 #include "code.h"
27 #include "dot.h"
28 #include "util.h"
29 #include "message.h"
30 #include "parserintf.h"
31 #include "filedef.h"
32 #include "htmlentity.h"
33
34 ManDocVisitor::ManDocVisitor(FTextStream &t,CodeOutputInterface &ci,
35                              const char *langExt) 
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)
38 {
39 }
40
41   //--------------------------------------
42   // visitor functions for leaf nodes
43   //--------------------------------------
44
45 void ManDocVisitor::visit(DocWord *w)
46 {
47   if (m_hide) return;
48   filter(w->word());
49   m_firstCol=FALSE;
50 }
51
52 void ManDocVisitor::visit(DocLinkedWord *w)
53 {
54   if (m_hide) return;
55   m_t << "\\fB";
56   filter(w->word());
57   m_t << "\\fP";
58   m_firstCol=FALSE;
59 }
60
61 void ManDocVisitor::visit(DocWhiteSpace *w)
62 {
63   if (m_hide) return;
64   if (m_insidePre)
65   {
66     m_t << w->chars();
67     m_firstCol=w->chars().at(w->chars().length()-1)=='\n';
68   }
69   else
70   {
71     m_t << " ";
72     m_firstCol=FALSE;
73   }
74 }
75
76 void ManDocVisitor::visit(DocSymbol *s)
77 {
78   if (m_hide) return;
79   const char *res = HtmlEntityMapper::instance()->man(s->symbol());
80   if (res)
81   {
82     m_t << res;
83   }
84   else
85   {
86     // no error or warning to be supplied
87     // err("man: non supported HTML-entity found: &%s;\n",get_symbol_item(s->symbol()));
88   }
89   m_firstCol=FALSE;
90 }
91
92 void ManDocVisitor::visit(DocURL *u)
93 {
94   if (m_hide) return;
95   m_t << u->url();
96   m_firstCol=FALSE;
97 }
98
99 void ManDocVisitor::visit(DocLineBreak *)
100 {
101   if (m_hide) return;
102   m_t << endl << ".br" << endl;
103   m_firstCol=TRUE;
104 }
105
106 void ManDocVisitor::visit(DocHorRuler *)
107 {
108   if (m_hide) return;
109   if (!m_firstCol) m_t << endl;
110   m_t << ".PP" << endl;
111   m_firstCol=TRUE;
112 }
113
114 void ManDocVisitor::visit(DocStyleChange *s)
115 {
116   if (m_hide) return;
117   switch (s->style())
118   {
119     case DocStyleChange::Bold:
120       if (s->enable()) m_t << "\\fB";      else m_t << "\\fP";
121       m_firstCol=FALSE;
122       break;
123     case DocStyleChange::Italic:
124       if (s->enable()) m_t << "\\fI";     else m_t << "\\fP";
125       m_firstCol=FALSE;
126       break;
127     case DocStyleChange::Code:
128       if (s->enable()) m_t << "\\fC";   else m_t << "\\fP";
129       m_firstCol=FALSE;
130       break;
131     case DocStyleChange::Subscript:
132       if (s->enable()) m_t << "\\*<";    else m_t << "\\*> ";
133       m_firstCol=FALSE;
134       break;
135     case DocStyleChange::Superscript:
136       if (s->enable()) m_t << "\\*{";    else m_t << "\\*} ";
137       m_firstCol=FALSE;
138       break;
139     case DocStyleChange::Center:
140       /* not supported */
141       break;
142     case DocStyleChange::Small:
143       /* not supported */
144       break;
145     case DocStyleChange::Preformatted:
146       if (s->enable())
147       {
148         if (!m_firstCol) m_t << endl;
149         m_t << ".PP" << endl;
150         m_t << ".nf" << endl;
151         m_insidePre=TRUE;
152       }
153       else
154       {
155         m_insidePre=FALSE;
156         if (!m_firstCol) m_t << endl;
157         m_t << ".fi" << endl;
158         m_t << ".PP" << endl;
159         m_firstCol=TRUE;
160       }
161       break;
162     case DocStyleChange::Div:  /* HTML only */ break;
163     case DocStyleChange::Span: /* HTML only */ break;
164   }
165 }
166
167 void ManDocVisitor::visit(DocVerbatim *s)
168 {
169   if (m_hide) return;
170   QCString lang = m_langExt;
171   if (!s->language().isEmpty()) // explicit language setting
172   {
173     lang = s->language();
174   }
175   SrcLangExt langExt = getLanguageFromFileName(lang);
176   switch (s->type())
177   {
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(),
184                                         langExt,
185                                         s->isExample(),s->exampleFile());
186       if (!m_firstCol) m_t << endl;
187       m_t << ".fi" << endl;
188       m_t << ".PP" << endl;
189       m_firstCol=TRUE;
190       break;
191     case DocVerbatim::Verbatim: 
192       if (!m_firstCol) m_t << endl;
193       m_t << ".PP" << endl;
194       m_t << ".nf" << endl;
195       m_t << s->text();
196       if (!m_firstCol) m_t << endl;
197       m_t << ".fi" << endl;
198       m_t << ".PP" << endl;
199       m_firstCol=TRUE;
200       break;
201     case DocVerbatim::ManOnly: 
202       m_t << s->text(); 
203       break;
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: 
212       /* nothing */ 
213       break;
214   }
215 }
216
217 void ManDocVisitor::visit(DocAnchor *)
218 {
219   /* no support for anchors in man pages */
220 }
221
222 void ManDocVisitor::visit(DocInclude *inc)
223 {
224   if (m_hide) return;
225   SrcLangExt langExt = getLanguageFromFileName(inc->extension());
226   switch(inc->type())
227   {
228     case DocInclude::IncWithLines:
229       { 
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(),
237                                            inc->text(),
238                                            langExt,
239                                            inc->isExample(),
240                                            inc->exampleFile(),
241                                            &fd,   // fileDef,
242                                            -1,    // start line
243                                            -1,    // end line
244                                            FALSE, // inline fragment
245                                            0,     // memberDef
246                                            TRUE
247                                            );
248          if (!m_firstCol) m_t << endl;
249          m_t << ".fi" << endl;
250          m_t << ".PP" << endl;
251          m_firstCol=TRUE;
252       }
253       break;
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(),
260                                         inc->text(),
261                                         langExt,
262                                         inc->isExample(),
263                                         inc->exampleFile(),
264                                         0,     // fileDef
265                                         -1,    // startLine
266                                         -1,    // endLine
267                                         TRUE,  // inlineFragment
268                                         0,     // memberDef
269                                         FALSE
270                                        );
271       if (!m_firstCol) m_t << endl;
272       m_t << ".fi" << endl;
273       m_t << ".PP" << endl;
274       m_firstCol=TRUE;
275       break;
276     case DocInclude::DontInclude: 
277       break;
278     case DocInclude::HtmlInclude: 
279       break;
280     case DocInclude::LatexInclude:
281       break;
282     case DocInclude::VerbInclude: 
283       if (!m_firstCol) m_t << endl;
284       m_t << ".PP" << endl;
285       m_t << ".nf" << endl;
286       m_t << inc->text();
287       if (!m_firstCol) m_t << endl;
288       m_t << ".fi" << endl;
289       m_t << ".PP" << endl;
290       m_firstCol=TRUE;
291       break;
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())
297                             ->parseCode(m_ci,
298                                         inc->context(),
299                                         extractBlock(inc->text(),inc->blockId()),
300                                         langExt,
301                                         inc->isExample(),
302                                         inc->exampleFile()
303                                        );
304       if (!m_firstCol) m_t << endl;
305       m_t << ".fi" << endl;
306       m_t << ".PP" << endl;
307       m_firstCol=TRUE;
308       break;
309     case DocInclude::SnipWithLines:
310       {
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())
317                                ->parseCode(m_ci,
318                                            inc->context(),
319                                            extractBlock(inc->text(),inc->blockId()),
320                                            langExt,
321                                            inc->isExample(),
322                                            inc->exampleFile(), 
323                                            &fd,
324                                            lineBlock(inc->text(),inc->blockId()),
325                                            -1,    // endLine
326                                            FALSE, // inlineFragment
327                                            0,     // memberDef
328                                            TRUE   // show line number
329                                           );
330          if (!m_firstCol) m_t << endl;
331          m_t << ".fi" << endl;
332          m_t << ".PP" << endl;
333          m_firstCol=TRUE;
334       }
335       break;
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__);
340       break;
341   }
342 }
343
344 void ManDocVisitor::visit(DocIncOperator *op)
345 {
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());
349   if (op->isFirst()) 
350   {
351     if (!m_hide)
352     {
353       if (!m_firstCol) m_t << endl;
354       m_t << ".PP" << endl;
355       m_t << ".nf" << endl;
356     }
357     pushEnabled();
358     m_hide = TRUE;
359   }
360   if (op->type()!=DocIncOperator::Skip) 
361   {
362     popEnabled();
363     if (!m_hide) 
364     {
365       Doxygen::parserManager->getParser(m_langExt)
366                             ->parseCode(m_ci,op->context(),op->text(),langExt,
367                                         op->isExample(),op->exampleFile());
368     }
369     pushEnabled();
370     m_hide=TRUE;
371   }
372   if (op->isLast())  
373   {
374     popEnabled();
375     if (!m_hide)
376     {
377       if (!m_firstCol) m_t << endl;
378       m_t << ".fi" << endl;
379       m_t << ".PP" << endl;
380       m_firstCol=TRUE;
381     }
382   }
383   else
384   {
385     if (!m_hide) m_t << endl;
386   }
387 }
388
389 void ManDocVisitor::visit(DocFormula *f)
390 {
391   if (m_hide) return;
392   m_t << f->text();
393 }
394
395 void ManDocVisitor::visit(DocIndexEntry *)
396 {
397 }
398
399 void ManDocVisitor::visit(DocSimpleSectSep *)
400 {
401 }
402
403 void ManDocVisitor::visit(DocCite *cite)
404 {
405   if (m_hide) return;
406   m_t << "\\fB";
407   if (cite->file().isEmpty()) m_t << "[";
408   filter(cite->text());
409   if (cite->file().isEmpty()) m_t << "]";
410   m_t << "\\fP";
411 }
412
413
414 //--------------------------------------
415 // visitor functions for compound nodes
416 //--------------------------------------
417
418 void ManDocVisitor::visitPre(DocAutoList *)
419 {
420   if (m_hide) return;
421   m_indent+=2;
422 }
423
424 void ManDocVisitor::visitPost(DocAutoList *)
425 {
426   if (m_hide) return;
427   m_indent-=2;
428   m_t << ".PP" << endl;
429 }
430
431 void ManDocVisitor::visitPre(DocAutoListItem *li)
432 {
433   if (m_hide) return;
434   QCString ws;
435   ws.fill(' ',m_indent-2);
436   if (!m_firstCol) m_t << endl;
437   m_t << ".IP \"" << ws; 
438   if (((DocAutoList *)li->parent())->isEnumList())
439   {
440     m_t << li->itemNumber() << ".\" " << m_indent+2;
441   }
442   else // bullet list
443   {
444     m_t << "\\(bu\" " << m_indent;
445   }
446   m_t << endl;
447   m_firstCol=TRUE;
448 }
449
450 void ManDocVisitor::visitPost(DocAutoListItem *) 
451 {
452   if (m_hide) return;
453   m_t << endl;
454   m_firstCol=TRUE;
455 }
456
457 void ManDocVisitor::visitPre(DocPara *) 
458 {
459 }
460
461 void ManDocVisitor::visitPost(DocPara *p)
462 {
463   if (m_hide) return;
464   if (!p->isLast() &&            // omit <p> for last paragraph
465       !(p->parent() &&           // and for parameter sections
466         p->parent()->kind()==DocNode::Kind_ParamSect
467        )
468      ) 
469   {
470     if (!m_firstCol) m_t << endl;
471     m_t << ".PP" << endl;
472     m_firstCol=TRUE;
473   }
474 }
475
476 void ManDocVisitor::visitPre(DocRoot *)
477 {
478 }
479
480 void ManDocVisitor::visitPost(DocRoot *)
481 {
482 }
483
484 void ManDocVisitor::visitPre(DocSimpleSect *s)
485 {
486   if (m_hide) return;
487   if (!m_firstCol)
488   { 
489     m_t << endl;
490     m_t << ".PP" << endl;
491   }
492   m_t << "\\fB";
493   switch(s->type())
494   {
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;
528   }
529
530   // special case 1: user defined title
531   if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
532   {
533     m_t << ":\\fP" << endl;
534     m_t << ".RS 4" << endl;
535   }
536 }
537
538 void ManDocVisitor::visitPost(DocSimpleSect *)
539 {
540   if (m_hide) return;
541   if (!m_firstCol) m_t << endl;
542   m_t << ".RE" << endl;
543   m_t << ".PP" << endl;
544   m_firstCol=TRUE;
545 }
546
547 void ManDocVisitor::visitPre(DocTitle *)
548 {
549 }
550
551 void ManDocVisitor::visitPost(DocTitle *)
552 {
553   if (m_hide) return;
554   m_t << "\\fP" << endl;
555   m_t << ".RS 4" << endl;
556 }
557
558 void ManDocVisitor::visitPre(DocSimpleList *)
559 {
560   if (m_hide) return;
561   m_indent+=2;
562   if (!m_firstCol) m_t << endl;
563   m_t << ".PD 0" << endl;
564 }
565
566 void ManDocVisitor::visitPost(DocSimpleList *)
567 {
568   if (m_hide) return;
569   m_indent-=2;
570   m_t << ".PP" << endl;
571 }
572
573 void ManDocVisitor::visitPre(DocSimpleListItem *)
574 {
575   if (m_hide) return;
576   QCString ws;
577   ws.fill(' ',m_indent-2);
578   if (!m_firstCol) m_t << endl;
579   m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
580   m_firstCol=TRUE;
581 }
582
583 void ManDocVisitor::visitPost(DocSimpleListItem *) 
584 {
585   if (m_hide) return;
586   m_t << endl;
587   m_firstCol=TRUE;
588 }
589
590 void ManDocVisitor::visitPre(DocSection *s)
591 {
592   if (m_hide) return;
593   if (!m_firstCol) m_t << endl;
594   if (s->level()==1) m_t << ".SH"; else m_t << ".SS";
595   m_t << " \"";
596   filter(s->title());
597   m_t << "\"" << endl;
598   if (s->level()==1) m_t << ".PP" << endl;
599   m_firstCol=TRUE;
600 }
601
602 void ManDocVisitor::visitPost(DocSection *) 
603 {
604 }
605
606 void ManDocVisitor::visitPre(DocHtmlList *)
607 {
608   if (m_hide) return;
609   m_indent+=2;
610   if (!m_firstCol) m_t << endl;
611   m_t << ".PD 0" << endl;
612 }
613
614 void ManDocVisitor::visitPost(DocHtmlList *) 
615 {
616   if (m_hide) return;
617   m_indent-=2;
618   if (!m_firstCol) m_t << endl;
619   m_t << ".PP" << endl;
620 }
621
622 void ManDocVisitor::visitPre(DocHtmlListItem *li)
623 {
624   if (m_hide) return;
625   QCString ws;
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)
630   {
631     m_t << li->itemNumber() << ".\" " << m_indent+2;
632   }
633   else // bullet list
634   {
635     m_t << "\\(bu\" " << m_indent;
636   }
637   m_t << endl;
638   m_firstCol=TRUE;
639 }
640
641 void ManDocVisitor::visitPost(DocHtmlListItem *) 
642 {
643   if (m_hide) return;
644   m_t << endl;
645   m_firstCol=TRUE;
646 }
647
648 //void ManDocVisitor::visitPre(DocHtmlPre *)
649 //{
650 //  if (!m_firstCol) m_t << endl;
651 //  m_t << ".PP" << endl;
652 //  m_t << ".nf" << endl;
653 //  m_insidePre=TRUE;
654 //}
655 //
656 //void ManDocVisitor::visitPost(DocHtmlPre *) 
657 //{
658 //  m_insidePre=FALSE;
659 //  if (!m_firstCol) m_t << endl;
660 //  m_t << ".fi" << endl;
661 //  m_t << ".PP" << endl;
662 //  m_firstCol=TRUE;
663 //}
664
665 void ManDocVisitor::visitPre(DocHtmlDescList *)
666 {
667 }
668
669 void ManDocVisitor::visitPost(DocHtmlDescList *) 
670 {
671   if (m_hide) return;
672   if (!m_firstCol) m_t << endl;
673   m_t << ".PP" << endl;
674   m_firstCol=TRUE;
675 }
676
677 void ManDocVisitor::visitPre(DocHtmlDescTitle *)
678 {
679   if (m_hide) return;
680   if (!m_firstCol) m_t << endl;
681   m_t << ".IP \"\\fB";
682   m_firstCol=FALSE;
683 }
684
685 void ManDocVisitor::visitPost(DocHtmlDescTitle *) 
686 {
687   if (m_hide) return;
688   m_t << "\\fP\" 1c" << endl;
689   m_firstCol=TRUE;
690 }
691
692 void ManDocVisitor::visitPre(DocHtmlDescData *)
693 {
694 }
695
696 void ManDocVisitor::visitPost(DocHtmlDescData *) 
697 {
698 }
699
700 void ManDocVisitor::visitPre(DocHtmlTable *)
701 {
702 }
703
704 void ManDocVisitor::visitPost(DocHtmlTable *) 
705 {
706 }
707
708 void ManDocVisitor::visitPre(DocHtmlCaption *)
709 {
710 }
711
712 void ManDocVisitor::visitPost(DocHtmlCaption *) 
713 {
714 }
715
716 void ManDocVisitor::visitPre(DocHtmlRow *)
717 {
718 }
719
720 void ManDocVisitor::visitPost(DocHtmlRow *) 
721 {
722 }
723
724 void ManDocVisitor::visitPre(DocHtmlCell *)
725 {
726 }
727
728 void ManDocVisitor::visitPost(DocHtmlCell *) 
729 {
730 }
731
732 void ManDocVisitor::visitPre(DocInternal *)
733 {
734   if (m_hide) return;
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;
739 }
740
741 void ManDocVisitor::visitPost(DocInternal *) 
742 {
743   if (m_hide) return;
744   //if (!m_firstCol) m_t << endl;
745   //m_t << ".RE" << endl;
746   //m_t << ".PP" << endl;
747   //m_firstCol=TRUE;
748 }
749
750 void ManDocVisitor::visitPre(DocHRef *)
751 {
752   if (m_hide) return;
753   m_t << "\\fC";
754 }
755
756 void ManDocVisitor::visitPost(DocHRef *) 
757 {
758   if (m_hide) return;
759   m_t << "\\fP";
760 }
761
762 void ManDocVisitor::visitPre(DocHtmlHeader *header)
763 {
764   if (m_hide) return;
765   if (!m_firstCol) m_t << endl;
766   if (header->level()==1) m_t << ".SH"; else m_t << ".SS";
767   m_t << " \"";
768 }
769
770 void ManDocVisitor::visitPost(DocHtmlHeader *header) 
771 {
772   if (m_hide) return;
773   m_t << "\"" << endl;
774   if (header->level()==1) m_t << ".PP" << endl;
775   m_firstCol=TRUE;
776 }
777
778 void ManDocVisitor::visitPre(DocImage *)
779 {
780 }
781
782 void ManDocVisitor::visitPost(DocImage *) 
783 {
784 }
785
786 void ManDocVisitor::visitPre(DocDotFile *)
787 {
788 }
789
790 void ManDocVisitor::visitPost(DocDotFile *) 
791 {
792 }
793 void ManDocVisitor::visitPre(DocMscFile *)
794 {
795 }
796
797 void ManDocVisitor::visitPost(DocMscFile *) 
798 {
799 }
800
801 void ManDocVisitor::visitPre(DocDiaFile *)
802 {
803 }
804
805 void ManDocVisitor::visitPost(DocDiaFile *)
806 {
807 }
808
809 void ManDocVisitor::visitPre(DocLink *)
810 {
811   if (m_hide) return;
812   m_t << "\\fB";
813 }
814
815 void ManDocVisitor::visitPost(DocLink *) 
816 {
817   if (m_hide) return;
818   m_t << "\\fP";
819 }
820
821 void ManDocVisitor::visitPre(DocRef *ref)
822 {
823   if (m_hide) return;
824   m_t << "\\fB";
825   if (!ref->hasLinkText()) filter(ref->targetTitle());
826 }
827
828 void ManDocVisitor::visitPost(DocRef *) 
829 {
830   if (m_hide) return;
831   m_t << "\\fP";
832 }
833
834 void ManDocVisitor::visitPre(DocSecRefItem *)
835 {
836   if (m_hide) return;
837   QCString ws;
838   ws.fill(' ',m_indent-2);
839   if (!m_firstCol) m_t << endl;
840   m_t << ".IP \"" << ws << "\\(bu\" " << m_indent << endl;
841   m_firstCol=TRUE;
842 }
843
844 void ManDocVisitor::visitPost(DocSecRefItem *) 
845 {
846   if (m_hide) return;
847   m_t << endl;
848   m_firstCol=TRUE;
849 }
850
851 void ManDocVisitor::visitPre(DocSecRefList *)
852 {
853   if (m_hide) return;
854   m_indent+=2;
855 }
856
857 void ManDocVisitor::visitPost(DocSecRefList *) 
858 {
859   if (m_hide) return;
860   m_indent-=2;
861   if (!m_firstCol) m_t << endl;
862   m_t << ".PP" << endl;
863 }
864
865 //void ManDocVisitor::visitPre(DocLanguage *l)
866 //{
867 //  QString langId = Config_getEnum(OUTPUT_LANGUAGE);
868 //  if (l->id().lower()!=langId.lower())
869 //  {
870 //    pushEnabled();
871 //    m_hide = TRUE;
872 //  }
873 //}
874 //
875 //void ManDocVisitor::visitPost(DocLanguage *l) 
876 //{
877 //  QString langId = Config_getEnum(OUTPUT_LANGUAGE);
878 //  if (l->id().lower()!=langId.lower())
879 //  {
880 //    popEnabled();
881 //  }
882 //}
883
884 void ManDocVisitor::visitPre(DocParamSect *s)
885 {
886   if (m_hide) return;
887   if (!m_firstCol)
888   { 
889     m_t << endl;
890     m_t << ".PP" << endl;
891   }
892   m_t << "\\fB";
893   switch(s->type())
894   {
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: 
902       /* TODO: add this 
903       m_t << theTranslator->trTemplateParam(); break;
904       */
905       m_t << "Template Parameters"; break;
906     default:
907       ASSERT(0);
908   }
909   m_t << ":\\fP" << endl;
910   m_t << ".RS 4" << endl;
911 }
912
913 void ManDocVisitor::visitPost(DocParamSect *)
914 {
915   if (m_hide) return;
916   if (!m_firstCol) m_t << endl;
917   m_t << ".RE" << endl;
918   m_t << ".PP" << endl;
919   m_firstCol=TRUE;
920 }
921
922 void ManDocVisitor::visitPre(DocParamList *pl)
923 {
924   if (m_hide) return;
925   m_t << "\\fI";
926   //QStrListIterator li(pl->parameters());
927   //const char *s;
928   QListIterator<DocNode> li(pl->parameters());
929   DocNode *param;
930   bool first=TRUE;
931   for (li.toFirst();(param=li.current());++li)
932   {
933     if (!first) m_t << ","; else first=FALSE;
934     if (param->kind()==DocNode::Kind_Word)
935     {
936       visit((DocWord*)param); 
937     }
938     else if (param->kind()==DocNode::Kind_LinkedWord)
939     {
940       visit((DocLinkedWord*)param); 
941     }
942   }
943   m_t << "\\fP ";
944 }
945
946 void ManDocVisitor::visitPost(DocParamList *pl)
947 {
948   if (m_hide) return;
949   if (!pl->isLast())
950   {
951     if (!m_firstCol) m_t << endl;
952     m_t << ".br" << endl;
953   }
954 }
955
956 void ManDocVisitor::visitPre(DocXRefItem *x)
957 {
958   if (m_hide) return;
959   if (x->title().isEmpty()) return;
960   if (!m_firstCol)
961   { 
962     m_t << endl;
963     m_t << ".PP" << endl;
964   }
965   m_t << "\\fB";
966   filter(x->title());
967   m_t << "\\fP" << endl;
968   m_t << ".RS 4" << endl;
969 }
970
971 void ManDocVisitor::visitPost(DocXRefItem *x)
972 {
973   if (m_hide) return;
974   if (x->title().isEmpty()) return;
975   if (!m_firstCol) m_t << endl;
976   m_t << ".RE" << endl;
977   m_t << ".PP" << endl;
978   m_firstCol=TRUE;
979 }
980
981 void ManDocVisitor::visitPre(DocInternalRef *)
982 {
983   if (m_hide) return;
984   m_t << "\\fB";
985 }
986
987 void ManDocVisitor::visitPost(DocInternalRef *) 
988 {
989   if (m_hide) return;
990   m_t << "\\fP";
991 }
992
993 void ManDocVisitor::visitPre(DocCopy *)
994 {
995 }
996
997 void ManDocVisitor::visitPost(DocCopy *)
998 {
999 }
1000
1001 void ManDocVisitor::visitPre(DocText *)
1002 {
1003 }
1004
1005 void ManDocVisitor::visitPost(DocText *)
1006 {
1007 }
1008
1009 void ManDocVisitor::visitPre(DocHtmlBlockQuote *)
1010 {
1011   if (m_hide) return;
1012   if (!m_firstCol)
1013   { 
1014     m_t << endl;
1015     m_t << ".PP" << endl;
1016   }
1017   m_t << ".RS 4" << endl; // TODO: add support for nested block quotes
1018 }
1019
1020 void ManDocVisitor::visitPost(DocHtmlBlockQuote *)
1021 {
1022   if (m_hide) return;
1023   if (!m_firstCol) m_t << endl;
1024   m_t << ".RE" << endl;
1025   m_t << ".PP" << endl;
1026   m_firstCol=TRUE;
1027 }
1028
1029 void ManDocVisitor::visitPre(DocVhdlFlow *)
1030 {
1031 }
1032
1033 void ManDocVisitor::visitPost(DocVhdlFlow *)
1034 {
1035 }
1036
1037 void ManDocVisitor::visitPre(DocParBlock *)
1038 {
1039 }
1040
1041 void ManDocVisitor::visitPost(DocParBlock *)
1042 {
1043 }
1044
1045
1046 void ManDocVisitor::filter(const char *str)
1047
1048   if (str)
1049   {
1050     const char *p=str;
1051     char c=0;
1052     while ((c=*p++)) 
1053     {
1054       switch(c)
1055       {
1056         case '.':  m_t << "\\&."; break; // see  bug652277
1057         case '\\': m_t << "\\\\"; break;
1058         case '"':  c = '\''; // fall through
1059         default: m_t << c; break;
1060       }
1061     }
1062   }
1063 }
1064
1065 void ManDocVisitor::pushEnabled()
1066 {
1067   m_enabled.push(new bool(m_hide));
1068 }
1069
1070 void ManDocVisitor::popEnabled()
1071 {
1072   bool *v=m_enabled.pop();
1073   ASSERT(v!=0);
1074   m_hide = *v;
1075   delete v;
1076 }
1077