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