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