Imported Upstream version 1.8.15
[platform/upstream/doxygen.git] / src / xmldocvisitor.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 "xmldocvisitor.h"
22 #include "docparser.h"
23 #include "language.h"
24 #include "doxygen.h"
25 #include "outputgen.h"
26 #include "xmlgen.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 "htmlentity.h"
34 #include "emoji.h"
35
36 static void visitCaption(XmlDocVisitor *parent, QList<DocNode> children)
37 {
38   QListIterator<DocNode> cli(children);
39   DocNode *n;
40   for (cli.toFirst();(n=cli.current());++cli) n->accept(parent);
41 }
42
43 static void visitPreStart(FTextStream &t, const char *cmd, bool doCaption, 
44                           XmlDocVisitor *parent, QList<DocNode> children, 
45                           const QCString &name, bool writeType, DocImage::Type type, const QCString &width, 
46                           const QCString &height, bool inlineImage = FALSE)
47 {
48   t << "<" << cmd;
49   if (writeType)
50   {
51     t << " type=\"";
52     switch(type)
53     {
54       case DocImage::Html:    t << "html"; break;
55       case DocImage::Latex:   t << "latex"; break;
56       case DocImage::Rtf:     t << "rtf"; break;
57       case DocImage::DocBook: t << "docbook"; break;
58     }
59     t << "\"";
60   }
61   if (!name.isEmpty())
62   {
63     t << " name=\"" << name << "\"";
64   }
65   if (!width.isEmpty())
66   {
67     t << " width=\"" << convertToXML(width) << "\"";
68   }
69   if (!height.isEmpty())
70   {
71     t << " height=\"" << convertToXML(height) << "\"";
72   }
73   if (inlineImage) t << " inline=\"yes\">";
74   if (doCaption)
75   {
76     t << " caption=\"";
77     visitCaption(parent, children);
78     t << "\"";
79   }
80   t << ">";
81 }
82
83 static void visitPostEnd(FTextStream &t, const char *cmd)
84 {
85   t << "</" << cmd << ">" << endl;
86 }
87
88 XmlDocVisitor::XmlDocVisitor(FTextStream &t,CodeOutputInterface &ci) 
89   : DocVisitor(DocVisitor_XML), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) 
90 {
91 }
92
93   //--------------------------------------
94   // visitor functions for leaf nodes
95   //--------------------------------------
96
97 void XmlDocVisitor::visit(DocWord *w)
98 {
99   if (m_hide) return;
100   filter(w->word());
101 }
102
103 void XmlDocVisitor::visit(DocLinkedWord *w)
104 {
105   if (m_hide) return;
106   startLink(w->ref(),w->file(),w->anchor());
107   filter(w->word());
108   endLink();
109 }
110
111 void XmlDocVisitor::visit(DocWhiteSpace *w)
112 {
113   if (m_hide) return;
114   if (m_insidePre)
115   {
116     m_t << w->chars();
117   }
118   else
119   {
120     m_t << " ";
121   }
122 }
123
124 void XmlDocVisitor::visit(DocSymbol *s)
125 {
126   if (m_hide) return;
127   const char *res = HtmlEntityMapper::instance()->xml(s->symbol());
128   if (res)
129   {
130     m_t << res;
131   }
132   else
133   {
134     err("XML: non supported HTML-entity found: %s\n",HtmlEntityMapper::instance()->html(s->symbol(),TRUE));
135   }
136 }
137
138 void XmlDocVisitor::visit(DocEmoji *s)
139 {
140   if (m_hide) return;
141   const char *res = EmojiEntityMapper::instance()->name(s->index());
142   if (res)
143   {
144     QCString name=res;
145     name = name.mid(1,name.length()-2);
146     m_t << "<emoji name=\"" << name << "\" unicode=\"";
147     filter(EmojiEntityMapper::instance()->unicode(s->index()));
148     m_t << "\"/>";
149   }
150   else
151   {
152     m_t << s->name();
153   }
154 }
155
156 void XmlDocVisitor::visit(DocURL *u)
157 {
158   if (m_hide) return;
159   m_t << "<ulink url=\""; 
160   if (u->isEmail()) m_t << "mailto:";
161   filter(u->url());
162   m_t << "\">";
163   filter(u->url());
164   m_t << "</ulink>";
165 }
166
167 void XmlDocVisitor::visit(DocLineBreak *)
168 {
169   if (m_hide) return;
170   m_t << "<linebreak/>\n";
171 }
172
173 void XmlDocVisitor::visit(DocHorRuler *)
174 {
175   if (m_hide) return;
176   m_t << "<hruler/>\n";
177 }
178
179 void XmlDocVisitor::visit(DocStyleChange *s)
180 {
181   if (m_hide) return;
182   switch (s->style())
183   {
184     case DocStyleChange::Bold:
185       if (s->enable()) m_t << "<bold>";      else m_t << "</bold>";
186       break;
187     case DocStyleChange::Strike:
188       if (s->enable()) m_t << "<strike>";      else m_t << "</strike>";
189       break;
190     case DocStyleChange::Underline:
191       if (s->enable()) m_t << "<underline>";      else m_t << "</underline>";
192       break;
193     case DocStyleChange::Italic:
194       if (s->enable()) m_t << "<emphasis>";     else m_t << "</emphasis>";
195       break;
196     case DocStyleChange::Code:
197       if (s->enable()) m_t << "<computeroutput>";   else m_t << "</computeroutput>";
198       break;
199     case DocStyleChange::Subscript:
200       if (s->enable()) m_t << "<subscript>";    else m_t << "</subscript>";
201       break;
202     case DocStyleChange::Superscript:
203       if (s->enable()) m_t << "<superscript>";    else m_t << "</superscript>";
204       break;
205     case DocStyleChange::Center:
206       if (s->enable()) m_t << "<center>"; else m_t << "</center>";
207       break;
208     case DocStyleChange::Small:
209       if (s->enable()) m_t << "<small>";  else m_t << "</small>";
210       break;
211     case DocStyleChange::Preformatted:
212       if (s->enable()) 
213       {
214         m_t << "<preformatted>";  
215         m_insidePre=TRUE;
216       }
217       else 
218       {
219         m_t << "</preformatted>";
220         m_insidePre=FALSE;
221       }
222       break;
223     case DocStyleChange::Div:  /* HTML only */ break;
224     case DocStyleChange::Span: /* HTML only */ break;
225   }
226 }
227
228 void XmlDocVisitor::visit(DocVerbatim *s)
229 {
230   if (m_hide) return;
231   QCString lang = m_langExt;
232   if (!s->language().isEmpty()) // explicit language setting
233   {
234     lang = s->language();
235   }
236   SrcLangExt langExt = getLanguageFromFileName(lang);
237   switch(s->type())
238   {
239     case DocVerbatim::Code: // fall though
240       m_t << "<programlisting";
241       if (!s->language().isEmpty())
242           m_t << " filename=\"" << lang << "\">";
243       else
244           m_t << ">";
245       Doxygen::parserManager->getParser(lang)
246                             ->parseCode(m_ci,s->context(),s->text(),langExt,
247                                         s->isExample(),s->exampleFile());
248       m_t << "</programlisting>"; 
249       break;
250     case DocVerbatim::Verbatim: 
251       m_t << "<verbatim>";
252       filter(s->text());
253       m_t << "</verbatim>"; 
254       break;
255     case DocVerbatim::HtmlOnly: 
256     case DocVerbatim::RtfOnly: 
257     case DocVerbatim::ManOnly: 
258     case DocVerbatim::LatexOnly: 
259     case DocVerbatim::DocbookOnly:
260       /* nothing */ 
261       break;
262     case DocVerbatim::XmlOnly: 
263       m_t << s->text();
264       break;
265     case DocVerbatim::Dot:
266       visitPreStart(m_t, "dot", s->hasCaption(), this, s->children(), QCString(""), FALSE, DocImage::Html, s->width(), s->height());
267       filter(s->text());
268       visitPostEnd(m_t, "dot");
269       break;
270     case DocVerbatim::Msc:
271       visitPreStart(m_t, "msc", s->hasCaption(), this, s->children(),  QCString(""), FALSE, DocImage::Html, s->width(), s->height());
272       filter(s->text());
273       visitPostEnd(m_t, "msc");
274       break;
275     case DocVerbatim::PlantUML:
276       visitPreStart(m_t, "plantuml", s->hasCaption(), this, s->children(),  QCString(""), FALSE, DocImage::Html, s->width(), s->height());
277       filter(s->text());
278       visitPostEnd(m_t, "plantuml");
279       break;
280   }
281 }
282
283 void XmlDocVisitor::visit(DocAnchor *anc)
284 {
285   if (m_hide) return;
286   m_t << "<anchor id=\"" << anc->file() << "_1" << anc->anchor() << "\"/>";
287 }
288
289 void XmlDocVisitor::visit(DocInclude *inc)
290 {
291   if (m_hide) return;
292   SrcLangExt langExt = getLanguageFromFileName(inc->extension());
293   switch(inc->type())
294   {
295     case DocInclude::IncWithLines:
296       { 
297          m_t << "<programlisting filename=\"" << inc->file() << "\">";
298          QFileInfo cfi( inc->file() );
299          FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
300          Doxygen::parserManager->getParser(inc->extension())
301                                ->parseCode(m_ci,inc->context(),
302                                            inc->text(),
303                                            langExt,
304                                            inc->isExample(),
305                                            inc->exampleFile(),
306                                            &fd,   // fileDef,
307                                            -1,    // start line
308                                            -1,    // end line
309                                            FALSE, // inline fragment
310                                            0,     // memberDef
311                                            TRUE   // show line numbers
312                                            );
313          m_t << "</programlisting>"; 
314       }
315       break;    
316     case DocInclude::Include: 
317       m_t << "<programlisting filename=\"" << inc->file() << "\">";
318       Doxygen::parserManager->getParser(inc->extension())
319                             ->parseCode(m_ci,inc->context(),
320                                         inc->text(),
321                                         langExt,
322                                         inc->isExample(),
323                                         inc->exampleFile(),
324                                         0,     // fileDef
325                                         -1,    // startLine
326                                         -1,    // endLine
327                                         TRUE,  // inlineFragment
328                                         0,     // memberDef
329                                         FALSE  // show line numbers
330                                        );
331       m_t << "</programlisting>"; 
332       break;
333     case DocInclude::DontInclude: 
334       break;
335     case DocInclude::HtmlInclude: 
336       if (inc->isBlock())
337       {
338         m_t << "<htmlonly block=\"yes\">";
339       }
340       else
341       {
342         m_t << "<htmlonly>";
343       }
344       filter(inc->text());
345       m_t << "</htmlonly>";
346       break;
347     case DocInclude::LatexInclude:
348       m_t << "<latexonly>";
349       filter(inc->text());
350       m_t << "</latexonly>";
351       break;
352     case DocInclude::VerbInclude: 
353       m_t << "<verbatim>";
354       filter(inc->text());
355       m_t << "</verbatim>"; 
356       break;
357     case DocInclude::Snippet:
358       m_t << "<programlisting filename=\"" << inc->file() << "\">";
359       Doxygen::parserManager->getParser(inc->extension())
360                             ->parseCode(m_ci,
361                                         inc->context(),
362                                         extractBlock(inc->text(),inc->blockId()),
363                                         langExt,
364                                         inc->isExample(),
365                                         inc->exampleFile()
366                                        );
367       m_t << "</programlisting>"; 
368       break;
369     case DocInclude::SnipWithLines:
370       {
371          m_t << "<programlisting filename=\"" << inc->file() << "\">";
372          QFileInfo cfi( inc->file() );
373          FileDef fd( cfi.dirPath().utf8(), cfi.fileName().utf8() );
374          Doxygen::parserManager->getParser(inc->extension())
375                                ->parseCode(m_ci,
376                                            inc->context(),
377                                            extractBlock(inc->text(),inc->blockId()),
378                                            langExt,
379                                            inc->isExample(),
380                                            inc->exampleFile(), 
381                                            &fd,
382                                            lineBlock(inc->text(),inc->blockId()),
383                                            -1,    // endLine
384                                            FALSE, // inlineFragment
385                                            0,     // memberDef
386                                            TRUE   // show line number
387                                           );
388          m_t << "</programlisting>"; 
389       }
390       break;
391     case DocInclude::SnippetDoc: 
392     case DocInclude::IncludeDoc: 
393       err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s"
394           "Please create a bug report\n",__FILE__);
395       break;
396   }
397 }
398
399 void XmlDocVisitor::visit(DocIncOperator *op)
400 {
401   //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
402   //    op->type(),op->isFirst(),op->isLast(),op->text().data());
403   if (op->isFirst()) 
404   {
405     if (!m_hide)
406     {
407       m_t << "<programlisting filename=\"" << op->includeFileName() << "\">";
408     }
409     pushEnabled();
410     m_hide = TRUE;
411   }
412   SrcLangExt langExt = getLanguageFromFileName(m_langExt);
413   if (op->type()!=DocIncOperator::Skip) 
414   {
415     popEnabled();
416     if (!m_hide) 
417     {
418       Doxygen::parserManager->getParser(m_langExt)
419                             ->parseCode(m_ci,op->context(),
420                                         op->text(),langExt,op->isExample(),
421                                         op->exampleFile());
422     }
423     pushEnabled();
424     m_hide=TRUE;
425   }
426   if (op->isLast())  
427   {
428     popEnabled();
429     if (!m_hide) m_t << "</programlisting>"; 
430   }
431   else
432   {
433     if (!m_hide) m_t << endl;
434   }
435 }
436
437 void XmlDocVisitor::visit(DocFormula *f)
438 {
439   if (m_hide) return;
440   m_t << "<formula id=\"" << f->id() << "\">";
441   filter(f->text());
442   m_t << "</formula>";
443 }
444
445 void XmlDocVisitor::visit(DocIndexEntry *ie)
446 {
447   if (m_hide) return;
448   m_t << "<indexentry>"
449            "<primaryie>";
450   filter(ie->entry());
451   m_t << "</primaryie>"
452            "<secondaryie></secondaryie>"
453          "</indexentry>";
454 }
455
456 void XmlDocVisitor::visit(DocSimpleSectSep *sep)
457 {
458   if (sep->parent() && sep->parent()->kind()==DocNode::Kind_SimpleSect)
459   {
460     visitPost((DocSimpleSect*)sep->parent()); // end current section
461     visitPre((DocSimpleSect*)sep->parent());  // start new section
462   }
463 }
464
465 void XmlDocVisitor::visit(DocCite *cite)
466 {
467   if (m_hide) return;
468   if (!cite->file().isEmpty()) startLink(cite->ref(),cite->file(),cite->anchor());
469   filter(cite->text());
470   if (!cite->file().isEmpty()) endLink();
471 }
472
473 //--------------------------------------
474 // visitor functions for compound nodes
475 //--------------------------------------
476
477 void XmlDocVisitor::visitPre(DocAutoList *l)
478 {
479   if (m_hide) return;
480   if (l->isEnumList())
481   {
482     m_t << "<orderedlist>\n";
483   }
484   else
485   {
486     m_t << "<itemizedlist>\n";
487   }
488 }
489
490 void XmlDocVisitor::visitPost(DocAutoList *l)
491 {
492   if (m_hide) return;
493   if (l->isEnumList())
494   {
495     m_t << "</orderedlist>\n";
496   }
497   else
498   {
499     m_t << "</itemizedlist>\n";
500   }
501 }
502
503 void XmlDocVisitor::visitPre(DocAutoListItem *)
504 {
505   if (m_hide) return;
506   m_t << "<listitem>";
507 }
508
509 void XmlDocVisitor::visitPost(DocAutoListItem *) 
510 {
511   if (m_hide) return;
512   m_t << "</listitem>";
513 }
514
515 void XmlDocVisitor::visitPre(DocPara *) 
516 {
517   if (m_hide) return;
518   m_t << "<para>";
519 }
520
521 void XmlDocVisitor::visitPost(DocPara *)
522 {
523   if (m_hide) return;
524   m_t << "</para>" << endl;
525 }
526
527 void XmlDocVisitor::visitPre(DocRoot *)
528 {
529   //m_t << "<hr><h4><font color=\"red\">New parser:</font></h4>\n";
530 }
531
532 void XmlDocVisitor::visitPost(DocRoot *)
533 {
534   //m_t << "<hr><h4><font color=\"red\">Old parser:</font></h4>\n";
535 }
536
537 void XmlDocVisitor::visitPre(DocSimpleSect *s)
538 {
539   if (m_hide) return;
540   m_t << "<simplesect kind=\"";
541   switch(s->type())
542   {
543     case DocSimpleSect::See: 
544       m_t << "see"; break;
545     case DocSimpleSect::Return: 
546       m_t << "return"; break;
547     case DocSimpleSect::Author: 
548       m_t << "author"; break;
549     case DocSimpleSect::Authors: 
550       m_t << "authors"; break;
551     case DocSimpleSect::Version: 
552       m_t << "version"; break;
553     case DocSimpleSect::Since: 
554       m_t << "since"; break;
555     case DocSimpleSect::Date: 
556       m_t << "date"; break;
557     case DocSimpleSect::Note: 
558       m_t << "note"; break;
559     case DocSimpleSect::Warning:
560       m_t << "warning"; break;
561     case DocSimpleSect::Pre:
562       m_t << "pre"; break;
563     case DocSimpleSect::Post:
564       m_t << "post"; break;
565     case DocSimpleSect::Copyright:
566       m_t << "copyright"; break;
567     case DocSimpleSect::Invar:
568       m_t << "invariant"; break;
569     case DocSimpleSect::Remark:
570       m_t << "remark"; break;
571     case DocSimpleSect::Attention:
572       m_t << "attention"; break;
573     case DocSimpleSect::User: 
574       m_t << "par"; break;
575     case DocSimpleSect::Rcs: 
576       m_t << "rcs"; break;
577     case DocSimpleSect::Unknown:  break;
578   }
579   m_t << "\">";
580 }
581
582 void XmlDocVisitor::visitPost(DocSimpleSect *)
583 {
584   if (m_hide) return;
585   m_t << "</simplesect>\n";
586 }
587
588 void XmlDocVisitor::visitPre(DocTitle *)
589 {
590   if (m_hide) return;
591   m_t << "<title>";
592 }
593
594 void XmlDocVisitor::visitPost(DocTitle *)
595 {
596   if (m_hide) return;
597   m_t << "</title>";
598 }
599
600 void XmlDocVisitor::visitPre(DocSimpleList *)
601 {
602   if (m_hide) return;
603   m_t << "<itemizedlist>\n";
604 }
605
606 void XmlDocVisitor::visitPost(DocSimpleList *)
607 {
608   if (m_hide) return;
609   m_t << "</itemizedlist>\n";
610 }
611
612 void XmlDocVisitor::visitPre(DocSimpleListItem *)
613 {
614   if (m_hide) return;
615   m_t << "<listitem>";
616 }
617
618 void XmlDocVisitor::visitPost(DocSimpleListItem *) 
619 {
620   if (m_hide) return;
621   m_t << "</listitem>\n";
622 }
623
624 void XmlDocVisitor::visitPre(DocSection *s)
625 {
626   if (m_hide) return;
627   m_t << "<sect" << s->level() << " id=\"" << s->file();
628   if (!s->anchor().isEmpty()) m_t << "_1" << s->anchor();
629   m_t << "\">" << endl;
630   m_t << "<title>";
631   filter(convertCharEntitiesToUTF8(s->title()));
632   m_t << "</title>" << endl;
633 }
634
635 void XmlDocVisitor::visitPost(DocSection *s) 
636 {
637   m_t << "</sect" << s->level() << ">\n";
638 }
639
640 void XmlDocVisitor::visitPre(DocHtmlList *s)
641 {
642   if (m_hide) return;
643   if (s->type()==DocHtmlList::Ordered) 
644     m_t << "<orderedlist>\n"; 
645   else 
646     m_t << "<itemizedlist>\n";
647 }
648
649 void XmlDocVisitor::visitPost(DocHtmlList *s) 
650 {
651   if (m_hide) return;
652   if (s->type()==DocHtmlList::Ordered) 
653     m_t << "</orderedlist>\n"; 
654   else 
655     m_t << "</itemizedlist>\n";
656 }
657
658 void XmlDocVisitor::visitPre(DocHtmlListItem *)
659 {
660   if (m_hide) return;
661   m_t << "<listitem>\n";
662 }
663
664 void XmlDocVisitor::visitPost(DocHtmlListItem *) 
665 {
666   if (m_hide) return;
667   m_t << "</listitem>\n";
668 }
669
670 void XmlDocVisitor::visitPre(DocHtmlDescList *)
671 {
672   if (m_hide) return;
673   m_t << "<variablelist>\n";
674 }
675
676 void XmlDocVisitor::visitPost(DocHtmlDescList *) 
677 {
678   if (m_hide) return;
679   m_t << "</variablelist>\n";
680 }
681
682 void XmlDocVisitor::visitPre(DocHtmlDescTitle *)
683 {
684   if (m_hide) return;
685   m_t << "<varlistentry><term>";
686 }
687
688 void XmlDocVisitor::visitPost(DocHtmlDescTitle *) 
689 {
690   if (m_hide) return;
691   m_t << "</term></varlistentry>\n";
692 }
693
694 void XmlDocVisitor::visitPre(DocHtmlDescData *)
695 {
696   if (m_hide) return;
697   m_t << "<listitem>";
698 }
699
700 void XmlDocVisitor::visitPost(DocHtmlDescData *) 
701 {
702   if (m_hide) return;
703   m_t << "</listitem>\n";
704 }
705
706 void XmlDocVisitor::visitPre(DocHtmlTable *t)
707 {
708   if (m_hide) return;
709   m_t << "<table rows=\"" << t->numRows() 
710       << "\" cols=\"" << t->numColumns() << "\">" ;
711 }
712
713 void XmlDocVisitor::visitPost(DocHtmlTable *) 
714 {
715   if (m_hide) return;
716   m_t << "</table>\n";
717 }
718
719 void XmlDocVisitor::visitPre(DocHtmlRow *)
720 {
721   if (m_hide) return;
722   m_t << "<row>\n";
723 }
724
725 void XmlDocVisitor::visitPost(DocHtmlRow *) 
726 {
727   if (m_hide) return;
728   m_t << "</row>\n";
729 }
730
731 void XmlDocVisitor::visitPre(DocHtmlCell *c)
732 {
733   if (m_hide) return;
734   if (c->isHeading()) m_t << "<entry thead=\"yes\">"; else m_t << "<entry thead=\"no\">";
735 }
736
737 void XmlDocVisitor::visitPost(DocHtmlCell *) 
738 {
739   if (m_hide) return;
740   m_t << "</entry>"; 
741 }
742
743 void XmlDocVisitor::visitPre(DocHtmlCaption *)
744 {
745   if (m_hide) return;
746   m_t << "<caption>";
747 }
748
749 void XmlDocVisitor::visitPost(DocHtmlCaption *) 
750 {
751   if (m_hide) return;
752   m_t << "</caption>\n";
753 }
754
755 void XmlDocVisitor::visitPre(DocInternal *)
756 {
757   if (m_hide) return;
758   m_t << "<internal>";
759 }
760
761 void XmlDocVisitor::visitPost(DocInternal *) 
762 {
763   if (m_hide) return;
764   m_t << "</internal>" << endl;
765 }
766
767 void XmlDocVisitor::visitPre(DocHRef *href)
768 {
769   if (m_hide) return;
770   m_t << "<ulink url=\"";
771   filter(href->url());
772   m_t << "\">";
773 }
774
775 void XmlDocVisitor::visitPost(DocHRef *) 
776 {
777   if (m_hide) return;
778   m_t << "</ulink>";
779 }
780
781 void XmlDocVisitor::visitPre(DocHtmlHeader *header)
782 {
783   if (m_hide) return;
784   m_t << "<heading level=\"" << header->level() << "\">";
785 }
786
787 void XmlDocVisitor::visitPost(DocHtmlHeader *) 
788 {
789   if (m_hide) return;
790   m_t << "</heading>\n";
791 }
792
793 void XmlDocVisitor::visitPre(DocImage *img)
794 {
795   if (m_hide) return;
796
797   QCString baseName=img->name();
798   int i;
799   if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
800   {
801     baseName=baseName.right(baseName.length()-i-1);
802   }
803   visitPreStart(m_t, "image", FALSE, this, img->children(), baseName, TRUE, img->type(), img->width(), img->height(), img ->isInlineImage());
804
805   // copy the image to the output dir
806   FileDef *fd;
807   bool ambig;
808   if ((fd=findFileDef(Doxygen::imageNameDict,img->name(),ambig)))
809   {
810     QFile inImage(fd->absFilePath());
811     QFile outImage(Config_getString(XML_OUTPUT)+"/"+baseName.data());
812     if (inImage.open(IO_ReadOnly))
813     {
814       if (outImage.open(IO_WriteOnly))
815       {
816         char *buffer = new char[inImage.size()];
817         inImage.readBlock(buffer,inImage.size());
818         outImage.writeBlock(buffer,inImage.size());
819         outImage.flush();
820         delete[] buffer;
821       }
822     }
823   }
824 }
825
826 void XmlDocVisitor::visitPost(DocImage *) 
827 {
828   if (m_hide) return;
829   visitPostEnd(m_t, "image");
830 }
831
832 void XmlDocVisitor::visitPre(DocDotFile *df)
833 {
834   if (m_hide) return;
835   visitPreStart(m_t, "dotfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height());
836 }
837
838 void XmlDocVisitor::visitPost(DocDotFile *) 
839 {
840   if (m_hide) return;
841   visitPostEnd(m_t, "dotfile");
842 }
843
844 void XmlDocVisitor::visitPre(DocMscFile *df)
845 {
846   if (m_hide) return;
847   visitPreStart(m_t, "mscfile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height());
848 }
849
850 void XmlDocVisitor::visitPost(DocMscFile *) 
851 {
852   if (m_hide) return;
853   visitPostEnd(m_t, "mscfile");
854 }
855
856 void XmlDocVisitor::visitPre(DocDiaFile *df)
857 {
858   if (m_hide) return;
859   visitPreStart(m_t, "diafile", FALSE, this, df->children(), df->file(), FALSE, DocImage::Html, df->width(), df->height());
860 }
861
862 void XmlDocVisitor::visitPost(DocDiaFile *)
863 {
864   if (m_hide) return;
865   visitPostEnd(m_t, "diafile");
866 }
867
868 void XmlDocVisitor::visitPre(DocLink *lnk)
869 {
870   if (m_hide) return;
871   startLink(lnk->ref(),lnk->file(),lnk->anchor());
872 }
873
874 void XmlDocVisitor::visitPost(DocLink *) 
875 {
876   if (m_hide) return;
877   endLink();
878 }
879
880 void XmlDocVisitor::visitPre(DocRef *ref)
881 {
882   if (m_hide) return;
883   if (!ref->file().isEmpty()) 
884   {
885     startLink(ref->ref(),ref->file(),ref->isSubPage() ? QCString() : ref->anchor());
886   }
887   if (!ref->hasLinkText()) filter(ref->targetTitle());
888 }
889
890 void XmlDocVisitor::visitPost(DocRef *ref) 
891 {
892   if (m_hide) return;
893   if (!ref->file().isEmpty()) endLink();
894   //m_t << " ";
895 }
896
897 void XmlDocVisitor::visitPre(DocSecRefItem *ref)
898 {
899   if (m_hide) return;
900   m_t << "<tocitem id=\"" << ref->file() << "_1" << ref->anchor() << "\">";
901 }
902
903 void XmlDocVisitor::visitPost(DocSecRefItem *) 
904 {
905   if (m_hide) return;
906   m_t << "</tocitem>" << endl;
907 }
908
909 void XmlDocVisitor::visitPre(DocSecRefList *)
910 {
911   if (m_hide) return;
912   m_t << "<toclist>" << endl;
913 }
914
915 void XmlDocVisitor::visitPost(DocSecRefList *) 
916 {
917   if (m_hide) return;
918   m_t << "</toclist>" << endl;
919 }
920
921 //void XmlDocVisitor::visitPre(DocLanguage *l)
922 //{
923 //  if (m_hide) return;
924 //  m_t << "<language langid=\"" << l->id() << "\">";
925 //}
926 //
927 //void XmlDocVisitor::visitPost(DocLanguage *) 
928 //{
929 //  if (m_hide) return;
930 //  m_t << "</language>" << endl;
931 //}
932
933 void XmlDocVisitor::visitPre(DocParamSect *s)
934 {
935   if (m_hide) return;
936   m_t << "<parameterlist kind=\"";
937   switch(s->type())
938   {
939     case DocParamSect::Param: 
940       m_t << "param"; break;
941     case DocParamSect::RetVal: 
942       m_t << "retval"; break;
943     case DocParamSect::Exception: 
944       m_t << "exception"; break;
945     case DocParamSect::TemplateParam: 
946       m_t << "templateparam"; break;
947     default:
948       ASSERT(0);
949   }
950   m_t << "\">";
951 }
952
953 void XmlDocVisitor::visitPost(DocParamSect *)
954 {
955   if (m_hide) return;
956   m_t << "</parameterlist>" << endl;
957 }
958
959 void XmlDocVisitor::visitPre(DocParamList *pl)
960 {
961   if (m_hide) return;
962   m_t << "<parameteritem>" << endl;
963   m_t << "<parameternamelist>" << endl;
964   //QStrListIterator li(pl->parameters());
965   //const char *s;
966   QListIterator<DocNode> li(pl->parameters());
967   DocNode *param;
968   for (li.toFirst();(param=li.current());++li)
969   {
970     if (pl->paramTypes().count()>0)
971     {
972       QListIterator<DocNode> li(pl->paramTypes());
973       DocNode *type;
974       for (li.toFirst();(type=li.current());++li)
975       {
976         m_t << "<parametertype>";
977         if (type->kind()==DocNode::Kind_Word)
978         {
979           visit((DocWord*)type); 
980         }
981         else if (type->kind()==DocNode::Kind_LinkedWord)
982         {
983           visit((DocLinkedWord*)type); 
984         }
985         m_t << "</parametertype>" << endl;
986       }
987     }
988     m_t << "<parametername";
989     if (pl->direction()!=DocParamSect::Unspecified)
990     {
991       m_t << " direction=\"";
992       if (pl->direction()==DocParamSect::In)
993       {
994         m_t << "in";
995       }
996       else if (pl->direction()==DocParamSect::Out)
997       {
998         m_t << "out";
999       }
1000       else if (pl->direction()==DocParamSect::InOut)
1001       {
1002         m_t << "inout";
1003       }
1004       m_t << "\"";
1005     }
1006     m_t << ">";
1007     if (param->kind()==DocNode::Kind_Word)
1008     {
1009       visit((DocWord*)param); 
1010     }
1011     else if (param->kind()==DocNode::Kind_LinkedWord)
1012     {
1013       visit((DocLinkedWord*)param); 
1014     }
1015     m_t << "</parametername>" << endl;
1016   }
1017   m_t << "</parameternamelist>" << endl;
1018   m_t << "<parameterdescription>" << endl;
1019 }
1020
1021 void XmlDocVisitor::visitPost(DocParamList *)
1022 {
1023   if (m_hide) return;
1024   m_t << "</parameterdescription>" << endl;
1025   m_t << "</parameteritem>" << endl;
1026 }
1027
1028 void XmlDocVisitor::visitPre(DocXRefItem *x)
1029 {
1030   if (m_hide) return;
1031   if (x->title().isEmpty()) return;
1032   m_t << "<xrefsect id=\"";
1033   m_t << x->file() << "_1" << x->anchor();
1034   m_t << "\">";
1035   m_t << "<xreftitle>";
1036   filter(x->title());
1037   m_t << "</xreftitle>";
1038   m_t << "<xrefdescription>";
1039 }
1040
1041 void XmlDocVisitor::visitPost(DocXRefItem *x)
1042 {
1043   if (m_hide) return;
1044   if (x->title().isEmpty()) return;
1045   m_t << "</xrefdescription>";
1046   m_t << "</xrefsect>";
1047 }
1048
1049 void XmlDocVisitor::visitPre(DocInternalRef *ref)
1050 {
1051   if (m_hide) return;
1052   startLink(0,ref->file(),ref->anchor());
1053 }
1054
1055 void XmlDocVisitor::visitPost(DocInternalRef *) 
1056 {
1057   if (m_hide) return;
1058   endLink();
1059   m_t << " ";
1060 }
1061
1062 void XmlDocVisitor::visitPre(DocCopy *c)
1063 {
1064   if (m_hide) return;
1065   m_t << "<copydoc link=\"" << convertToXML(c->link()) << "\">";
1066 }
1067
1068 void XmlDocVisitor::visitPost(DocCopy *)
1069 {
1070   if (m_hide) return;
1071   m_t << "</copydoc>" << endl;
1072 }
1073
1074 void XmlDocVisitor::visitPre(DocText *)
1075 {
1076 }
1077
1078 void XmlDocVisitor::visitPost(DocText *)
1079 {
1080 }
1081
1082 void XmlDocVisitor::visitPre(DocHtmlBlockQuote *)
1083 {
1084   if (m_hide) return;
1085   m_t << "<blockquote>";
1086 }
1087
1088 void XmlDocVisitor::visitPost(DocHtmlBlockQuote *)
1089 {
1090   if (m_hide) return;
1091   m_t << "</blockquote>";
1092 }
1093
1094 void XmlDocVisitor::visitPre(DocVhdlFlow *)
1095 {
1096 }
1097
1098 void XmlDocVisitor::visitPost(DocVhdlFlow *)
1099 {
1100 }
1101
1102 void XmlDocVisitor::visitPre(DocParBlock *)
1103 {
1104   if (m_hide) return;
1105   m_t << "<parblock>";
1106 }
1107
1108 void XmlDocVisitor::visitPost(DocParBlock *)
1109 {
1110   if (m_hide) return;
1111   m_t << "</parblock>";
1112 }
1113
1114
1115 void XmlDocVisitor::filter(const char *str)
1116
1117   m_t << convertToXML(str);
1118 }
1119
1120 void XmlDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor)
1121 {
1122   //printf("XmlDocVisitor: file=%s anchor=%s\n",file.data(),anchor.data());
1123   m_t << "<ref refid=\"" << file;
1124   if (!anchor.isEmpty()) m_t << "_1" << anchor;
1125   m_t << "\" kindref=\"";
1126   if (!anchor.isEmpty()) m_t << "member"; else m_t << "compound";
1127   m_t << "\"";
1128   if (!ref.isEmpty()) m_t << " external=\"" << ref << "\"";
1129   m_t << ">";
1130 }
1131
1132 void XmlDocVisitor::endLink()
1133 {
1134   m_t << "</ref>";
1135 }
1136
1137 void XmlDocVisitor::pushEnabled()
1138 {
1139   m_enabled.push(new bool(m_hide));
1140 }
1141
1142 void XmlDocVisitor::popEnabled()
1143 {
1144   bool *v=m_enabled.pop();
1145   ASSERT(v!=0);
1146   m_hide = *v;
1147   delete v;
1148 }
1149