ab10da05c14cfb2c65bb6be3768301e11f104fc6
[platform/upstream/doxygen.git] / src / docbookvisitor.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 "docbookvisitor.h"
22 #include "docparser.h"
23 #include "language.h"
24 #include "doxygen.h"
25 #include "outputgen.h"
26 #include "docbookgen.h"
27 #include "dot.h"
28 #include "message.h"
29 #include "util.h"
30 #include "parserintf.h"
31 #include "filename.h"
32 #include "config.h"
33 #include "filedef.h"
34 #include "msc.h"
35 #include "dia.h"
36 #include "htmlentity.h"
37 #include "plantuml.h"
38
39 static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name,  QCString width,  QCString height)
40 {
41   QCString tmpStr;
42   t << "    <figure>" << endl;
43   t << "        <title></title>" << endl;
44   t << "        <mediaobject>" << endl;
45   t << "            <imageobject>" << endl;
46   t << "                <imagedata";
47   if (!width.isEmpty())
48   {
49     t << " width=\"" << convertToXML(width) << "\"";
50   }
51   else
52   {
53     t << " width=\"50%\"";
54   }
55   if (!height.isEmpty())
56   {
57     t << " depth=\"" << convertToXML(tmpStr) << "\"";
58   }
59   t << " align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << name << "\">";
60   t << "</imagedata>" << endl;
61   t << "            </imageobject>" << endl;
62   if (hasCaption)
63   {
64     t << "        <caption>" << endl;
65   }
66 }
67
68 static void visitPostEnd(FTextStream &t, const bool hasCaption)
69 {
70   t << endl;
71   if (hasCaption)
72   {
73     t << "        </caption>" << endl;
74   }
75   t << "        </mediaobject>" << endl;
76   t << "    </figure>" << endl;
77 }
78
79 static void visitCaption(DocbookDocVisitor *parent, QList<DocNode> children)
80 {
81   QListIterator<DocNode> cli(children);
82   DocNode *n;
83   for (cli.toFirst();(n=cli.current());++cli) n->accept(parent);
84 }
85
86 DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci)
87   : DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE)
88 {
89 }
90
91 //--------------------------------------
92 // visitor functions for leaf nodes
93 //--------------------------------------
94
95 void DocbookDocVisitor::visit(DocWord *w)
96 {
97   if (m_hide) return;
98   filter(w->word());
99 }
100
101 void DocbookDocVisitor::visit(DocLinkedWord *w)
102 {
103   if (m_hide) return;
104   startLink(w->file(),w->anchor());
105   filter(w->word());
106   endLink();
107 }
108
109 void DocbookDocVisitor::visit(DocWhiteSpace *w)
110 {
111   if (m_hide) return;
112   if (m_insidePre)
113   {
114     m_t << w->chars();
115   }
116   else
117   {
118     m_t << " ";
119   }
120 }
121
122 void DocbookDocVisitor::visit(DocSymbol *s)
123 {
124   if (m_hide) return;
125   const char *res = HtmlEntityMapper::instance()->docbook(s->symbol());
126   if (res)
127   {
128     m_t << res;
129   }
130   else
131   {
132     err("DocBook: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
133   }
134 }
135
136 void DocbookDocVisitor::visit(DocURL *u)
137 {
138   if (m_hide) return;
139   m_t << "<link xlink:href=\"";
140   if (u->isEmail()) m_t << "mailto:";
141   filter(u->url());
142   m_t << "\">";
143   filter(u->url());
144   m_t << "</link>";
145 }
146
147 void DocbookDocVisitor::visit(DocLineBreak *)
148 {
149   if (m_hide) return;
150   m_t << endl << "<literallayout>\n</literallayout>" << endl;
151 }
152
153 void DocbookDocVisitor::visit(DocHorRuler *)
154 {
155   if (m_hide) return;
156   m_t << "<informaltable frame='bottom'><tgroup cols='1'><colspec align='center'/><tbody><row><entry align='center'>\n";
157   m_t << "</entry></row></tbody></tgroup></informaltable>\n";
158 }
159
160 void DocbookDocVisitor::visit(DocStyleChange *s)
161 {
162   if (m_hide) return;
163   switch (s->style())
164   {
165     case DocStyleChange::Bold:
166       if (s->enable()) m_t << "<emphasis role=\"bold\">";      else m_t << "</emphasis>";
167       break;
168     case DocStyleChange::Italic:
169       if (s->enable()) m_t << "<emphasis>";     else m_t << "</emphasis>";
170       break;
171     case DocStyleChange::Code:
172       if (s->enable()) m_t << "<computeroutput>";   else m_t << "</computeroutput>";
173       break;
174     case DocStyleChange::Subscript:
175       if (s->enable()) m_t << "<subscript>";    else m_t << "</subscript>";
176       break;
177     case DocStyleChange::Superscript:
178       if (s->enable()) m_t << "<superscript>";    else m_t << "</superscript>";
179       break;
180     case DocStyleChange::Center:
181       if (s->enable()) m_t << "<informaltable frame='none'><tgroup cols='1'><colspec align='center'/><tbody><row><entry align='center'>";
182       else m_t << "</entry></row></tbody></tgroup></informaltable>";
183       break;
184     case DocStyleChange::Preformatted:
185       if (s->enable())
186       {
187         m_t << "<literallayout>";
188         m_insidePre=TRUE;
189       }
190       else
191       {
192         m_t << "</literallayout>";
193         m_insidePre=FALSE;
194       }
195       break;
196       /* There is no equivalent Docbook tag for rendering Small text */
197     case DocStyleChange::Small: /* XSLT Stylesheets can be used */ break;
198                                                                    /* HTML only */
199     case DocStyleChange::Div:  /* HTML only */ break;
200     case DocStyleChange::Span: /* HTML only */ break;
201   }
202 }
203
204 void DocbookDocVisitor::visit(DocVerbatim *s)
205 {
206   if (m_hide) return;
207   SrcLangExt langExt = getLanguageFromFileName(m_langExt);
208   switch(s->type())
209   {
210     case DocVerbatim::Code: // fall though
211       m_t << "<literallayout><computeroutput>";
212       Doxygen::parserManager->getParser(m_langExt)
213         ->parseCode(m_ci,s->context(),s->text(),langExt,
214             s->isExample(),s->exampleFile());
215       m_t << "</computeroutput></literallayout>";
216       break;
217     case DocVerbatim::Verbatim:
218       m_t << "<literallayout>";
219       filter(s->text());
220       m_t << "</literallayout>";
221       break;
222     case DocVerbatim::HtmlOnly:    
223       break;
224     case DocVerbatim::RtfOnly:     
225       break;
226     case DocVerbatim::ManOnly:     
227       break;
228     case DocVerbatim::LatexOnly:   
229       break;
230     case DocVerbatim::XmlOnly:     
231       break;
232     case DocVerbatim::DocbookOnly: 
233       break;
234       m_t << s->text();
235       break;
236     case DocVerbatim::Dot:
237       {
238         static int dotindex = 1;
239         QCString baseName(4096);
240         QCString name;
241         QCString stext = s->text();
242         m_t << "<para>" << endl;
243         name.sprintf("%s%d", "dot_inline_dotgraph_", dotindex);
244         baseName.sprintf("%s%d",
245             (Config_getString(DOCBOOK_OUTPUT)+"/inline_dotgraph_").data(),
246             dotindex++
247             );
248         QFile file(baseName+".dot");
249         if (!file.open(IO_WriteOnly))
250         {
251           err("Could not open file %s.msc for writing\n",baseName.data());
252         }
253         file.writeBlock( stext, stext.length() );
254         file.close();
255         writeDotFile(baseName, s);
256         m_t << "</para>" << endl;
257       }
258       break;
259     case DocVerbatim::Msc:
260       {
261         static int mscindex = 1;
262         QCString baseName(4096);
263         QCString name;
264         QCString stext = s->text();
265         m_t << "<para>" << endl;
266         name.sprintf("%s%d", "msc_inline_mscgraph_", mscindex);
267         baseName.sprintf("%s%d",
268             (Config_getString(DOCBOOK_OUTPUT)+"/inline_mscgraph_").data(),
269             mscindex++
270             );
271         QFile file(baseName+".msc");
272         if (!file.open(IO_WriteOnly))
273         {
274           err("Could not open file %s.msc for writing\n",baseName.data());
275         }
276         QCString text = "msc {";
277         text+=stext;
278         text+="}";
279         file.writeBlock( text, text.length() );
280         file.close();
281         writeMscFile(baseName,s);
282         m_t << "</para>" << endl;
283       }
284       break;
285     case DocVerbatim::PlantUML:
286       {
287         static QCString docbookOutput = Config_getString(DOCBOOK_OUTPUT);
288         QCString baseName = writePlantUMLSource(docbookOutput,s->exampleFile(),s->text());
289         QCString shortName = baseName;
290         int i;
291         if ((i=shortName.findRev('/'))!=-1)
292         {
293           shortName=shortName.right(shortName.length()-i-1);
294         }
295         m_t << "<para>" << endl;
296         writePlantUMLFile(baseName,s);
297         m_t << "</para>" << endl;
298       }
299       break;
300   }
301 }
302
303 void DocbookDocVisitor::visit(DocAnchor *anc)
304 {
305   if (m_hide) return;
306   m_t << "<anchor id=\"" << anc->file() << "_1" << anc->anchor() << "\"/>";
307 }
308
309 void DocbookDocVisitor::visit(DocInclude *inc)
310 {
311   if (m_hide) return;
312   SrcLangExt langExt = getLanguageFromFileName(inc->extension());
313   switch(inc->type())
314   {
315     case DocInclude::IncWithLines:
316       {
317         m_t << "<literallayout><computeroutput>";
318         QFileInfo cfi( inc->file() );
319         FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
320         Doxygen::parserManager->getParser(inc->extension())
321           ->parseCode(m_ci,inc->context(),
322               inc->text(),
323               langExt,
324               inc->isExample(),
325               inc->exampleFile(), &fd);
326         m_t << "</computeroutput></literallayout>";
327       }
328       break;
329     case DocInclude::Include:
330       m_t << "<literallayout><computeroutput>";
331       Doxygen::parserManager->getParser(inc->extension())
332         ->parseCode(m_ci,inc->context(),
333             inc->text(),
334             langExt,
335             inc->isExample(),
336             inc->exampleFile());
337       m_t << "</computeroutput></literallayout>";
338       break;
339     case DocInclude::DontInclude:
340       break;
341     case DocInclude::HtmlInclude:
342       break;
343     case DocInclude::LatexInclude:
344       break;
345     case DocInclude::VerbInclude:
346       m_t << "<verbatim>";
347       filter(inc->text());
348       m_t << "</verbatim>";
349       break;
350     case DocInclude::Snippet:
351       m_t << "<literallayout><computeroutput>";
352       Doxygen::parserManager->getParser(inc->extension())
353         ->parseCode(m_ci,
354             inc->context(),
355             extractBlock(inc->text(),inc->blockId()),
356             langExt,
357             inc->isExample(),
358             inc->exampleFile()
359             );
360       m_t << "</computeroutput></literallayout>";
361       break;
362     case DocInclude::SnipWithLines:
363       {
364          QFileInfo cfi( inc->file() );
365          FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
366          m_t << "<literallayout><computeroutput>";
367          Doxygen::parserManager->getParser(inc->extension())
368                                ->parseCode(m_ci,
369                                            inc->context(),
370                                            extractBlock(inc->text(),inc->blockId()),
371                                            langExt,
372                                            inc->isExample(),
373                                            inc->exampleFile(), 
374                                            &fd,
375                                            lineBlock(inc->text(),inc->blockId()),
376                                            -1,    // endLine
377                                            FALSE, // inlineFragment
378                                            0,     // memberDef
379                                            TRUE   // show line number
380                                           );
381          m_t << "</computeroutput></literallayout>";
382       }
383       break;
384     case DocInclude::SnippetDoc: 
385     case DocInclude::IncludeDoc: 
386       err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
387           "Please create a bug report\n",__FILE__);
388       break;
389   }
390 }
391
392 void DocbookDocVisitor::visit(DocIncOperator *op)
393 {
394   if (op->isFirst())
395   {
396     if (!m_hide)
397     {
398       m_t << "<programlisting>";
399     }
400     pushEnabled();
401     m_hide = TRUE;
402   }
403   SrcLangExt langExt = getLanguageFromFileName(m_langExt);
404   if (op->type()!=DocIncOperator::Skip)
405   {
406     popEnabled();
407     if (!m_hide)
408     {
409       Doxygen::parserManager->getParser(m_langExt)
410         ->parseCode(m_ci,op->context(),
411             op->text(),langExt,op->isExample(),
412             op->exampleFile());
413     }
414     pushEnabled();
415     m_hide=TRUE;
416   }
417   if (op->isLast())
418   {
419     popEnabled();
420     if (!m_hide) m_t << "</programlisting>";
421   }
422   else
423   {
424     if (!m_hide) m_t << endl;
425   }
426 }
427
428 void DocbookDocVisitor::visit(DocFormula *f)
429 {
430   if (m_hide) return;
431   m_t << "<equation><title>" << f->name() << "</title>";
432   filter(f->text());
433   m_t << "</equation>";
434 }
435
436 void DocbookDocVisitor::visit(DocIndexEntry *ie)
437 {
438   if (m_hide) return;
439   m_t << "<indexentry><primaryie>" << endl;
440   filter(ie->entry());
441   m_t << "</primaryie><secondaryie></secondaryie></indexentry>" << endl;
442 }
443
444 void DocbookDocVisitor::visit(DocSimpleSectSep *)
445 {
446   m_t << "<simplesect/>";
447 }
448
449 void DocbookDocVisitor::visit(DocCite *cite)
450 {
451   if (m_hide) return;
452   if (!cite->file().isEmpty()) startLink(cite->file(),cite->anchor());
453   filter(cite->text());
454   if (!cite->file().isEmpty()) endLink();
455 }
456
457 //--------------------------------------
458 // visitor functions for compound nodes
459 //--------------------------------------
460
461 void DocbookDocVisitor::visitPre(DocAutoList *l)
462 {
463   if (m_hide) return;
464   if (l->isEnumList())
465   {
466     m_t << "<orderedlist>\n";
467   }
468   else
469   {
470     m_t << "<itemizedlist>\n";
471   }
472 }
473
474 void DocbookDocVisitor::visitPost(DocAutoList *l)
475 {
476   if (m_hide) return;
477   if (l->isEnumList())
478   {
479     m_t << "</orderedlist>\n";
480   }
481   else
482   {
483     m_t << "</itemizedlist>\n";
484   }
485 }
486
487 void DocbookDocVisitor::visitPre(DocAutoListItem *)
488 {
489   if (m_hide) return;
490   m_t << "<listitem>";
491 }
492
493 void DocbookDocVisitor::visitPost(DocAutoListItem *)
494 {
495   if (m_hide) return;
496   m_t << "</listitem>";
497 }
498
499 void DocbookDocVisitor::visitPre(DocPara *)
500 {
501   if (m_hide) return;
502   m_t << endl;
503   m_t << "<para>";
504 }
505
506 void DocbookDocVisitor::visitPost(DocPara *)
507 {
508   if (m_hide) return;
509   m_t << "</para>";
510   m_t << endl;
511 }
512
513 void DocbookDocVisitor::visitPre(DocRoot *)
514 {
515   //m_t << "<hr><h4><font color=\"red\">New parser:</font></h4>\n";
516 }
517
518 void DocbookDocVisitor::visitPost(DocRoot *)
519 {
520   //m_t << "<hr><h4><font color=\"red\">Old parser:</font></h4>\n";
521 }
522
523 void DocbookDocVisitor::visitPre(DocSimpleSect *s)
524 {
525   if (m_hide) return;
526   switch(s->type())
527   {
528     case DocSimpleSect::See:
529       if (m_insidePre) 
530       {
531         m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << ": </title>" << endl;
532       } 
533       else 
534       {
535         m_t << "<formalpara><title>" << convertToXML(theTranslator->trSeeAlso()) << ": </title>" << endl;
536       }
537       break;
538     case DocSimpleSect::Return:
539       if (m_insidePre) 
540       {
541         m_t << "<formalpara><title>" << theTranslator->trReturns()<< ": </title>" << endl;
542       } 
543       else 
544       {
545         m_t << "<formalpara><title>" << convertToXML(theTranslator->trReturns()) << ": </title>" << endl;
546       }
547       break;
548     case DocSimpleSect::Author:
549       if (m_insidePre) 
550       {
551         m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << ": </title>" << endl;
552       } 
553       else 
554       {
555         m_t << "<formalpara><title>" << convertToXML(theTranslator->trAuthor(TRUE, TRUE)) << ": </title>" << endl;
556       }
557       break;
558     case DocSimpleSect::Authors:
559       if (m_insidePre) 
560       {
561         m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << ": </title>" << endl;
562       } 
563       else 
564       {
565         m_t << "<formalpara><title>" << convertToXML(theTranslator->trAuthor(TRUE, FALSE)) << ": </title>" << endl;
566       }
567       break;
568     case DocSimpleSect::Version:
569       if (m_insidePre) 
570       {
571         m_t << "<formalpara><title>" << theTranslator->trVersion() << ": </title>" << endl;
572       } 
573       else 
574       {
575         m_t << "<formalpara><title>" << convertToXML(theTranslator->trVersion()) << ": </title>" << endl;
576       }
577       break;
578     case DocSimpleSect::Since:
579       if (m_insidePre) 
580       {
581         m_t << "<formalpara><title>" << theTranslator->trSince() << ": </title>" << endl;
582       } 
583       else 
584       {
585         m_t << "<formalpara><title>" << convertToXML(theTranslator->trSince()) << ": </title>" << endl;
586       }
587       break;
588     case DocSimpleSect::Date:
589       if (m_insidePre) 
590       {
591         m_t << "<formalpara><title>" << theTranslator->trDate() << ": </title>" << endl;
592       } 
593       else 
594       {
595         m_t << "<formalpara><title>" << convertToXML(theTranslator->trDate()) << ": </title>" << endl;
596       }
597       break;
598     case DocSimpleSect::Note:
599       if (m_insidePre) 
600       {
601         m_t << "<formalpara><title>" << theTranslator->trNote() << ": </title>" << endl;
602       } 
603       else 
604       {
605         m_t << "<formalpara><title>" << convertToXML(theTranslator->trNote()) << ": </title>" << endl;
606       }
607       break;
608     case DocSimpleSect::Warning:
609       if (m_insidePre) 
610       {
611         m_t << "<formalpara><title>" << theTranslator->trWarning() << ": </title>" << endl;
612       } 
613       else 
614       {
615         m_t << "<formalpara><title>" << convertToXML(theTranslator->trWarning()) << ": </title>" << endl;
616       }
617       break;
618     case DocSimpleSect::Pre:
619       if (m_insidePre) 
620       {
621         m_t << "<formalpara><title>" << theTranslator->trPrecondition() << ": </title>" << endl;
622       } 
623       else 
624       {
625         m_t << "<formalpara><title>" << convertToXML(theTranslator->trPrecondition()) << ": </title>" << endl;
626       }
627       break;
628     case DocSimpleSect::Post:
629       if (m_insidePre) 
630       {
631         m_t << "<formalpara><title>" << theTranslator->trPostcondition() << ": </title>" << endl;
632       } 
633       else 
634       {
635         m_t << "<formalpara><title>" << convertToXML(theTranslator->trPostcondition()) << ": </title>" << endl;
636       }
637       break;
638     case DocSimpleSect::Copyright:
639       if (m_insidePre) 
640       {
641         m_t << "<formalpara><title>" << theTranslator->trCopyright() << ": </title>" << endl;
642       } 
643       else 
644       {
645         m_t << "<formalpara><title>" << convertToXML(theTranslator->trCopyright()) << ": </title>" << endl;
646       }
647       break;
648     case DocSimpleSect::Invar:
649       if (m_insidePre) 
650       {
651         m_t << "<formalpara><title>" << theTranslator->trInvariant() << ": </title>" << endl;
652       } 
653       else 
654       {
655         m_t << "<formalpara><title>" << convertToXML(theTranslator->trInvariant()) << ": </title>" << endl;
656       }
657       break;
658     case DocSimpleSect::Remark:
659       if (m_insidePre) 
660       {
661         m_t << "<formalpara><title>" << theTranslator->trRemarks() << ": </title>" << endl;
662       } 
663       else 
664       {
665         m_t << "<formalpara><title>" << convertToXML(theTranslator->trRemarks()) << ": </title>" << endl;
666       }
667       break;
668     case DocSimpleSect::Attention:
669       if (m_insidePre) 
670       {
671         m_t << "<formalpara><title>" << theTranslator->trAttention() << ": </title>" << endl;
672       } 
673       else 
674       {
675         m_t << "<formalpara><title>" << convertToXML(theTranslator->trAttention()) << ": </title>" << endl;
676       }
677       break;
678     case DocSimpleSect::User:
679       m_t << "<formalpara><title></title>" << endl;
680       break;
681     case DocSimpleSect::Rcs:
682       m_t << "<formalpara><title></title>" << endl;
683       break;
684     case DocSimpleSect::Unknown: m_t << "<formalpara><title></title>" << endl; break;
685   }
686 }
687
688 void DocbookDocVisitor::visitPost(DocSimpleSect *)
689 {
690   if (m_hide) return;
691   m_t << "</formalpara>" << endl;
692 }
693
694 void DocbookDocVisitor::visitPre(DocTitle *)
695 {
696   if (m_hide) return;
697   m_t << "<title>";
698 }
699
700 void DocbookDocVisitor::visitPost(DocTitle *)
701 {
702   if (m_hide) return;
703   m_t << "</title>";
704 }
705
706 void DocbookDocVisitor::visitPre(DocSimpleList *)
707 {
708   if (m_hide) return;
709   m_t << "<itemizedlist>\n";
710 }
711
712 void DocbookDocVisitor::visitPost(DocSimpleList *)
713 {
714   if (m_hide) return;
715   m_t << "</itemizedlist>\n";
716 }
717
718 void DocbookDocVisitor::visitPre(DocSimpleListItem *)
719 {
720   if (m_hide) return;
721   m_t << "<listitem>";
722 }
723
724 void DocbookDocVisitor::visitPost(DocSimpleListItem *)
725 {
726   if (m_hide) return;
727   m_t << "</listitem>\n";
728 }
729
730 void DocbookDocVisitor::visitPre(DocSection *s)
731 {
732   if (m_hide) return;
733   m_t << "<section xml:id=\"" << s->file();
734   if (!s->anchor().isEmpty()) m_t << "_1" << s->anchor();
735   m_t << "\">" << endl;
736   m_t << "<title>";
737   filter(s->title());
738   m_t << "</title>" << endl;
739 }
740
741 void DocbookDocVisitor::visitPost(DocSection *)
742 {
743   m_t << "</section>\n";
744 }
745
746 void DocbookDocVisitor::visitPre(DocHtmlList *s)
747 {
748   if (m_hide) return;
749   if (s->type()==DocHtmlList::Ordered)
750     m_t << "<orderedlist>\n";
751   else
752     m_t << "<itemizedlist>\n";
753 }
754
755 void DocbookDocVisitor::visitPost(DocHtmlList *s)
756 {
757   if (m_hide) return;
758   if (s->type()==DocHtmlList::Ordered)
759     m_t << "</orderedlist>\n";
760   else
761     m_t << "</itemizedlist>\n";
762 }
763
764 void DocbookDocVisitor::visitPre(DocHtmlListItem *)
765 {
766   if (m_hide) return;
767   m_t << "<listitem>\n";
768 }
769
770 void DocbookDocVisitor::visitPost(DocHtmlListItem *)
771 {
772   if (m_hide) return;
773   m_t << "</listitem>\n";
774 }
775
776 void DocbookDocVisitor::visitPre(DocHtmlDescList *)
777 {
778   if (m_hide) return;
779   m_t << "<variablelist>\n";
780 }
781
782 void DocbookDocVisitor::visitPost(DocHtmlDescList *)
783 {
784   if (m_hide) return;
785   m_t << "</variablelist>\n";
786 }
787
788 void DocbookDocVisitor::visitPre(DocHtmlDescTitle *)
789 {
790   if (m_hide) return;
791   m_t << "<varlistentry><term>";
792 }
793
794 void DocbookDocVisitor::visitPost(DocHtmlDescTitle *)
795 {
796   if (m_hide) return;
797   m_t << "</term>\n";
798 }
799
800 void DocbookDocVisitor::visitPre(DocHtmlDescData *)
801 {
802   if (m_hide) return;
803   m_t << "<listitem>";
804 }
805
806 void DocbookDocVisitor::visitPost(DocHtmlDescData *)
807 {
808   if (m_hide) return;
809   m_t << "</listitem></varlistentry>\n";
810 }
811
812 void DocbookDocVisitor::visitPre(DocHtmlTable *t)
813 {
814   if (m_hide) return;
815   m_t << "<table frame=\"all\">" << endl;
816   m_t << "    <title></title>" << endl;
817   m_t << "    <tgroup cols=\"" << t->numColumns() << "\" align=\"left\" colsep=\"1\" rowsep=\"1\">" << endl;
818   m_t << "    <tbody>" << endl;
819 }
820
821 void DocbookDocVisitor::visitPost(DocHtmlTable *)
822 {
823   if (m_hide) return;
824   m_t << "    </tbody>" << endl;
825   m_t << "    </tgroup>" << endl;
826   m_t << "</table>" << endl;
827 }
828
829 void DocbookDocVisitor::visitPre(DocHtmlRow *)
830 {
831   if (m_hide) return;
832   m_t << "<row>\n";
833 }
834
835 void DocbookDocVisitor::visitPost(DocHtmlRow *)
836 {
837   if (m_hide) return;
838   m_t << "</row>\n";
839 }
840
841 void DocbookDocVisitor::visitPre(DocHtmlCell *)
842 {
843   if (m_hide) return;
844   m_t << "<entry>";
845 }
846
847 void DocbookDocVisitor::visitPost(DocHtmlCell *)
848 {
849   if (m_hide) return;
850   m_t << "</entry>";
851 }
852
853 void DocbookDocVisitor::visitPre(DocHtmlCaption *)
854 {
855   if (m_hide) return;
856   m_t << "<caption>";
857 }
858
859 void DocbookDocVisitor::visitPost(DocHtmlCaption *)
860 {
861   if (m_hide) return;
862   m_t << "</caption>\n";
863 }
864
865 void DocbookDocVisitor::visitPre(DocInternal *)
866 {
867   if (m_hide) return;
868   // TODO: to be implemented
869 }
870
871 void DocbookDocVisitor::visitPost(DocInternal *)
872 {
873   if (m_hide) return;
874   // TODO: to be implemented
875 }
876
877 void DocbookDocVisitor::visitPre(DocHRef *href)
878 {
879   if (m_hide) return;
880   m_t << "<link xlink:href=\"" << href->url() << "\">";
881 }
882
883 void DocbookDocVisitor::visitPost(DocHRef *)
884 {
885   if (m_hide) return;
886   m_t << "</link>";
887 }
888
889 void DocbookDocVisitor::visitPre(DocHtmlHeader *)
890 {
891   if (m_hide) return;
892   m_t << "<formalpara><title>";
893 }
894
895 void DocbookDocVisitor::visitPost(DocHtmlHeader *)
896 {
897   if (m_hide) return;
898   m_t << "</title></formalpara>\n";
899 }
900
901 void DocbookDocVisitor::visitPre(DocImage *img)
902 {
903   if (img->type()==DocImage::DocBook)
904   {
905     if (m_hide) return;
906     m_t << endl;
907     QCString baseName=img->name();
908     int i;
909     if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
910     {
911       baseName=baseName.right(baseName.length()-i-1);
912     }
913     visitPreStart(m_t, img -> hasCaption(), baseName, img -> width(), img -> height());
914   }
915   else
916   {
917     pushEnabled();
918     m_hide=TRUE;
919   }
920 }
921
922 void DocbookDocVisitor::visitPost(DocImage *img)
923 {
924   if (img->type()==DocImage::DocBook)
925   {
926     if (m_hide) return;
927     visitPostEnd(m_t, img -> hasCaption());
928     // copy the image to the output dir
929     QCString baseName=img->name();
930     int i;
931     if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
932     {
933       baseName=baseName.right(baseName.length()-i-1);
934     }
935     QCString m_file;
936     bool ambig;
937     FileDef *fd=findFileDef(Doxygen::imageNameDict, baseName, ambig);
938     if (fd) 
939     {
940       m_file=fd->absFilePath();
941     }
942     QFile inImage(m_file);
943     QFile outImage(Config_getString(DOCBOOK_OUTPUT)+"/"+baseName.data());
944     if (inImage.open(IO_ReadOnly))
945     {
946       if (outImage.open(IO_WriteOnly))
947       {
948         char *buffer = new char[inImage.size()];
949         inImage.readBlock(buffer,inImage.size());
950         outImage.writeBlock(buffer,inImage.size());
951         outImage.flush();
952         delete[] buffer;
953       }
954     }
955   } 
956   else 
957   {
958     popEnabled();
959   }
960 }
961
962 void DocbookDocVisitor::visitPre(DocDotFile *df)
963 {
964   if (m_hide) return;
965   startDotFile(df->file(),df->width(),df->height(),df->hasCaption());
966 }
967
968 void DocbookDocVisitor::visitPost(DocDotFile *df)
969 {
970   if (m_hide) return;
971   endDotFile(df->hasCaption());
972 }
973
974 void DocbookDocVisitor::visitPre(DocMscFile *df)
975 {
976   if (m_hide) return;
977   startMscFile(df->file(),df->width(),df->height(),df->hasCaption());
978 }
979
980 void DocbookDocVisitor::visitPost(DocMscFile *df)
981 {
982   if (m_hide) return;
983   endMscFile(df->hasCaption());
984 }
985 void DocbookDocVisitor::visitPre(DocDiaFile *df)
986 {
987   if (m_hide) return;
988   startDiaFile(df->file(),df->width(),df->height(),df->hasCaption());
989 }
990
991 void DocbookDocVisitor::visitPost(DocDiaFile *df)
992 {
993   if (m_hide) return;
994   endDiaFile(df->hasCaption());
995 }
996
997 void DocbookDocVisitor::visitPre(DocLink *lnk)
998 {
999   if (m_hide) return;
1000   startLink(lnk->file(),lnk->anchor());
1001 }
1002
1003 void DocbookDocVisitor::visitPost(DocLink *)
1004 {
1005   if (m_hide) return;
1006   endLink();
1007 }
1008
1009 void DocbookDocVisitor::visitPre(DocRef *ref)
1010 {
1011   if (m_hide) return;
1012   if (!ref->file().isEmpty()) startLink(ref->file(),ref->anchor());
1013   if (!ref->hasLinkText()) filter(ref->targetTitle());
1014 }
1015
1016 void DocbookDocVisitor::visitPost(DocRef *ref)
1017 {
1018   if (m_hide) return;
1019   if (!ref->file().isEmpty()) endLink();
1020 }
1021
1022 void DocbookDocVisitor::visitPre(DocSecRefItem *ref)
1023 {
1024   if (m_hide) return;
1025   m_t << "<tocitem id=\"" << ref->file() << "_1" << ref->anchor() << "\">";
1026 }
1027
1028 void DocbookDocVisitor::visitPost(DocSecRefItem *)
1029 {
1030   if (m_hide) return;
1031   m_t << "</tocitem>" << endl;
1032 }
1033
1034 void DocbookDocVisitor::visitPre(DocSecRefList *)
1035 {
1036   if (m_hide) return;
1037   m_t << "<toclist>" << endl;
1038 }
1039
1040 void DocbookDocVisitor::visitPost(DocSecRefList *)
1041 {
1042   if (m_hide) return;
1043   m_t << "</toclist>" << endl;
1044 }
1045
1046 void DocbookDocVisitor::visitPre(DocParamSect *s)
1047 {
1048   if (m_hide) return;
1049   m_t <<  endl;
1050   m_t << "                <formalpara>" << endl;
1051   m_t << "                    <title/>" << endl;
1052   m_t << "                    <table frame=\"all\">" << endl;
1053   m_t << "                        <title>";
1054   switch(s->type())
1055   {
1056     case DocParamSect::Param:         m_t << theTranslator->trParameters();         break;
1057     case DocParamSect::RetVal:        m_t << theTranslator->trReturnValues();       break;
1058     case DocParamSect::Exception:     m_t << theTranslator->trExceptions();         break;
1059     case DocParamSect::TemplateParam: m_t << theTranslator->trTemplateParameters(); break;
1060     default:
1061       ASSERT(0);
1062   }
1063   m_t << "                        </title>" << endl;
1064   m_t << "                        <tgroup cols=\"2\" align=\"left\" colsep=\"1\" rowsep=\"1\">" << endl;
1065   m_t << "                        <colspec colwidth=\"1*\"/>" << endl;
1066   m_t << "                        <colspec colwidth=\"4*\"/>" << endl;
1067   m_t << "                        <tbody>" << endl;
1068 }
1069
1070 void DocbookDocVisitor::visitPost(DocParamSect *)
1071 {
1072   if (m_hide) return;
1073   m_t << "                        </tbody>" << endl;
1074   m_t << "                        </tgroup>" << endl;
1075   m_t << "                    </table>" << endl;
1076   m_t << "                </formalpara>" << endl;
1077   m_t << "                ";
1078 }
1079
1080 void DocbookDocVisitor::visitPre(DocParamList *pl)
1081 {
1082   if (m_hide) return;
1083   QListIterator<DocNode> li(pl->parameters());
1084   DocNode *param;
1085   m_t << "                            <row>" << endl;
1086   if (!li.toFirst())
1087   {
1088     m_t << "                                <entry></entry>" << endl;
1089   }
1090   else
1091   {
1092     m_t << "                                <entry>";
1093     int cnt = 0;
1094     for (li.toFirst();(param=li.current());++li)
1095     {
1096       if (cnt)
1097       {
1098         m_t << ", ";
1099       }
1100       if (param->kind()==DocNode::Kind_Word)
1101       {
1102         visit((DocWord*)param);
1103       }
1104       else if (param->kind()==DocNode::Kind_LinkedWord)
1105       {
1106         visit((DocLinkedWord*)param);
1107       }
1108       cnt++;
1109     }
1110     m_t << "</entry>" << endl;
1111   }
1112   m_t << "                                <entry>";
1113 }
1114
1115 void DocbookDocVisitor::visitPost(DocParamList *)
1116 {
1117   if (m_hide) return;
1118   m_t << "</entry>" << endl;
1119   m_t << "                            </row>" << endl;
1120 }
1121
1122 void DocbookDocVisitor::visitPre(DocXRefItem *x)
1123 {
1124   if (m_hide) return;
1125   if (x->title().isEmpty()) return;
1126   m_t << "<para><link linkend=\"";
1127   m_t << x->file() << "_1" << x->anchor();
1128   m_t << "\">";
1129   filter(x->title());
1130   m_t << "</link>";
1131   m_t << " ";
1132 }
1133
1134 void DocbookDocVisitor::visitPost(DocXRefItem *x)
1135 {
1136   if (m_hide) return;
1137   if (x->title().isEmpty()) return;
1138   m_t << "</para>";
1139 }
1140
1141 void DocbookDocVisitor::visitPre(DocInternalRef *ref)
1142 {
1143   if (m_hide) return;
1144   startLink(ref->file(),ref->anchor());
1145 }
1146
1147 void DocbookDocVisitor::visitPost(DocInternalRef *)
1148 {
1149   if (m_hide) return;
1150   endLink();
1151   m_t << " ";
1152 }
1153
1154 void DocbookDocVisitor::visitPre(DocCopy *)
1155 {
1156   if (m_hide) return;
1157   // TODO: to be implemented
1158 }
1159
1160
1161 void DocbookDocVisitor::visitPost(DocCopy *)
1162 {
1163   if (m_hide) return;
1164   // TODO: to be implemented
1165 }
1166
1167
1168 void DocbookDocVisitor::visitPre(DocText *)
1169 {
1170   // TODO: to be implemented
1171 }
1172
1173
1174 void DocbookDocVisitor::visitPost(DocText *)
1175 {
1176   // TODO: to be implemented
1177 }
1178
1179
1180 void DocbookDocVisitor::visitPre(DocHtmlBlockQuote *)
1181 {
1182   if (m_hide) return;
1183   m_t << "<blockquote>";
1184 }
1185
1186 void DocbookDocVisitor::visitPost(DocHtmlBlockQuote *)
1187 {
1188   if (m_hide) return;
1189   m_t << "</blockquote>";
1190 }
1191
1192 void DocbookDocVisitor::visitPre(DocVhdlFlow *)
1193 {
1194   // TODO: to be implemented
1195 }
1196
1197
1198 void DocbookDocVisitor::visitPost(DocVhdlFlow *)
1199 {
1200   // TODO: to be implemented
1201 }
1202
1203 void DocbookDocVisitor::visitPre(DocParBlock *)
1204 {
1205 }
1206
1207 void DocbookDocVisitor::visitPost(DocParBlock *)
1208 {
1209 }
1210
1211
1212 void DocbookDocVisitor::filter(const char *str)
1213 {
1214   m_t << convertToXML(str);
1215 }
1216
1217 void DocbookDocVisitor::startLink(const QCString &file,const QCString &anchor)
1218 {
1219   m_t << "<link linkend=\"" << file;
1220   if (!anchor.isEmpty()) m_t << "_1" << anchor;
1221   m_t << "\">";
1222 }
1223
1224 void DocbookDocVisitor::endLink()
1225 {
1226   m_t << "</link>";
1227 }
1228
1229 void DocbookDocVisitor::pushEnabled()
1230 {
1231   m_enabled.push(new bool(m_hide));
1232 }
1233
1234 void DocbookDocVisitor::popEnabled()
1235 {
1236   bool *v=m_enabled.pop();
1237   ASSERT(v!=0);
1238   m_hide = *v;
1239   delete v;
1240 }
1241
1242 void DocbookDocVisitor::writeMscFile(const QCString &baseName, DocVerbatim *s)
1243 {
1244   QCString shortName = baseName;
1245   int i;
1246   if ((i=shortName.findRev('/'))!=-1)
1247   {
1248     shortName=shortName.right(shortName.length()-i-1);
1249   }
1250   QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1251   writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_BITMAP);
1252   visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height());
1253   visitCaption(this, s->children());
1254   visitPostEnd(m_t, s->hasCaption());
1255 }
1256
1257 void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim *s)
1258 {
1259   QCString shortName = baseName;
1260   int i;
1261   if ((i=shortName.findRev('/'))!=-1)
1262   {
1263     shortName=shortName.right(shortName.length()-i-1);
1264   }
1265   QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1266   generatePlantUMLOutput(baseName,outDir,PUML_BITMAP);
1267   visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height());
1268   visitCaption(this, s->children());
1269   visitPostEnd(m_t, s->hasCaption());
1270 }
1271
1272 void DocbookDocVisitor::startMscFile(const QCString &fileName,
1273     const QCString &width,
1274     const QCString &height,
1275     bool hasCaption
1276     )
1277 {
1278   QCString baseName=fileName;
1279   int i;
1280   if ((i=baseName.findRev('/'))!=-1)
1281   {
1282     baseName=baseName.right(baseName.length()-i-1);
1283   }
1284   if ((i=baseName.find('.'))!=-1)
1285   {
1286     baseName=baseName.left(i);
1287   }
1288   baseName.prepend("msc_");
1289   QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1290   writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP);
1291   m_t << "<para>" << endl;
1292   visitPreStart(m_t, hasCaption, baseName + ".png",  width,  height);
1293 }
1294
1295 void DocbookDocVisitor::endMscFile(bool hasCaption)
1296 {
1297   if (m_hide) return;
1298   visitPostEnd(m_t, hasCaption);
1299   m_t << "</para>" << endl;
1300 }
1301
1302 void DocbookDocVisitor::writeDiaFile(const QCString &baseName, DocVerbatim *s)
1303 {
1304   QCString shortName = baseName;
1305   int i;
1306   if ((i=shortName.findRev('/'))!=-1)
1307   {
1308     shortName=shortName.right(shortName.length()-i-1);
1309   }
1310   QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1311   writeDiaGraphFromFile(baseName+".dia",outDir,shortName,DIA_BITMAP);
1312   visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height());
1313   visitCaption(this, s->children());
1314   visitPostEnd(m_t, s->hasCaption());
1315 }
1316
1317 void DocbookDocVisitor::startDiaFile(const QCString &fileName,
1318     const QCString &width,
1319     const QCString &height,
1320     bool hasCaption
1321     )
1322 {
1323   QCString baseName=fileName;
1324   int i;
1325   if ((i=baseName.findRev('/'))!=-1)
1326   {
1327     baseName=baseName.right(baseName.length()-i-1);
1328   }
1329   if ((i=baseName.find('.'))!=-1)
1330   {
1331     baseName=baseName.left(i);
1332   }
1333   baseName.prepend("dia_");
1334   QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1335   writeDiaGraphFromFile(fileName,outDir,baseName,DIA_BITMAP);
1336   m_t << "<para>" << endl;
1337   visitPreStart(m_t, hasCaption, baseName + ".png",  width,  height);
1338 }
1339
1340 void DocbookDocVisitor::endDiaFile(bool hasCaption)
1341 {
1342   if (m_hide) return;
1343   visitPostEnd(m_t, hasCaption);
1344   m_t << "</para>" << endl;
1345 }
1346
1347 void DocbookDocVisitor::writeDotFile(const QCString &baseName, DocVerbatim *s)
1348 {
1349   QCString shortName = baseName;
1350   int i;
1351   if ((i=shortName.findRev('/'))!=-1)
1352   {
1353     shortName=shortName.right(shortName.length()-i-1);
1354   }
1355   QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1356   writeDotGraphFromFile(baseName+".dot",outDir,shortName,GOF_BITMAP);
1357   visitPreStart(m_t, s->hasCaption(), baseName + ".dot", s->width(),s->height());
1358   visitCaption(this, s->children());
1359   visitPostEnd(m_t, s->hasCaption());
1360 }
1361
1362 void DocbookDocVisitor::startDotFile(const QCString &fileName,
1363     const QCString &width,
1364     const QCString &height,
1365     bool hasCaption
1366     )
1367 {
1368   QCString baseName=fileName;
1369   int i;
1370   if ((i=baseName.findRev('/'))!=-1)
1371   {
1372     baseName=baseName.right(baseName.length()-i-1);
1373   }
1374   if ((i=baseName.find('.'))!=-1)
1375   {
1376     baseName=baseName.left(i);
1377   }
1378   baseName.prepend("dot_");
1379   QCString outDir = Config_getString(DOCBOOK_OUTPUT);
1380   QCString imgExt = getDotImageExtension();
1381   writeDotGraphFromFile(fileName,outDir,baseName,GOF_BITMAP);
1382   m_t << "<para>" << endl;
1383   visitPreStart(m_t, hasCaption, baseName + "." + imgExt,  width,  height);
1384 }
1385
1386 void DocbookDocVisitor::endDotFile(bool hasCaption)
1387 {
1388   if (m_hide) return;
1389   m_t << endl;
1390   visitPostEnd(m_t, hasCaption);
1391   m_t << "</para>" << endl;
1392 }
1393