htmldocvisitor.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * $Id: $
00004  *
00005  *
00006  * Copyright (C) 1997-2008 by Dimitri van Heesch.
00007  *
00008  * Permission to use, copy, modify, and distribute this software and its
00009  * documentation under the terms of the GNU General Public License is hereby 
00010  * granted. No representations are made about the suitability of this software 
00011  * for any purpose. It is provided "as is" without express or implied warranty.
00012  * See the GNU General Public License for more details.
00013  *
00014  * Documents produced by Doxygen are derivative works derived from the
00015  * input used in their production; they are not affected by this license.
00016  *
00017  */
00018 
00019 #include <qdir.h>
00020 #include "htmldocvisitor.h"
00021 #include "docparser.h"
00022 #include "language.h"
00023 #include "doxygen.h"
00024 #include "outputgen.h"
00025 #include "dot.h"
00026 #include "message.h"
00027 #include "config.h"
00028 #include "htmlgen.h"
00029 #include "parserintf.h"
00030 #include "msc.h"
00031 #include "util.h"
00032 
00033 
00034 static const int NUM_HTML_LIST_TYPES = 4;
00035 static const char types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"};
00036 
00037 
00038 static QString htmlAttribsToString(const HtmlAttribList &attribs)
00039 {
00040   QString result;
00041   HtmlAttribListIterator li(attribs);
00042   HtmlAttrib *att;
00043   for (li.toFirst();(att=li.current());++li)
00044   {
00045     result+=" ";
00046     result+=att->name;
00047     if (!att->value.isEmpty()) result+="=\""+att->value+"\"";
00048   }
00049   return result;
00050 }
00051 
00052 //-------------------------------------------------------------------------
00053 
00054 HtmlDocVisitor::HtmlDocVisitor(QTextStream &t,CodeOutputInterface &ci,
00055                                const char *langExt) 
00056   : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), 
00057                                  m_hide(FALSE), m_langExt(langExt)
00058 {
00059 }
00060 
00061   //--------------------------------------
00062   // visitor functions for leaf nodes
00063   //--------------------------------------
00064 
00065 void HtmlDocVisitor::visit(DocWord *w)
00066 {
00067   if (m_hide) return;
00068   filter(w->word());
00069 }
00070 
00071 void HtmlDocVisitor::visit(DocLinkedWord *w)
00072 {
00073   if (m_hide) return;
00074   startLink(w->ref(),w->file(),w->relPath(),w->anchor(),w->tooltip());
00075   filter(w->word());
00076   endLink();
00077 }
00078 
00079 void HtmlDocVisitor::visit(DocWhiteSpace *w)
00080 {
00081   if (m_hide) return;
00082   if (m_insidePre)
00083   {
00084     m_t << w->chars();
00085   }
00086   else
00087   {
00088     m_t << " ";
00089   }
00090 }
00091 
00092 void HtmlDocVisitor::visit(DocSymbol *s)
00093 {
00094   if (m_hide) return;
00095   switch(s->symbol())
00096   {
00097     case DocSymbol::BSlash:  m_t << "\\"; break;
00098     case DocSymbol::At:      m_t << "@"; break;
00099     case DocSymbol::Less:    m_t << "&lt;"; break;
00100     case DocSymbol::Greater: m_t << "&gt;"; break;
00101     case DocSymbol::Amp:     m_t << "&amp;"; break;
00102     case DocSymbol::Dollar:  m_t << "$"; break;
00103     case DocSymbol::Hash:    m_t << "#"; break;
00104     case DocSymbol::Percent: m_t << "%"; break;
00105     case DocSymbol::Copy:    m_t << "&copy;"; break;
00106     case DocSymbol::Tm:      m_t << "&trade;"; break;
00107     case DocSymbol::Reg:     m_t << "&reg;"; break;
00108     case DocSymbol::Apos:    m_t << "'"; break;
00109     case DocSymbol::Quot:    m_t << "\""; break;
00110     case DocSymbol::Lsquo:   m_t << "&lsquo;"; break;
00111     case DocSymbol::Rsquo:   m_t << "&rsquo;"; break;
00112     case DocSymbol::Ldquo:   m_t << "&ldquo;"; break;
00113     case DocSymbol::Rdquo:   m_t << "&rdquo;"; break;
00114     case DocSymbol::Ndash:   m_t << "&ndash;"; break;
00115     case DocSymbol::Mdash:   m_t << "&mdash;"; break;
00116     case DocSymbol::Uml:     m_t << "&" << s->letter() << "uml;"; break;
00117     case DocSymbol::Acute:   m_t << "&" << s->letter() << "acute;"; break;
00118     case DocSymbol::Grave:   m_t << "&" << s->letter() << "grave;"; break;
00119     case DocSymbol::Circ:    m_t << "&" << s->letter() << "circ;"; break;
00120     case DocSymbol::Slash:   m_t << "&" << s->letter() << "slash;"; break;
00121     case DocSymbol::Tilde:   m_t << "&" << s->letter() << "tilde;"; break;
00122     case DocSymbol::Szlig:   m_t << "&szlig;"; break;
00123     case DocSymbol::Cedil:   m_t << "&" << s->letter() << "cedil;"; break;
00124     case DocSymbol::Ring:    m_t << "&" << s->letter() << "ring;"; break;
00125     case DocSymbol::Nbsp:    m_t << "&nbsp;"; break;
00126     default:
00127                              err("Error: unknown symbol found\n");
00128   }
00129 }
00130 
00131 void HtmlDocVisitor::visit(DocURL *u)
00132 {
00133   if (m_hide) return;
00134   m_t << "<a href=\"";
00135   if (u->isEmail()) m_t << "mailto:";
00136   m_t << u->url() << "\">";
00137   filter(u->url());
00138   m_t << "</a>";
00139 }
00140 
00141 void HtmlDocVisitor::visit(DocLineBreak *)
00142 {
00143   if (m_hide) return;
00144   m_t << "<br>\n";
00145 }
00146 
00147 void HtmlDocVisitor::visit(DocHorRuler *)
00148 {
00149   if (m_hide) return;
00150   m_t << "<hr>\n";
00151 }
00152 
00153 void HtmlDocVisitor::visit(DocStyleChange *s)
00154 {
00155   if (m_hide) return;
00156   switch (s->style())
00157   {
00158     case DocStyleChange::Bold:
00159       if (s->enable()) m_t << "<b" << htmlAttribsToString(s->attribs()) << ">";      else m_t << "</b>";
00160       break;
00161     case DocStyleChange::Italic:
00162       if (s->enable()) m_t << "<em" << htmlAttribsToString(s->attribs()) << ">";     else m_t << "</em>";
00163       break;
00164     case DocStyleChange::Code:
00165       if (s->enable()) m_t << "<code" << htmlAttribsToString(s->attribs()) << ">";   else m_t << "</code>";
00166       break;
00167     case DocStyleChange::Subscript:
00168       if (s->enable()) m_t << "<sub" << htmlAttribsToString(s->attribs()) << ">";    else m_t << "</sub>";
00169       break;
00170     case DocStyleChange::Superscript:
00171       if (s->enable()) m_t << "<sup" << htmlAttribsToString(s->attribs()) << ">";    else m_t << "</sup>";
00172       break;
00173     case DocStyleChange::Center:
00174       if (s->enable()) m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</center>";
00175       break;
00176     case DocStyleChange::Small:
00177       if (s->enable()) m_t << "<small" << htmlAttribsToString(s->attribs()) << ">";  else m_t << "</small>";
00178       break;
00179     case DocStyleChange::Preformatted:
00180       if (s->enable())
00181       {
00182         m_t << "<pre" << htmlAttribsToString(s->attribs()) << ">";
00183         m_insidePre=TRUE;
00184       }
00185       else
00186       {
00187         m_insidePre=FALSE;
00188         m_t << "</pre>";
00189       }
00190       break;
00191     case DocStyleChange::Div:
00192       if (s->enable()) m_t << "<div" << htmlAttribsToString(s->attribs()) << ">";  else m_t << "</div>";
00193       break;
00194     case DocStyleChange::Span:
00195       if (s->enable()) m_t << "<span" << htmlAttribsToString(s->attribs()) << ">";  else m_t << "</span>";
00196       break;
00197 
00198   }
00199 }
00200 
00201 
00202 void HtmlDocVisitor::visit(DocVerbatim *s)
00203 {
00204   if (m_hide) return;
00205   switch(s->type())
00206   {
00207     case DocVerbatim::Code: // fall though
00208       m_t << PREFRAG_START;
00209       Doxygen::parserManager->getParser(m_langExt)
00210                             ->parseCode(m_ci,s->context(),s->text().latin1(),
00211                                         s->isExample(),s->exampleFile());
00212       m_t << PREFRAG_END;
00213       break;
00214     case DocVerbatim::Verbatim: 
00215       m_t << PREFRAG_START;
00216       filter(s->text());
00217       m_t << PREFRAG_END;
00218       break;
00219     case DocVerbatim::HtmlOnly: 
00220       m_t << s->text(); 
00221       break;
00222     case DocVerbatim::ManOnly: 
00223     case DocVerbatim::LatexOnly: 
00224     case DocVerbatim::XmlOnly: 
00225       /* nothing */ 
00226       break;
00227      
00228     case DocVerbatim::Dot:
00229       {
00230         static int dotindex = 1;
00231         QCString fileName(4096);
00232 
00233         fileName.sprintf("%s%d%s", 
00234             (Config_getString("HTML_OUTPUT")+"/inline_dotgraph_").data(), 
00235             dotindex++,
00236             ".dot"
00237            );
00238         QFile file(fileName);
00239         if (!file.open(IO_WriteOnly))
00240         {
00241           err("Could not open file %s for writing\n",fileName.data());
00242         }
00243         file.writeBlock( s->text(), s->text().length() );
00244         file.close();
00245 
00246         m_t << "<div align=\"center\">" << endl;
00247         writeDotFile(fileName,s->relPath(),s->context());
00248         m_t << "</div>" << endl;
00249 
00250         if (Config_getBool("DOT_CLEANUP")) file.remove();
00251       }
00252       break;
00253     case DocVerbatim::Msc:
00254       {
00255         static int mscindex = 1;
00256         QCString baseName(4096);
00257 
00258         baseName.sprintf("%s%d", 
00259             (Config_getString("HTML_OUTPUT")+"/inline_mscgraph_").data(), 
00260             mscindex++
00261            );
00262         QFile file(baseName+".msc");
00263         if (!file.open(IO_WriteOnly))
00264         {
00265           err("Could not open file %s.msc for writing\n",baseName.data());
00266         }
00267         QCString text = "msc {";
00268         text+=s->text();
00269         text+="}";
00270         file.writeBlock( text, text.length() );
00271         file.close();
00272 
00273         m_t << "<div align=\"center\">" << endl;
00274         writeMscFile(baseName,s->relPath(),s->context());
00275         m_t << "</div>" << endl;
00276 
00277         if (Config_getBool("DOT_CLEANUP")) file.remove();
00278       }
00279       break;
00280   }
00281 }
00282 
00283 void HtmlDocVisitor::visit(DocAnchor *anc)
00284 {
00285   if (m_hide) return;
00286   m_t << "<a class=\"anchor\" name=\"" << anc->anchor() << "\"></a>";
00287 }
00288 
00289 void HtmlDocVisitor::visit(DocInclude *inc)
00290 {
00291   if (m_hide) return;
00292   switch(inc->type())
00293   {
00294     case DocInclude::Include: 
00295       m_t << PREFRAG_START;
00296       Doxygen::parserManager->getParser(inc->extension())
00297                             ->parseCode(m_ci,                 
00298                                         inc->context(),
00299                                         inc->text().latin1(),
00300                                         inc->isExample(),
00301                                         inc->exampleFile(),
00302                                         0,   // fd
00303                                         -1,  // startLine
00304                                         -1,  // endLine
00305                                         TRUE // inlineFragment
00306                                        );
00307       m_t << PREFRAG_END;
00308       break;
00309     case DocInclude::IncWithLines:
00310       { 
00311          m_t << PREFRAG_START;
00312          QFileInfo cfi( inc->file() );
00313          FileDef fd( cfi.dirPath(), cfi.fileName() );
00314          Doxygen::parserManager->getParser(inc->extension())
00315                                ->parseCode(m_ci,
00316                                            inc->context(),
00317                                            inc->text().latin1(),
00318                                            inc->isExample(),
00319                                            inc->exampleFile(), &fd);
00320          m_t << PREFRAG_END;
00321       }
00322       break;
00323     case DocInclude::DontInclude: 
00324       break;
00325     case DocInclude::HtmlInclude: 
00326       m_t << inc->text(); 
00327       break;
00328     case DocInclude::VerbInclude: 
00329       m_t << PREFRAG_START;
00330       filter(inc->text());
00331       m_t << PREFRAG_END;
00332       break;
00333   }
00334 }
00335 
00336 void HtmlDocVisitor::visit(DocIncOperator *op)
00337 {
00338   //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n",
00339   //    op->type(),op->isFirst(),op->isLast(),op->text().data());
00340   if (op->isFirst()) 
00341   {
00342     if (!m_hide) m_t << PREFRAG_START;
00343     pushEnabled();
00344     m_hide=TRUE;
00345   }
00346   if (op->type()!=DocIncOperator::Skip) 
00347   {
00348     popEnabled();
00349     if (!m_hide) 
00350     {
00351       Doxygen::parserManager->getParser(m_langExt)
00352                             ->parseCode(m_ci,op->context(),
00353                                 op->text().latin1(),op->isExample(),
00354                                 op->exampleFile());
00355     }
00356     pushEnabled();
00357     m_hide=TRUE;
00358   }
00359   if (op->isLast())  
00360   {
00361     popEnabled();
00362     if (!m_hide) m_t << PREFRAG_END;
00363   }
00364   else
00365   {
00366     if (!m_hide) m_t << endl;
00367   }
00368 }
00369 
00370 void HtmlDocVisitor::visit(DocFormula *f)
00371 {
00372   if (m_hide) return;
00373   bool bDisplay = f->text().at(0)=='\\';
00374   if (bDisplay) m_t << "<p class=\"formulaDsp\">" << endl;
00375   m_t << "<img class=\"formula" 
00376       << (bDisplay ? "Dsp" : "Inl");
00377   m_t << "\" alt=\"";
00378   filterQuotedCdataAttr(f->text());
00379   m_t << "\"";
00382   m_t << " src=\"" << f->relPath() << f->name() << ".png\">";
00383   if (bDisplay)
00384     m_t << endl << "<p>" << endl;
00385 }
00386 
00387 void HtmlDocVisitor::visit(DocIndexEntry *)
00388 {
00389 }
00390 
00391 //--------------------------------------
00392 // visitor functions for compound nodes
00393 //--------------------------------------
00394 
00395 
00396 void HtmlDocVisitor::visitPre(DocAutoList *l)
00397 {
00398   if (m_hide) return;
00399   if (l->isEnumList())
00400   {
00401     //
00402     // Do list type based on depth:
00403     // 1.
00404     //   a.
00405     //     i.
00406     //       A. 
00407     //         1. (repeat)...
00408     //
00409     m_t << "<ol type=" << types[l->depth() % NUM_HTML_LIST_TYPES] << ">";
00410   }
00411   else
00412   {
00413     m_t << "<ul>";
00414   }
00415   if (!l->isPreformatted()) m_t << "\n";
00416 }
00417 
00418 void HtmlDocVisitor::visitPost(DocAutoList *l)
00419 {
00420   if (m_hide) return;
00421   if (l->isEnumList())
00422   {
00423     m_t << "</ol>";
00424   }
00425   else
00426   {
00427     m_t << "</ul>";
00428   }
00429   if (!l->isPreformatted()) m_t << "\n";
00430 }
00431 
00432 void HtmlDocVisitor::visitPre(DocAutoListItem *)
00433 {
00434   if (m_hide) return;
00435   m_t << "<li>";
00436 }
00437 
00438 void HtmlDocVisitor::visitPost(DocAutoListItem *) 
00439 {
00440   if (m_hide) return;
00441   m_t << "</li>";
00442 }
00443 
00444 void HtmlDocVisitor::visitPre(DocPara *) 
00445 {
00446   if (m_hide) return;
00447 
00448   // TODO:
00449   // Paragraph should be surrounded by <p>..</p>, but
00450   // 
00451   // A list item (li), description data (dd), or table data (td) should
00452   // only have paragraph markers if there are multiple paragraphs (otherwise
00453   // the output looks ugly).
00454   //
00455   // A list or table should be placed outside the paragraph context,
00456   // so the current paragraph should be ended and restarted. To avoid
00457   // empty paragraphs, it has to be checked if the list or table is the
00458   // first or last child within the paragraph.
00459   
00460 }
00461 
00462 void HtmlDocVisitor::visitPost(DocPara *p)
00463 {
00464   if (m_hide) return;
00465   if (!p->isLast() &&            // omit <p> for last paragraph
00466       !(p->parent() &&           // and for parameter sections
00467         p->parent()->kind()==DocNode::Kind_ParamSect
00468        ) 
00469      ) 
00470   {
00471     m_t << "<p>\n";
00472   }
00473 }
00474 
00475 void HtmlDocVisitor::visitPre(DocRoot *)
00476 {
00477 }
00478 
00479 void HtmlDocVisitor::visitPost(DocRoot *)
00480 {
00481 }
00482 
00483 void HtmlDocVisitor::visitPre(DocSimpleSect *s)
00484 {
00485   if (m_hide) return;
00486   m_t << "<dl class=\"" << s->typeString() << "\" compact><dt><b>";
00487   switch(s->type())
00488   {
00489     case DocSimpleSect::See: 
00490       m_t << theTranslator->trSeeAlso(); break;
00491     case DocSimpleSect::Return: 
00492       m_t << theTranslator->trReturns(); break;
00493     case DocSimpleSect::Author: 
00494       m_t << theTranslator->trAuthor(TRUE,TRUE); break;
00495     case DocSimpleSect::Authors: 
00496       m_t << theTranslator->trAuthor(TRUE,FALSE); break;
00497     case DocSimpleSect::Version: 
00498       m_t << theTranslator->trVersion(); break;
00499     case DocSimpleSect::Since: 
00500       m_t << theTranslator->trSince(); break;
00501     case DocSimpleSect::Date: 
00502       m_t << theTranslator->trDate(); break;
00503     case DocSimpleSect::Note: 
00504       m_t << theTranslator->trNote(); break;
00505     case DocSimpleSect::Warning:
00506       m_t << theTranslator->trWarning(); break;
00507     case DocSimpleSect::Pre:
00508       m_t << theTranslator->trPrecondition(); break;
00509     case DocSimpleSect::Post:
00510       m_t << theTranslator->trPostcondition(); break;
00511     case DocSimpleSect::Invar:
00512       m_t << theTranslator->trInvariant(); break;
00513     case DocSimpleSect::Remark:
00514       m_t << theTranslator->trRemarks(); break;
00515     case DocSimpleSect::Attention:
00516       m_t << theTranslator->trAttention(); break;
00517     case DocSimpleSect::User: break;
00518     case DocSimpleSect::Rcs: break;
00519     case DocSimpleSect::Unknown:  break;
00520   }
00521 
00522   // special case 1: user defined title
00523   if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs)
00524   {
00525     m_t << ":</b></dt><dd>";
00526   }
00527 }
00528 
00529 void HtmlDocVisitor::visitPost(DocSimpleSect *)
00530 {
00531   if (m_hide) return;
00532   m_t << "</dd></dl>\n";
00533 }
00534 
00535 void HtmlDocVisitor::visitPre(DocTitle *)
00536 {
00537 }
00538 
00539 void HtmlDocVisitor::visitPost(DocTitle *)
00540 {
00541   if (m_hide) return;
00542   m_t << "</b></dt><dd>";
00543 }
00544 
00545 void HtmlDocVisitor::visitPre(DocSimpleList *sl)
00546 {
00547   if (m_hide) return;
00548   m_t << "<ul>";
00549   if (!sl->isPreformatted()) m_t << "\n";
00550 }
00551 
00552 void HtmlDocVisitor::visitPost(DocSimpleList *sl)
00553 {
00554   if (m_hide) return;
00555   m_t << "</ul>";
00556   if (!sl->isPreformatted()) m_t << "\n";
00557 }
00558 
00559 void HtmlDocVisitor::visitPre(DocSimpleListItem *)
00560 {
00561   if (m_hide) return;
00562   m_t << "<li>";
00563 }
00564 
00565 void HtmlDocVisitor::visitPost(DocSimpleListItem *li) 
00566 {
00567   if (m_hide) return;
00568   m_t << "</li>";
00569   if (!li->isPreformatted()) m_t << "\n";
00570 }
00571 
00572 void HtmlDocVisitor::visitPre(DocSection *s)
00573 {
00574   if (m_hide) return;
00575   m_t << "<h" << s->level()+1 << ">";
00576   m_t << "<a class=\"anchor\" name=\"" << s->anchor();
00577   m_t << "\">" << endl;
00578   filter(convertCharEntitiesToUTF8(s->title().data()));
00579   m_t << "</a></h" << s->level()+1 << ">\n";
00580 }
00581 
00582 void HtmlDocVisitor::visitPost(DocSection *) 
00583 {
00584 }
00585 
00586 void HtmlDocVisitor::visitPre(DocHtmlList *s)
00587 {
00588   if (m_hide) return;
00589   if (s->type()==DocHtmlList::Ordered) 
00590   {
00591     m_t << "<ol" << htmlAttribsToString(s->attribs()) << ">\n"; 
00592   }
00593   else 
00594   {
00595     m_t << "<ul" << htmlAttribsToString(s->attribs()) << ">\n";
00596   }
00597 }
00598 
00599 void HtmlDocVisitor::visitPost(DocHtmlList *s) 
00600 {
00601   if (m_hide) return;
00602   if (s->type()==DocHtmlList::Ordered) 
00603   {
00604     m_t << "</ol>"; 
00605   }
00606   else
00607   { 
00608     m_t << "</ul>";
00609   }
00610   if (!s->isPreformatted()) m_t << "\n";
00611 }
00612 
00613 void HtmlDocVisitor::visitPre(DocHtmlListItem *i)
00614 {
00615   if (m_hide) return;
00616   m_t << "<li" << htmlAttribsToString(i->attribs()) << ">";
00617   if (!i->isPreformatted()) m_t << "\n";
00618 }
00619 
00620 void HtmlDocVisitor::visitPost(DocHtmlListItem *) 
00621 {
00622   if (m_hide) return;
00623   m_t << "</li>\n";
00624 }
00625 
00626 void HtmlDocVisitor::visitPre(DocHtmlDescList *dl)
00627 {
00628   if (m_hide) return;
00629   m_t << "<dl" << htmlAttribsToString(dl->attribs()) << ">\n";
00630 }
00631 
00632 void HtmlDocVisitor::visitPost(DocHtmlDescList *) 
00633 {
00634   if (m_hide) return;
00635   m_t << "</dl>\n";
00636 }
00637 
00638 void HtmlDocVisitor::visitPre(DocHtmlDescTitle *dt)
00639 {
00640   if (m_hide) return;
00641   m_t << "<dt" << htmlAttribsToString(dt->attribs()) << ">";
00642 }
00643 
00644 void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) 
00645 {
00646   if (m_hide) return;
00647   m_t << "</dt>\n";
00648 }
00649 
00650 void HtmlDocVisitor::visitPre(DocHtmlDescData *dd)
00651 {
00652   if (m_hide) return;
00653   m_t << "<dd" << htmlAttribsToString(dd->attribs()) << ">";
00654 }
00655 
00656 void HtmlDocVisitor::visitPost(DocHtmlDescData *) 
00657 {
00658   if (m_hide) return;
00659   m_t << "</dd>\n";
00660 }
00661 
00662 void HtmlDocVisitor::visitPre(DocHtmlTable *t)
00663 {
00664   if (m_hide) return;
00665   bool hasBorder      = FALSE;
00666   bool hasCellSpacing = FALSE;
00667   bool hasCellPadding = FALSE;
00668 
00669   HtmlAttribListIterator li(t->attribs());
00670   HtmlAttrib *att;
00671   for (li.toFirst();(att=li.current());++li)
00672   {
00673     if      (att->name=="border")      hasBorder=TRUE;
00674     else if (att->name=="cellspacing") hasCellSpacing=TRUE;
00675     else if (att->name=="cellpadding") hasCellPadding=TRUE;
00676   }
00677   m_t << "<table" << htmlAttribsToString(t->attribs());
00678   if (!hasBorder)      m_t << " border=\"1\"";
00679   if (!hasCellSpacing) m_t << " cellspacing=\"3\"";
00680   if (!hasCellPadding) m_t << " cellpadding=\"3\"";
00681   m_t << ">\n";
00682 }
00683 
00684 void HtmlDocVisitor::visitPost(DocHtmlTable *) 
00685 {
00686   if (m_hide) return;
00687   m_t << "</table>\n";
00688 }
00689 
00690 void HtmlDocVisitor::visitPre(DocHtmlRow *tr)
00691 {
00692   if (m_hide) return;
00693   m_t << "<tr" << htmlAttribsToString(tr->attribs()) << ">\n";
00694 }
00695 
00696 void HtmlDocVisitor::visitPost(DocHtmlRow *) 
00697 {
00698   if (m_hide) return;
00699   m_t << "</tr>\n";
00700 }
00701 
00702 void HtmlDocVisitor::visitPre(DocHtmlCell *c)
00703 {
00704   if (m_hide) return;
00705   if (c->isHeading()) 
00706   {
00707     m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; 
00708   }
00709   else 
00710   {
00711     m_t << "<td" << htmlAttribsToString(c->attribs()) << ">";
00712   }
00713 }
00714 
00715 void HtmlDocVisitor::visitPost(DocHtmlCell *c) 
00716 {
00717   if (m_hide) return;
00718   if (c->isHeading()) m_t << "</th>"; else m_t << "</td>";
00719 }
00720 
00721 void HtmlDocVisitor::visitPre(DocHtmlCaption *c)
00722 {
00723   if (m_hide) return;
00724   bool hasAlign      = FALSE;
00725   HtmlAttribListIterator li(c->attribs());
00726   HtmlAttrib *att;
00727   for (li.toFirst();(att=li.current());++li)
00728   {
00729     if (att->name=="align") hasAlign=TRUE;
00730   }
00731   m_t << "<caption" << htmlAttribsToString(c->attribs());
00732   if (!hasAlign) m_t << " align=\"bottom\"";
00733   m_t << ">";
00734 }
00735 
00736 void HtmlDocVisitor::visitPost(DocHtmlCaption *) 
00737 {
00738   if (m_hide) return;
00739   m_t << "</caption>\n";
00740 }
00741 
00742 void HtmlDocVisitor::visitPre(DocInternal *)
00743 {
00744   if (m_hide) return;
00745   m_t << "<p><b>" << theTranslator->trForInternalUseOnly() << "</b></p>" << endl;
00746   m_t << "<p>" << endl;
00747 }
00748 
00749 void HtmlDocVisitor::visitPost(DocInternal *) 
00750 {
00751   if (m_hide) return;
00752   m_t << "</p>" << endl;
00753 }
00754 
00755 void HtmlDocVisitor::visitPre(DocHRef *href)
00756 {
00757   if (m_hide) return;
00758   m_t << "<a href=\"" << href->url()  << "\""
00759       << htmlAttribsToString(href->attribs()) << ">";
00760 }
00761 
00762 void HtmlDocVisitor::visitPost(DocHRef *) 
00763 {
00764   if (m_hide) return;
00765   m_t << "</a>";
00766 }
00767 
00768 void HtmlDocVisitor::visitPre(DocHtmlHeader *header)
00769 {
00770   if (m_hide) return;
00771   m_t << "<h" << header->level() 
00772       << htmlAttribsToString(header->attribs()) << ">";
00773 }
00774 
00775 void HtmlDocVisitor::visitPost(DocHtmlHeader *header) 
00776 {
00777   if (m_hide) return;
00778   m_t << "</h" << header->level() << ">\n";
00779 }
00780 
00781 void HtmlDocVisitor::visitPre(DocImage *img)
00782 {
00783   if (img->type()==DocImage::Html)
00784   {
00785     if (m_hide) return;
00786     QString baseName=img->name();
00787     int i;
00788     if ((i=baseName.findRev('/'))!=-1 || (i=baseName.findRev('\\'))!=-1)
00789     {
00790       baseName=baseName.right(baseName.length()-i-1);
00791     }
00792     m_t << "<div align=\"center\">" << endl;
00793     m_t << "<img src=\"" << img->relPath() << img->name() << "\" alt=\"" 
00794       << baseName << "\"" << ">" << endl;
00795     if (img->hasCaption())
00796     {
00797       m_t << "<p><strong>";
00798     }
00799   }
00800   else // other format -> skip
00801   {
00802     pushEnabled();
00803     m_hide=TRUE;
00804   }
00805 }
00806 
00807 void HtmlDocVisitor::visitPost(DocImage *img) 
00808 {
00809   if (img->type()==DocImage::Html)
00810   {
00811     if (m_hide) return;
00812     if (img->hasCaption())
00813     {
00814       m_t << "</strong></p>";
00815     }
00816     m_t << "</div>" << endl;
00817   }
00818   else // other format
00819   {
00820     popEnabled();
00821   }
00822 }
00823 
00824 void HtmlDocVisitor::visitPre(DocDotFile *df)
00825 {
00826   if (m_hide) return;
00827   writeDotFile(df->file(),df->relPath(),df->context());
00828   m_t << "<div align=\"center\">" << endl;
00829   if (df->hasCaption())
00830   { 
00831     m_t << "<p><strong>";
00832   }
00833 }
00834 
00835 void HtmlDocVisitor::visitPost(DocDotFile *df) 
00836 {
00837   if (m_hide) return;
00838   if (df->hasCaption())
00839   {
00840     m_t << "</strong></p>" << endl;
00841   }
00842   m_t << "</div>" << endl;
00843 }
00844 
00845 void HtmlDocVisitor::visitPre(DocLink *lnk)
00846 {
00847   if (m_hide) return;
00848   startLink(lnk->ref(),lnk->file(),lnk->relPath(),lnk->anchor());
00849 }
00850 
00851 void HtmlDocVisitor::visitPost(DocLink *) 
00852 {
00853   if (m_hide) return;
00854   endLink();
00855 }
00856 
00857 void HtmlDocVisitor::visitPre(DocRef *ref)
00858 {
00859   if (m_hide) return;
00860   if (!ref->file().isEmpty()) 
00861   {
00862     startLink(ref->ref(),ref->file(),ref->relPath(),ref->anchor());
00863   }
00864   if (!ref->hasLinkText()) filter(ref->targetTitle());
00865 }
00866 
00867 void HtmlDocVisitor::visitPost(DocRef *ref) 
00868 {
00869   if (m_hide) return;
00870   if (!ref->file().isEmpty()) endLink();
00871   //m_t << " ";
00872 }
00873 
00874 void HtmlDocVisitor::visitPre(DocSecRefItem *ref)
00875 {
00876   if (m_hide) return;
00877   QString refName=ref->file();
00878   if (refName.right(Doxygen::htmlFileExtension.length())!=
00879       QString(Doxygen::htmlFileExtension))
00880   {
00881     refName+=Doxygen::htmlFileExtension;
00882   }
00883   m_t << "<li><a href=\"" << refName << "#" << ref->anchor() << "\">";
00884 
00885 }
00886 
00887 void HtmlDocVisitor::visitPost(DocSecRefItem *) 
00888 {
00889   if (m_hide) return;
00890   m_t << "</a> ";
00891 }
00892 
00893 void HtmlDocVisitor::visitPre(DocSecRefList *)
00894 {
00895   if (m_hide) return;
00896   m_t << "<multicol cols=3>" << endl;
00897   m_t << "<ul>" << endl;
00898 }
00899 
00900 void HtmlDocVisitor::visitPost(DocSecRefList *) 
00901 {
00902   if (m_hide) return;
00903   m_t << "</ul>" << endl;
00904   m_t << "</multicol>" << endl;
00905 }
00906 
00907 //void HtmlDocVisitor::visitPre(DocLanguage *l)
00908 //{
00909 //  QString langId = Config_getEnum("OUTPUT_LANGUAGE");
00910 //  if (l->id().lower()!=langId.lower())
00911 //  {
00912 //    pushEnabled();
00913 //    m_hide = TRUE;
00914 //  }
00915 //}
00916 //
00917 //void HtmlDocVisitor::visitPost(DocLanguage *l) 
00918 //{
00919 //  QString langId = Config_getEnum("OUTPUT_LANGUAGE");
00920 //  if (l->id().lower()!=langId.lower())
00921 //  {
00922 //    popEnabled();
00923 //  }
00924 //}
00925 
00926 void HtmlDocVisitor::visitPre(DocParamSect *s)
00927 {
00928   if (m_hide) return;
00929   m_t << "<dl compact><dt><b>";
00930   switch(s->type())
00931   {
00932     case DocParamSect::Param: 
00933       m_t << theTranslator->trParameters(); break;
00934     case DocParamSect::RetVal: 
00935       m_t << theTranslator->trReturnValues(); break;
00936     case DocParamSect::Exception: 
00937       m_t << theTranslator->trExceptions(); break;
00938     case DocParamSect::TemplateParam: 
00939       /* TODO: add this 
00940       m_t << theTranslator->trTemplateParam(); break;
00941       */
00942       m_t << "Template Parameters"; break;
00943     default:
00944       ASSERT(0);
00945   }
00946   m_t << ":";
00947   m_t << "</b></dt><dd>" << endl;
00948   m_t << "  <table border=\"0\" cellspacing=\"2\" cellpadding=\"0\">" << endl;
00949 }
00950 
00951 void HtmlDocVisitor::visitPost(DocParamSect *)
00952 {
00953   if (m_hide) return;
00954   m_t << "  </table>" << endl;
00955   m_t << "</dl>" << endl;
00956 }
00957 
00958 void HtmlDocVisitor::visitPre(DocParamList *pl)
00959 {
00960   if (m_hide) return;
00961   m_t << "    <tr><td valign=\"top\">";
00962   if (pl->direction()!=DocParamSect::Unspecified)
00963   {
00964     m_t << "<tt>[";
00965     if (pl->direction()==DocParamSect::In)
00966     {
00967       m_t << "in";
00968     }
00969     else if (pl->direction()==DocParamSect::Out)
00970     {
00971       m_t << "out";
00972     }
00973     else if (pl->direction()==DocParamSect::InOut)
00974     {
00975       m_t << "in,out";
00976     }
00977     m_t << "]</tt>&nbsp;";
00978   }
00979   m_t << "</td><td valign=\"top\"><em>";
00980   //QStrListIterator li(pl->parameters());
00981   //const char *s;
00982   QListIterator<DocNode> li(pl->parameters());
00983   DocNode *param;
00984   bool first=TRUE;
00985   for (li.toFirst();(param=li.current());++li)
00986   {
00987     if (!first) m_t << ","; else first=FALSE;
00988     if (param->kind()==DocNode::Kind_Word)
00989     {
00990       visit((DocWord*)param); 
00991     }
00992     else if (param->kind()==DocNode::Kind_LinkedWord)
00993     {
00994       visit((DocLinkedWord*)param); 
00995     }
00996   }
00997   m_t << "</em>&nbsp;</td><td>";
00998 }
00999 
01000 void HtmlDocVisitor::visitPost(DocParamList *)
01001 {
01002   if (m_hide) return;
01003   m_t << "</td></tr>" << endl;
01004 }
01005 
01006 void HtmlDocVisitor::visitPre(DocXRefItem *x)
01007 {
01008   if (m_hide) return;
01009   bool anonymousEnum = x->file()=="@";
01010   if (!anonymousEnum)
01011   {
01012     m_t << "<dl compact><dt><b><a class=\"el\" href=\"" 
01013         << x->relPath() << x->file() << Doxygen::htmlFileExtension 
01014         << "#" << x->anchor() << "\">";
01015   }
01016   else 
01017   {
01018     m_t << "<dl compact><dt><b>";
01019   }
01020   filter(x->title());
01021   m_t << ":";
01022   if (!anonymousEnum) m_t << "</a>";
01023   m_t << "</b></dt><dd>";
01024 }
01025 
01026 void HtmlDocVisitor::visitPost(DocXRefItem *)
01027 {
01028   if (m_hide) return;
01029   m_t << "</dd></dl>" << endl;
01030 }
01031 
01032 void HtmlDocVisitor::visitPre(DocInternalRef *ref)
01033 {
01034   if (m_hide) return;
01035   startLink(0,ref->file(),ref->relPath(),ref->anchor());
01036 }
01037 
01038 void HtmlDocVisitor::visitPost(DocInternalRef *) 
01039 {
01040   if (m_hide) return;
01041   endLink();
01042   m_t << " ";
01043 }
01044 
01045 void HtmlDocVisitor::visitPre(DocCopy *)
01046 {
01047 }
01048 
01049 void HtmlDocVisitor::visitPost(DocCopy *)
01050 {
01051 }
01052 
01053 void HtmlDocVisitor::visitPre(DocText *)
01054 {
01055 }
01056 
01057 void HtmlDocVisitor::visitPost(DocText *)
01058 {
01059 }
01060 
01061 void HtmlDocVisitor::filter(const char *str)
01062 { 
01063   if (str==0) return;
01064   const char *p=str;
01065   char c;
01066   while (*p)
01067   {
01068     c=*p++;
01069     switch(c)
01070     {
01071       case '<':  m_t << "&lt;"; break;
01072       case '>':  m_t << "&gt;"; break;
01073       case '&':  m_t << "&amp;"; break;
01074       default:   m_t << c;
01075     }
01076   }
01077 }
01078 
01081 void HtmlDocVisitor::filterQuotedCdataAttr(const char* str)
01082 {
01083   if (str==0) return;
01084   const char *p=str;
01085   char c;
01086   while (*p)
01087   {
01088     c=*p++;
01089     switch(c)
01090     {
01091       case '&':  m_t << "&amp;"; break;
01092       case '"':  m_t << "&quot;"; break;
01093        // For SGML compliance, and given the SGML declaration for HTML syntax,
01094        // it's enough to replace these two, provided that the declaration
01095        // for the HTML version we generate (and as supported by the browser)
01096        // specifies that all the other symbols used in rawVal are
01097        // within the right charachter class (i.e., they're not
01098        // some multinational weird charachters not in the BASESET).
01099        // We assume that 1) the browser will support whatever is remaining
01100        // in the formula and 2) the TeX formulae are generally governed
01101        // by even stricter charachter restrictions so it should be enough.
01102        //
01103        // On some incompliant browsers, additional translation of
01104        // '>' and '<' into "&gt;" and "&lt;", respectively, might be needed;
01105        // but I'm unaware of particular modern (last 4 years) versions
01106        // with such problems, so let's not do it for performance.
01107        // Also, some brousers will (wrongly) not process the entity references
01108        // inside the attribute value and show the &...; form instead,  
01109        // so we won't create entites unless necessary to minimize clutter there.
01110        // --vassilii 
01111       default:   m_t << c;
01112     }
01113   }
01114 }
01115 
01116 void HtmlDocVisitor::startLink(const QString &ref,const QString &file,
01117                                const QString &relPath,const QString &anchor,
01118                                const QString &tooltip)
01119 {
01120   QCString *dest;
01121   if (!ref.isEmpty()) // link to entity imported via tag file
01122   {
01123     m_t << "<a class=\"elRef\" ";
01124     m_t << "doxygen=\"" << ref << ":";
01125     if ((dest=Doxygen::tagDestinationDict[ref])) m_t << *dest << "/";
01126     m_t << "\" ";
01127   }
01128   else // local link
01129   {
01130     m_t << "<a class=\"el\" ";
01131   }
01132   m_t << "href=\"";
01133   if (!ref.isEmpty())
01134   {
01135     if ((dest=Doxygen::tagDestinationDict[ref])) m_t << *dest << "/";
01136   }
01137   else
01138   {
01139     m_t << relPath;
01140   }
01141   if (!file.isEmpty()) m_t << file << Doxygen::htmlFileExtension;
01142   if (!anchor.isEmpty()) m_t << "#" << anchor;
01143   m_t << "\"";
01144   if (!tooltip.isEmpty()) m_t << " title=\"" << tooltip << "\"";
01145   m_t << ">";
01146 }
01147 
01148 void HtmlDocVisitor::endLink()
01149 {
01150   m_t << "</a>";
01151 }
01152 
01153 void HtmlDocVisitor::pushEnabled()
01154 {
01155   m_enabled.push(new bool(m_hide));
01156 }
01157 
01158 void HtmlDocVisitor::popEnabled()
01159 {
01160   bool *v=m_enabled.pop();
01161   ASSERT(v!=0);
01162   m_hide = *v;
01163   delete v;
01164 }
01165 
01166 void HtmlDocVisitor::writeDotFile(const QString &fileName,const QString &relPath,
01167                                   const QString &context)
01168 {
01169   QString baseName=fileName;
01170   int i;
01171   if ((i=baseName.findRev('/'))!=-1)
01172   {
01173     baseName=baseName.right(baseName.length()-i-1);
01174   } 
01175   QString outDir = Config_getString("HTML_OUTPUT");
01176   writeDotGraphFromFile(fileName,outDir,baseName,BITMAP);
01177   QString mapName = baseName+".map";
01178   QString mapFile = fileName+".map";
01179   m_t << "<img src=\"" << relPath << baseName << "." 
01180     << Config_getEnum("DOT_IMAGE_FORMAT") << "\" alt=\""
01181     << baseName << "\" border=\"0\" usemap=\"#" << mapName << "\">" << endl;
01182   QString imap = getDotImageMapFromFile(fileName,outDir,relPath.data(),context);
01183   m_t << "<map name=\"" << mapName << "\">" << imap << "</map>" << endl;
01184 }
01185 
01186 void HtmlDocVisitor::writeMscFile(const QString &fileName,const QString &relPath,
01187                                   const QString &context)
01188 {
01189   QString baseName=fileName;
01190   int i;
01191   if ((i=baseName.findRev('/'))!=-1)
01192   {
01193     baseName=baseName.right(baseName.length()-i-1);
01194   } 
01195   QString outDir = Config_getString("HTML_OUTPUT");
01196   writeMscGraphFromFile(fileName,outDir,baseName,MSC_BITMAP);
01197   QString mapName = baseName+".map";
01198   QString mapFile = fileName+".map";
01199   m_t << "<img src=\"" << relPath << baseName << ".png\" alt=\""
01200     << baseName << "\" border=\"0\" usemap=\"#" << mapName << "\">" << endl;
01201   QString imap = getMscImageMapFromFile(fileName,outDir,relPath.data(),context);
01202   m_t << "<map name=\"" << mapName << "\">" << imap << "</map>" << endl;
01203 }
01204 



Generated on Mon Mar 31 10:58:39 2008 by  doxygen 1.5.1