TClassDocOutput.cxx

Go to the documentation of this file.
00001 // @(#)root/html:$Id: TClassDocOutput.cxx 31521 2009-12-03 13:05:56Z axel $
00002 // Author: Axel Naumann 2007-01-09
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TClassDocOutput.h"
00013 
00014 #include "TBaseClass.h"
00015 #include "TClassEdit.h"
00016 #include "TDataMember.h"
00017 #include "TMethodArg.h"
00018 #include "TDataType.h"
00019 #include "TDocInfo.h"
00020 #include "TDocParser.h"
00021 #include "TEnv.h"
00022 #include "TError.h"
00023 #include "THtml.h"
00024 #include "TMethod.h"
00025 #include "TROOT.h"
00026 #include "TSystem.h"
00027 #include "TVirtualPad.h"
00028 #include "TVirtualMutex.h"
00029 #include "Riostream.h"
00030 #include <sstream>
00031 
00032 //______________________________________________________________________________
00033 //
00034 // Write the documentation for a class or namespace. The documentation is
00035 // parsed by TDocParser and then passed to TClassDocOutput to generate
00036 // the class doc header, the class description, members overview, and method
00037 // documentation. All generic output functionality is in TDocOutput; it is
00038 // re-used in this derived class.
00039 // 
00040 // You usually do not use this class yourself; it is invoked indirectly by
00041 // THtml. Customization of the output should happen via the interfaces defined
00042 // by THtml.
00043 //______________________________________________________________________________
00044 
00045 
00046 ClassImp(TClassDocOutput);
00047 
00048 //______________________________________________________________________________
00049 TClassDocOutput::TClassDocOutput(THtml& html, TClass* cl, TList* typedefs):
00050    TDocOutput(html), fHierarchyLines(0), fCurrentClass(cl),
00051    fCurrentClassesTypedefs(typedefs), fParser(0)
00052 {
00053    // Create an object given the invoking THtml object, and the TClass
00054    // object that we will generate output for.
00055 
00056    fParser = new TDocParser(*this, fCurrentClass);
00057 }
00058 
00059 //______________________________________________________________________________
00060 TClassDocOutput::~TClassDocOutput()
00061 {
00062    // Destructor, deletes fParser
00063    delete fParser;
00064 }
00065 
00066 //______________________________________________________________________________
00067 void TClassDocOutput::Class2Html(Bool_t force)
00068 {
00069 // Create HTML files for a single class.
00070 //
00071 
00072    gROOT->GetListOfGlobals(kTRUE);
00073 
00074    // create a filename
00075    TString filename(fCurrentClass->GetName());
00076    NameSpace2FileName(filename);
00077 
00078    gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
00079 
00080    filename += ".html";
00081 
00082    if (!force && !IsModified(fCurrentClass, kSource)
00083        && !IsModified(fCurrentClass, kDoc)) {
00084       Printf(fHtml->GetCounterFormat(), "-no change-", fHtml->GetCounter(), filename.Data());
00085       return;
00086    }
00087 
00088    // open class file
00089    std::ofstream classFile(filename);
00090 
00091    if (!classFile.good()) {
00092       Error("Make", "Can't open file '%s' !", filename.Data());
00093       return;
00094    }
00095 
00096    Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
00097 
00098    // write a HTML header for the classFile file
00099    WriteHtmlHeader(classFile, fCurrentClass->GetName(), "", fCurrentClass);
00100    WriteClassDocHeader(classFile);
00101 
00102    // copy .h file to the Html output directory
00103    TString declf;
00104    if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declf))
00105       CopyHtmlFile(declf);
00106 
00107    // process a '.cxx' file
00108    fParser->Parse(classFile);
00109 
00110    // write classFile footer
00111    WriteHtmlFooter(classFile, "",
00112       fParser->GetSourceInfo(TDocParser::kInfoLastUpdate),
00113       fParser->GetSourceInfo(TDocParser::kInfoAuthor),
00114       fParser->GetSourceInfo(TDocParser::kInfoCopyright));
00115 }
00116 
00117 //______________________________________________________________________________
00118 void TClassDocOutput::ListFunctions(std::ostream& classFile)
00119 {
00120    // Write the list of functions
00121 
00122    // loop to get a pointers to method names
00123 
00124    classFile << endl << "<div id=\"functions\">" << endl;
00125    TString mangled(fCurrentClass->GetName());
00126    NameSpace2FileName(mangled);
00127    classFile << "<h2><a id=\"" << mangled
00128       << ":Function_Members\"></a>Function Members (Methods)</h2>" << endl;
00129 
00130    const char* tab4nbsp="&nbsp;&nbsp;&nbsp;&nbsp;";
00131    TString declFile;
00132    fHtml->GetDeclFileName(fCurrentClass, kFALSE, declFile);
00133    if (fCurrentClass->Property() & kIsAbstract)
00134       classFile << "&nbsp;<br /><b>"
00135                 << tab4nbsp << "This is an abstract class, constructors will not be documented.<br />" << endl
00136                 << tab4nbsp << "Look at the <a href=\""
00137                 << gSystem->BaseName(declFile)
00138                 << "\">header</a> to check for available constructors.</b><br />" << endl;
00139 
00140    Int_t minAccess = 0;
00141    if (fHtml->IsNamespace(fCurrentClass))
00142       minAccess = TDocParser::kPublic;
00143    for (Int_t access = TDocParser::kPublic; access >= minAccess; --access) {
00144 
00145       const TList* methods = fParser->GetMethods((TDocParser::EAccess)access);
00146       if (methods->GetEntries() == 0)
00147          continue;
00148 
00149       classFile << "<div class=\"access\" ";
00150       const char* accessID [] = {"priv", "prot", "publ"};
00151       const char* accesstxt[] = {"private", "protected", "public"};
00152 
00153       classFile << "id=\"func" << accessID[access] << "\"><b>" 
00154          << accesstxt[access] << ":</b>" << endl
00155          << "<table class=\"func\" id=\"tabfunc" << accessID[access] << "\" cellspacing=\"0\">" << endl;
00156 
00157       TIter iMethWrap(methods);
00158       TDocMethodWrapper *methWrap = 0;
00159       while ((methWrap = (TDocMethodWrapper*) iMethWrap())) {
00160          const TMethod* method = methWrap->GetMethod();
00161 
00162          // it's a c'tor - Cint stores the class name as return type
00163          Bool_t isctor = (!strcmp(method->GetName(), method->GetReturnTypeName()));
00164          // it's a d'tor - Cint stores "void" as return type
00165          Bool_t isdtor = (!isctor && method->GetName()[0] == '~');
00166 
00167          classFile << "<tr class=\"func";
00168          if (method->GetClass() != fCurrentClass)
00169             classFile << "inh";
00170          classFile << "\"><td class=\"funcret\">";
00171          if (kIsVirtual & method->Property()) {
00172             if (!isdtor)
00173                classFile << "virtual ";
00174             else
00175                classFile << " virtual";
00176          }
00177 
00178          if (kIsStatic & method->Property())
00179             classFile << "static ";
00180 
00181          if (!isctor && !isdtor)
00182             fParser->DecorateKeywords(classFile, method->GetReturnTypeName());
00183 
00184          TString mangledM(method->GetClass()->GetName());
00185          NameSpace2FileName(mangledM);
00186          classFile << "</td><td class=\"funcname\"><a class=\"funcname\" href=\"";
00187          if (method->GetClass() != fCurrentClass) {
00188             TString htmlFile;
00189             fHtml->GetHtmlFileName(method->GetClass(), htmlFile);
00190             classFile << htmlFile;
00191          }
00192          classFile << "#" << mangledM;
00193          classFile << ":";
00194          mangledM = method->GetName();
00195          NameSpace2FileName(mangledM);
00196          Int_t overloadIdx = methWrap->GetOverloadIdx();
00197          if (overloadIdx) {
00198             mangledM += "%";
00199             mangledM += overloadIdx;
00200          }
00201          classFile << mangledM << "\">";
00202          if (method->GetClass() != fCurrentClass) {
00203             classFile << "<span class=\"baseclass\">";
00204             ReplaceSpecialChars(classFile, method->GetClass()->GetName());
00205             classFile << "::</span>";
00206          }
00207          ReplaceSpecialChars(classFile, method->GetName());
00208          classFile << "</a>";
00209 
00210          fParser->DecorateKeywords(classFile, const_cast<TMethod*>(method)->GetSignature());
00211          bool propSignal = false;
00212          bool propMenu   = false;
00213          bool propToggle = false;
00214          bool propGetter = false;
00215          if (method->GetTitle()) {
00216             propSignal = (strstr(method->GetTitle(), "*SIGNAL*"));
00217             propMenu   = (strstr(method->GetTitle(), "*MENU*"));
00218             propToggle = (strstr(method->GetTitle(), "*TOGGLE*"));
00219             propGetter = (strstr(method->GetTitle(), "*GETTER"));
00220             if (propSignal || propMenu || propToggle || propGetter) {
00221                classFile << "<span class=\"funcprop\">";
00222                if (propSignal) classFile << "<abbr title=\"emits a signal\">SIGNAL</abbr> ";
00223                if (propMenu) classFile << "<abbr title=\"has a popup menu entry\">MENU</abbr> ";
00224                if (propToggle) classFile << "<abbr title=\"toggles a state\">TOGGLE</abbr> ";
00225                if (propGetter) {
00226                   TString getter(method->GetTitle());
00227                   Ssiz_t posGetter = getter.Index("*GETTER=");
00228                   getter.Remove(0, posGetter + 8);
00229                   classFile << "<abbr title=\"use " + getter + "() as getter\">GETTER</abbr> ";
00230                }
00231                classFile << "</span>";
00232             }
00233          }
00234          classFile << "</td></tr>" << endl;
00235       }
00236       classFile << endl << "</table></div>" << endl;
00237    }
00238 
00239    classFile << "</div>" << endl; // class="functions"
00240 }
00241 
00242 //______________________________________________________________________________
00243 void  TClassDocOutput::ListDataMembers(std::ostream& classFile)
00244 {
00245    // Write the list of data members and enums
00246 
00247    // make a loop on data members
00248    Bool_t haveDataMembers = (fParser->GetDataMembers(TDocParser::kPrivate)->GetEntries() || 
00249                              fParser->GetDataMembers(TDocParser::kProtected)->GetEntries() || 
00250                              fParser->GetDataMembers(TDocParser::kPublic)->GetEntries() || 
00251                              fParser->GetEnums(TDocParser::kPublic)->GetEntries() || 
00252                              fParser->GetEnums(TDocParser::kProtected)->GetEntries() || 
00253                              fParser->GetEnums(TDocParser::kPrivate)->GetEntries());
00254 
00255    if (!haveDataMembers) return;
00256 
00257    classFile << endl << "<div id=\"datamembers\">" << endl;
00258    TString mangled(fCurrentClass->GetName());
00259    NameSpace2FileName(mangled);
00260    classFile << "<h2><a name=\"" << mangled
00261       << ":Data_Members\"></a>Data Members</h2>" << endl;
00262 
00263    for (Int_t access = 5; access >= 0 && !fHtml->IsNamespace(fCurrentClass); --access) {
00264       const TList* datamembers = 0;
00265       if (access > 2) datamembers = fParser->GetEnums((TDocParser::EAccess) (access - 3));
00266       else datamembers = fParser->GetDataMembers((TDocParser::EAccess) access);
00267       if (datamembers->GetEntries() == 0)
00268          continue;
00269 
00270       classFile << "<div class=\"access\" ";
00271       const char* what = "data";
00272       if (access > 2) what = "enum";
00273       const char* accessID [] = {"priv", "prot", "publ"};
00274       const char* accesstxt[] = {"private", "protected", "public"};
00275 
00276       classFile << "id=\"" << what << accessID[access%3] << "\"><b>" 
00277          << accesstxt[access%3] << ":</b>" << endl
00278          << "<table class=\"data\" id=\"tab" << what << accessID[access%3] << "\" cellspacing=\"0\">" << endl;
00279 
00280       TIter iDM(datamembers);
00281       TDataMember *member = 0;
00282       TString prevEnumName;
00283       Bool_t prevIsInh = kTRUE;
00284 
00285       while ((member = (TDataMember*) iDM())) {
00286          Bool_t haveNewEnum = access > 2 && prevEnumName != member->GetTypeName();
00287          if (haveNewEnum) {
00288             if (prevEnumName.Length()) {
00289                classFile << "<tr class=\"data";
00290                if (prevIsInh)
00291                   classFile << "inh";
00292                classFile << "\"><td class=\"datatype\">};</td><td></td><td></td></tr>" << endl;
00293             }
00294             prevEnumName = member->GetTypeName();
00295          }
00296 
00297          classFile << "<tr class=\"data";
00298          prevIsInh = (member->GetClass() != fCurrentClass);
00299          if (prevIsInh)
00300             classFile << "inh";
00301          classFile << "\"><td class=\"datatype\">";
00302          if (haveNewEnum) {
00303             TString enumName(member->GetTypeName());
00304             TString myScope(fCurrentClass->GetName());
00305             myScope += "::";
00306             enumName.ReplaceAll(myScope, "");
00307             if (enumName.EndsWith("::"))
00308                enumName += "<i>[unnamed]</i>";
00309             Ssiz_t startClassName = 0;
00310             if (!enumName.BeginsWith("enum "))
00311                classFile << "enum ";
00312             else 
00313                startClassName = 5;
00314             
00315             Ssiz_t endClassName = enumName.Last(':'); // need template handling here!
00316             if (endClassName != kNPOS && endClassName > 0 && enumName[endClassName - 1] == ':') {
00317                // TClass* cl = fHtml->GetClass(TString(enumName(startClassName, endClassName - startClassName - 1)));
00318                TSubString substr(enumName(startClassName, endClassName - startClassName + 1));
00319                // if (cl)
00320                   // ReferenceEntity(substr, cl);
00321                enumName.Insert(substr.Start() + substr.Length(), "</span>");
00322                enumName.Insert(substr.Start(), "<span class=\"baseclass\">");
00323             }
00324             classFile << enumName << " { ";
00325          } else
00326             if (access < 3) {
00327                if (member->Property() & G__BIT_ISSTATIC)
00328                   classFile << "static ";
00329                std::string shortTypeName(fHtml->ShortType(member->GetFullTypeName()));
00330                fParser->DecorateKeywords(classFile, shortTypeName.c_str());
00331             }
00332 
00333          TString mangledM(member->GetClass()->GetName());
00334          NameSpace2FileName(mangledM);
00335          classFile << "</td><td class=\"dataname\"><a ";
00336          if (member->GetClass() != fCurrentClass) {
00337             classFile << "href=\"";
00338             TString htmlFile;
00339             fHtml->GetHtmlFileName(member->GetClass(), htmlFile);
00340             classFile << htmlFile << "#";
00341          } else
00342             classFile << "name=\"";
00343          classFile << mangledM;
00344          classFile << ":";
00345          mangledM = member->GetName();
00346          NameSpace2FileName(mangledM);
00347          classFile << mangledM << "\">";
00348          if (member->GetClass() == fCurrentClass)
00349             classFile << "</a>";
00350          if (access < 3 && member->GetClass() != fCurrentClass) {
00351             classFile << "<span class=\"baseclass\">";
00352             ReplaceSpecialChars(classFile, member->GetClass()->GetName());
00353             classFile << "::</span>";
00354          }
00355          ReplaceSpecialChars(classFile, member->GetName());
00356 
00357          // Add the dimensions to "array" members
00358          for (Int_t indx = 0; indx < member->GetArrayDim(); ++indx)
00359             if (member->GetMaxIndex(indx) <= 0)
00360                break;
00361             else
00362                classFile << "[" << member->GetMaxIndex(indx) << "]";
00363 
00364          if (member->GetClass() != fCurrentClass)
00365             classFile << "</a>";
00366          classFile << "</td>";
00367          if (member->GetTitle() && member->GetTitle()[0]) {
00368             classFile << "<td class=\"datadesc\">";
00369             ReplaceSpecialChars(classFile, member->GetTitle());
00370          } else classFile << "<td>";
00371          classFile << "</td></tr>" << endl;
00372       } // for members
00373 
00374       if (prevEnumName.Length()) {
00375          classFile << "<tr class=\"data";
00376          if (prevIsInh)
00377             classFile << "inh";
00378          classFile << "\"><td class=\"datatype\">};</td><td></td><td></td></tr>" << endl;
00379       }
00380       classFile << endl << "</table></div>" << endl;
00381    } // for access
00382 
00383    classFile << "</div>" << endl; // datamembers
00384 }
00385 
00386 //______________________________________________________________________________
00387 Bool_t TClassDocOutput::ClassDotCharts(std::ostream& out)
00388 {
00389 // This function builds the class charts for one class in GraphViz/Dot format,
00390 // i.e. the inheritance diagram, the include dependencies, and the library
00391 // dependency.
00392 //
00393 // Input: out      - output file stream
00394 
00395    if (!fHtml->HaveDot()) 
00396       return kFALSE;
00397 
00398    TString title(fCurrentClass->GetName());
00399    NameSpace2FileName(title);
00400 
00401    TString dir("inh");
00402    gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
00403    gSystem->MakeDirectory(dir);
00404 
00405    dir = "inhmem";
00406    gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
00407    gSystem->MakeDirectory(dir);
00408 
00409    dir = "incl";
00410    gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
00411    gSystem->MakeDirectory(dir);
00412 
00413    dir = "lib";
00414    gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
00415    gSystem->MakeDirectory(dir);
00416 
00417    TString filenameInh(title);
00418    gSystem->PrependPathName("inh", filenameInh);
00419    gSystem->PrependPathName(fHtml->GetOutputDir(), filenameInh);
00420    filenameInh += "_Inh";
00421    if (!CreateDotClassChartInh(filenameInh + ".dot") ||
00422       !RunDot(filenameInh, &out))
00423    return kFALSE;
00424 
00425    TString filenameInhMem(title);
00426    gSystem->PrependPathName("inhmem", filenameInhMem);
00427    gSystem->PrependPathName(fHtml->GetOutputDir(), filenameInhMem);
00428    filenameInhMem += "_InhMem";
00429    if (CreateDotClassChartInhMem(filenameInhMem + ".dot"))
00430       RunDot(filenameInhMem, &out);
00431 
00432    TString filenameIncl(title);
00433    gSystem->PrependPathName("incl", filenameIncl);
00434    gSystem->PrependPathName(fHtml->GetOutputDir(), filenameIncl);
00435    filenameIncl += "_Incl";
00436    if (CreateDotClassChartIncl(filenameIncl + ".dot"))
00437       RunDot(filenameIncl, &out);
00438 
00439    TString filenameLib(title);
00440    gSystem->PrependPathName("lib", filenameLib);
00441    gSystem->PrependPathName(fHtml->GetOutputDir(), filenameLib);
00442    filenameLib += "_Lib";
00443    if (CreateDotClassChartLib(filenameLib + ".dot"))
00444       RunDot(filenameLib, &out);
00445 
00446    out << "<div class=\"tabs\">" << endl
00447        << "<a id=\"img" << title << "_Inh\" class=\"tabsel\" href=\"inh/" << title << "_Inh.png\" onclick=\"javascript:return SetImg('Charts','inh/" << title << "_Inh.png');\">Inheritance</a>" << endl
00448        << "<a id=\"img" << title << "_InhMem\" class=\"tab\" href=\"inhmem/" << title << "_InhMem.png\" onclick=\"javascript:return SetImg('Charts','inhmem/" << title << "_InhMem.png');\">Inherited Members</a>" << endl
00449        << "<a id=\"img" << title << "_Incl\" class=\"tab\" href=\"incl/" << title << "_Incl.png\" onclick=\"javascript:return SetImg('Charts','incl/" << title << "_Incl.png');\">Includes</a>" << endl
00450        << "<a id=\"img" << title << "_Lib\" class=\"tab\" href=\"lib/" << title << "_Lib.png\" onclick=\"javascript:return SetImg('Charts','lib/" << title << "_Lib.png');\">Libraries</a><br/>" << endl
00451        << "</div><div class=\"classcharts\"><div class=\"classchartswidth\"></div>" << endl
00452        << "<img id=\"Charts\" alt=\"Class Charts\" class=\"classcharts\" usemap=\"#Map" << title << "_Inh\" src=\"inh/" << title << "_Inh.png\"/></div>" << endl;
00453 
00454    return kTRUE;
00455 }
00456 
00457 //______________________________________________________________________________
00458 void TClassDocOutput::ClassHtmlTree(std::ostream& out, TClass * classPtr,
00459                           ETraverse dir, int depth)
00460 {
00461 // This function builds the class tree for one class in HTML
00462 // (inherited and succeeding classes, called recursively)
00463 //
00464 //
00465 // Input: out      - output file stream
00466 //        classPtr - pointer to the class
00467 //        dir      - direction to traverse tree: up, down or both
00468 //
00469 
00470    if (dir == kBoth) {
00471       out << "<!--INHERITANCE TREE-->" << endl;
00472 
00473       // draw class tree into nested tables recursively
00474       out << "<table><tr><td width=\"10%\"></td><td width=\"70%\">"
00475           << "<a href=\"ClassHierarchy.html\">Inheritance Chart</a>:</td></tr>";
00476       out << "<tr class=\"inhtree\"><td width=\"10%\"></td><td width=\"70%\">";
00477 
00478       out << "<table class=\"inhtree\"><tr><td>" << endl;
00479       out << "<table width=\"100%\" border=\"0\" ";
00480       out << "cellpadding =\"0\" cellspacing=\"2\"><tr>" << endl;
00481    } else {
00482       out << "<table><tr>";
00483    }
00484 
00485    ////////////////////////////////////////////////////////
00486    // Loop up to mother classes
00487    if (dir == kUp || dir == kBoth) {
00488 
00489       // make a loop on base classes
00490       TBaseClass *inheritFrom;
00491       TIter nextBase(classPtr->GetListOfBases());
00492 
00493       UInt_t bgcolor=255-depth*8;
00494       Bool_t first = kTRUE;
00495       while ((inheritFrom = (TBaseClass *) nextBase())) {
00496 
00497          if (first) {
00498             out << "<td><table><tr>" << endl;
00499             first = kFALSE;
00500          } else
00501             out << "</tr><tr>" << endl;
00502          out << "<td bgcolor=\""
00503             << Form("#%02x%02x%02x", bgcolor, bgcolor, bgcolor)
00504             << "\" align=\"right\">" << endl;
00505          // get a class
00506          TClass *classInh = fHtml->GetClass((const char *) inheritFrom->GetName());
00507          if (classInh)
00508             ClassHtmlTree(out, classInh, kUp, depth+1);
00509          else
00510             out << "<tt>"
00511                 << (const char *) inheritFrom->GetName()
00512                 << "</tt>";
00513          out << "</td>"<< endl;
00514       }
00515       if (!first) {
00516          out << "</tr></table></td>" << endl; // put it in additional row in table
00517          out << "<td>&larr;</td>";
00518       }
00519    }
00520 
00521    out << "<td>" << endl; // put it in additional row in table
00522    ////////////////////////////////////////////////////////
00523    // Output Class Name
00524 
00525    const char *className = classPtr->GetName();
00526    TString htmlFile;
00527    fHtml->GetHtmlFileName(classPtr, htmlFile);
00528    TString anchor(className);
00529    NameSpace2FileName(anchor);
00530 
00531    if (dir == kUp) {
00532       if (htmlFile) {
00533          out << "<center><tt><a name=\"" << anchor;
00534          out << "\" href=\"" << htmlFile << "\">";
00535          ReplaceSpecialChars(out, className);
00536          out << "</a></tt></center>" << endl;
00537       } else
00538          ReplaceSpecialChars(out, className);
00539    }
00540 
00541    if (dir == kBoth) {
00542       if (htmlFile.Length()) {
00543          out << "<center><big><b><tt><a name=\"" << anchor;
00544          out << "\" href=\"" << htmlFile << "\">";
00545          ReplaceSpecialChars(out, className);
00546          out << "</a></tt></b></big></center>" << endl;
00547       } else
00548          ReplaceSpecialChars(out, className);
00549    }
00550 
00551    out << "</td>" << endl; // put it in additional row in table
00552 
00553    ////////////////////////////////////////////////////////
00554    // Loop down to child classes
00555 
00556    if (dir == kDown || dir == kBoth) {
00557 
00558       // 1. make a list of class names
00559       // 2. use DescendHierarchy
00560 
00561       out << "<td><table><tr>" << endl;
00562       fHierarchyLines = 0;
00563       DescendHierarchy(out,classPtr,10);
00564 
00565       out << "</tr></table>";
00566       if (dir==kBoth && fHierarchyLines>=10)
00567          out << "</td><td align=\"left\">&nbsp;<a href=\"ClassHierarchy.html\">[more...]</a>";
00568       out<<"</td>" << endl;
00569 
00570       // free allocated memory
00571    }
00572 
00573    out << "</tr></table>" << endl;
00574    if (dir == kBoth)
00575       out << "</td></tr></table></td></tr></table>"<<endl;
00576 }
00577 
00578 
00579 //______________________________________________________________________________
00580 void TClassDocOutput::ClassTree(TVirtualPad * psCanvas, Bool_t force)
00581 {
00582 // It makes a graphical class tree
00583 //
00584 //
00585 // Input: psCanvas - pointer to the current canvas
00586 //        classPtr - pointer to the class
00587 //
00588 
00589    if (!psCanvas || !fCurrentClass)
00590       return;
00591 
00592    TString filename(fCurrentClass->GetName());
00593    NameSpace2FileName(filename);
00594 
00595    gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
00596 
00597 
00598    filename += "_Tree.pdf";
00599 
00600    if (IsModified(fCurrentClass, kTree) || force) {
00601       // TCanvas already prints pdf being saved
00602       // Printf(fHtml->GetCounterFormat(), "", "", filename);
00603       fCurrentClass->Draw("same");
00604       Int_t saveErrorIgnoreLevel = gErrorIgnoreLevel;
00605       gErrorIgnoreLevel = kWarning;
00606       psCanvas->SaveAs(filename);
00607       gErrorIgnoreLevel = saveErrorIgnoreLevel;
00608    } else
00609       Printf(fHtml->GetCounterFormat(), "-no change-", "", filename.Data());
00610 }
00611 
00612 //______________________________________________________________________________
00613 Bool_t TClassDocOutput::CreateDotClassChartInh(const char* filename)
00614 {
00615 // Build the class tree for one class in GraphViz/Dot format
00616 //
00617 //
00618 // Input: filename - output dot file incl. path
00619 
00620    std::ofstream outdot(filename);
00621    outdot << "strict digraph G {" << endl
00622       << "rankdir=RL;" << endl
00623       << "ranksep=2;" << endl
00624       << "nodesep=0;" << endl
00625       << "size=\"8,10\";" << endl
00626       << "ratio=auto;" << endl
00627       << "margin=0;" << endl
00628       << "node [shape=plaintext,fontsize=40,width=4,height=0.75];" << endl
00629       << "\"" << fCurrentClass->GetName() << "\" [shape=ellipse];" << endl;
00630 
00631    std::stringstream ssDep;
00632    std::list<TClass*> writeBasesFor;
00633    writeBasesFor.push_back(fCurrentClass);
00634    Bool_t haveBases = fCurrentClass->GetListOfBases() && 
00635       fCurrentClass->GetListOfBases()->GetSize();
00636    if (haveBases) {
00637       outdot << "{" << endl;
00638       while (!writeBasesFor.empty()) {
00639          TClass* cl = writeBasesFor.front();
00640          writeBasesFor.pop_front();
00641          if (cl != fCurrentClass) {
00642             outdot << "  \"" << cl->GetName() << "\"";
00643             const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
00644             if (htmlFileName)
00645                outdot << " [URL=\"" << htmlFileName << "\"]";
00646             outdot << ";" << endl;
00647          }
00648          if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
00649             ssDep << "  \"" << cl->GetName() << "\" -> {";
00650             TIter iBase(cl->GetListOfBases());
00651             TBaseClass* base = 0;
00652             while ((base = (TBaseClass*)iBase())) {
00653                ssDep << " \"" << base->GetName() << "\";";
00654                writeBasesFor.push_back(base->GetClassPointer());
00655             }
00656             ssDep << "}" << endl;
00657          }
00658       }
00659       outdot << "}" << endl; // cluster
00660    }
00661 
00662    std::map<TClass*, Int_t> derivesFromMe;
00663    std::map<TClass*, unsigned int> entriesPerDerived;
00664    std::set<TClass*> wroteNode;
00665    wroteNode.insert(fCurrentClass);
00666    static const unsigned int maxClassesPerDerived = 20;
00667    fHtml->GetDerivedClasses(fCurrentClass, derivesFromMe);
00668    outdot << "{" << endl;
00669    for (Int_t level = 1; kTRUE; ++level) {
00670       Bool_t levelExists = kFALSE;
00671       for (std::map<TClass*, Int_t>::iterator iDerived = derivesFromMe.begin();
00672          iDerived != derivesFromMe.end(); ++iDerived) {
00673          if (iDerived->second != level) continue;
00674          levelExists = kTRUE;
00675          TIter iBaseOfDerived(iDerived->first->GetListOfBases());
00676          TBaseClass* baseDerived = 0;
00677          Bool_t writeNode = kFALSE;
00678          TClass* writeAndMoreFor = 0;
00679          while ((baseDerived = (TBaseClass*) iBaseOfDerived())) {
00680             TClass* clBaseDerived = baseDerived->GetClassPointer();
00681             if (clBaseDerived->InheritsFrom(fCurrentClass) 
00682                && wroteNode.find(clBaseDerived) != wroteNode.end()) {
00683                unsigned int& count = entriesPerDerived[clBaseDerived];
00684                if (count < maxClassesPerDerived) {
00685                   writeNode = kTRUE;
00686                   ssDep << "\"" << iDerived->first->GetName() << "\" -> \""
00687                      << clBaseDerived->GetName() << "\";" << endl;
00688                   ++count;
00689                } else if (count == maxClassesPerDerived) {
00690                   writeAndMoreFor = clBaseDerived;
00691                   ssDep << "\"...andmore" << clBaseDerived->GetName() << "\"-> \"" 
00692                      << clBaseDerived->GetName() << "\";" << endl;
00693                   ++count;
00694                }
00695             }
00696          }
00697 
00698          if (writeNode) {
00699             wroteNode.insert(iDerived->first);
00700             outdot << "  \"" << iDerived->first->GetName() << "\"";
00701             const char* htmlFileName = fHtml->GetHtmlFileName(iDerived->first->GetName());
00702             if (htmlFileName)
00703                outdot << " [URL=\"" << htmlFileName << "\"]";
00704             outdot << ";" << endl;
00705          } else if (writeAndMoreFor) {
00706                outdot << "  \"...andmore" << writeAndMoreFor->GetName()
00707                       << "\" [label=\"...and more\",fontname=\"Times-Italic\",fillcolor=lightgrey,style=filled];" << endl;
00708          }
00709       }
00710       if (!levelExists) break;
00711    }
00712    outdot << "}" << endl; // cluster
00713 
00714    outdot << ssDep.str();
00715 
00716    outdot << "}" << endl; // digraph
00717 
00718    return kTRUE;
00719 }
00720 
00721 //______________________________________________________________________________
00722 Bool_t TClassDocOutput::CreateDotClassChartInhMem(const char* filename) {
00723 // Build the class tree of inherited members for one class in GraphViz/Dot format
00724 //
00725 // Input: filename - output dot file incl. path
00726 
00727    std::ofstream outdot(filename);
00728    outdot << "strict digraph G {" << endl
00729       << "ratio=auto;" << endl
00730       << "rankdir=RL;" << endl
00731       << "compound=true;" << endl
00732       << "constraint=false;" << endl
00733       << "ranksep=0.1;" << endl
00734       << "nodesep=0;" << endl
00735       << "margin=0;" << endl;
00736    outdot << "  node [style=filled,width=0.7,height=0.15,fixedsize=true,shape=plaintext,fontsize=10];" << endl;
00737 
00738    std::stringstream ssDep;
00739    const int numColumns = 3;
00740 
00741    std::list<TClass*> writeBasesFor;
00742    writeBasesFor.push_back(fCurrentClass);
00743    while (!writeBasesFor.empty()) {
00744       TClass* cl = writeBasesFor.front();
00745       writeBasesFor.pop_front();
00746 
00747       const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
00748 
00749       outdot << "subgraph \"cluster" << cl->GetName() << "\" {" << endl
00750              << "  color=lightgray;" << endl
00751              << "  label=\"" << cl->GetName() << "\";" << endl;
00752       if (cl != fCurrentClass && htmlFileName)
00753          outdot << "  URL=\"" << htmlFileName << "\"" << endl;
00754 
00755       //Bool_t haveMembers = (cl->GetListOfDataMembers() && cl->GetListOfDataMembers()->GetSize());
00756       Bool_t haveFuncs = cl->GetListOfMethods() && cl->GetListOfMethods()->GetSize();
00757 
00758       // DATA MEMBERS
00759       {
00760          // make sure each member name is listed only once
00761          // that's useless for data members, but symmetric to what we have for methods
00762          std::map<std::string, TDataMember*> dmMap;
00763 
00764          {
00765             TIter iDM(cl->GetListOfDataMembers());
00766             TDataMember* dm = 0;
00767             while ((dm = (TDataMember*) iDM()))
00768                dmMap[dm->GetName()] = dm;
00769          }
00770 
00771          outdot << "subgraph \"clusterData0" << cl->GetName() << "\" {" << endl
00772                 << "  color=white;" << endl
00773                 << "  label=\"\";" << endl
00774                 << "  \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
00775          TString prevColumnNode;
00776          Int_t pos = dmMap.size();
00777          Int_t column = 0;
00778          Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
00779          for (std::map<std::string, TDataMember*>::iterator iDM = dmMap.begin();
00780               iDM != dmMap.end(); ++iDM, --pos) {
00781             TDataMember* dm = iDM->second;
00782             TString nodeName(cl->GetName());
00783             nodeName += "::";
00784             nodeName += dm->GetName();
00785             if (iDM == dmMap.begin())
00786                prevColumnNode = nodeName;
00787 
00788             outdot << "\"" << nodeName << "\" [label=\""
00789                    << dm->GetName() << "\"";
00790             if (dm->Property() & kIsPrivate)
00791                outdot << ",color=\"#FFCCCC\"";
00792             else if (dm->Property() & kIsProtected)
00793                outdot << ",color=\"#FFFF77\"";
00794             else
00795                outdot << ",color=\"#CCFFCC\"";
00796             outdot << "];" << endl;
00797             if (pos % newColumnEvery == 1) {
00798                ++column;
00799                outdot << "};" << endl // end dataR
00800                       << "subgraph \"clusterData" << column << cl->GetName() << "\" {" << endl
00801                       << "  color=white;" << endl
00802                       << "  label=\"\";" << endl
00803                       << "  \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
00804             } else if (iDM != dmMap.begin() && pos % newColumnEvery == 0) {
00805                ssDep << "\"" << prevColumnNode
00806                      << "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
00807                prevColumnNode = nodeName;
00808             }
00809          }
00810 
00811          while (column < numColumns - 1) {
00812             ++column;
00813             outdot << "  \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
00814          }
00815 
00816          outdot << "};" << endl; // subgraph dataL/R
00817       } // DATA MEMBERS
00818 
00819       // FUNCTION MEMBERS
00820       if (haveFuncs) {
00821          // make sure each member name is listed only once
00822          std::map<std::string, TMethod*> methMap;
00823 
00824          {
00825             TIter iMeth(cl->GetListOfMethods());
00826             TMethod* meth = 0;
00827             while ((meth = (TMethod*) iMeth())) 
00828                methMap[meth->GetName()] = meth;
00829          }
00830 
00831          outdot << "subgraph \"clusterFunc0" << cl->GetName() << "\" {" << endl
00832                 << "  color=white;" << endl
00833                 << "  label=\"\";" << endl
00834                 << "  \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
00835 
00836          TString prevColumnNodeFunc;
00837          Int_t pos = methMap.size();
00838          Int_t column = 0;
00839          Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
00840          for (std::map<std::string, TMethod*>::iterator iMeth = methMap.begin();
00841             iMeth != methMap.end(); ++iMeth, --pos) {
00842             TMethod* meth = iMeth->second;
00843             TString nodeName(cl->GetName());
00844             nodeName += "::";
00845             nodeName += meth->GetName();
00846             if (iMeth == methMap.begin())
00847                prevColumnNodeFunc = nodeName;
00848 
00849             outdot << "\"" << nodeName << "\" [label=\"" << meth->GetName() << "\"";
00850             if (cl != fCurrentClass && 
00851                fCurrentClass->GetMethodAny(meth->GetName()))
00852                outdot << ",color=\"#777777\"";
00853             else if (meth->Property() & kIsPrivate)
00854                outdot << ",color=\"#FFCCCC\"";
00855             else if (meth->Property() & kIsProtected)
00856                outdot << ",color=\"#FFFF77\"";
00857             else
00858                outdot << ",color=\"#CCFFCC\"";
00859             outdot << "];" << endl;
00860             if (pos % newColumnEvery == 1) {
00861                ++column;
00862                outdot << "};" << endl // end funcR
00863                       << "subgraph \"clusterFunc" << column << cl->GetName() << "\" {" << endl
00864                       << "  color=white;" << endl
00865                       << "  label=\"\";" << endl;
00866             } else if (iMeth != methMap.begin() && pos % newColumnEvery == 0) {
00867                ssDep << "\"" << prevColumnNodeFunc
00868                      << "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
00869                prevColumnNodeFunc = nodeName;
00870             }
00871          }
00872          outdot << "};" << endl; // subgraph funcL/R
00873       }
00874 
00875       outdot << "}" << endl; // cluster class
00876 
00877       for (Int_t pos = 0; pos < numColumns - 1; ++pos)
00878          ssDep << "\"clusterNode" << pos << cl->GetName() << "\" -> \"clusterNode" << pos + 1 << cl->GetName() << "\" [style=invis];" << endl;
00879 
00880       if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
00881          TIter iBase(cl->GetListOfBases());
00882          TBaseClass* base = 0;
00883          while ((base = (TBaseClass*)iBase())) {
00884             ssDep << "  \"clusterNode" << numColumns - 1 << cl->GetName() << "\" -> "
00885                   << " \"clusterNode0" << base->GetName() << "\" [ltail=\"cluster" << cl->GetName() 
00886                   << "\",lhead=\"cluster" << base->GetName() << "\"";
00887             if (base != cl->GetListOfBases()->First())
00888                ssDep << ",weight=0";
00889             ssDep << "];" << endl;
00890             writeBasesFor.push_back(base->GetClassPointer());
00891          }
00892       }
00893    }
00894 
00895    outdot << ssDep.str();
00896 
00897    outdot << "}" << endl; // digraph
00898 
00899    return kTRUE;
00900 }
00901 
00902 //______________________________________________________________________________
00903 Bool_t TClassDocOutput::CreateDotClassChartIncl(const char* filename) {
00904 // Build the include dependency graph for one class in 
00905 // GraphViz/Dot format
00906 //
00907 // Input: filename - output dot file incl. path
00908 
00909    R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
00910 
00911    std::map<std::string, std::string> filesToParse;
00912    std::list<std::string> listFilesToParse;
00913    TString declFileName;
00914    TString implFileName;
00915    fHtml->GetImplFileName(fCurrentClass, kFALSE, implFileName);
00916    if (fHtml->GetDeclFileName(fCurrentClass, kFALSE, declFileName)) {
00917       TString real;
00918       if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, real)) {
00919          filesToParse[declFileName.Data()] = real.Data();
00920          listFilesToParse.push_back(declFileName.Data());
00921       }
00922    }
00923    /* do it only for the header
00924    if (implFileName && strlen(implFileName)) {
00925       char* real = gSystem->Which(fHtml->GetInputPath(), implFileName, kReadPermission);
00926       if (real) {
00927          filesToParse[implFileName] = real;
00928          listFilesToParse.push_back(implFileName);
00929          delete real;
00930       }
00931    }
00932    */
00933 
00934    std::ofstream outdot(filename);
00935    outdot << "strict digraph G {" << endl
00936       << "ratio=compress;" << endl
00937       << "rankdir=TB;" << endl
00938       << "concentrate=true;" << endl
00939       << "ranksep=0;" << endl
00940       << "nodesep=0;" << endl
00941       << "size=\"8,10\";" << endl
00942       << "node [fontsize=20,shape=plaintext];" << endl;
00943 
00944    for (std::list<std::string>::iterator iFile = listFilesToParse.begin();
00945       iFile != listFilesToParse.end(); ++iFile) {
00946       ifstream in(filesToParse[*iFile].c_str());
00947       std::string line;
00948       while (in && !in.eof()) {
00949          std::getline(in, line);
00950          size_t pos = 0;
00951          while (line[pos] == ' ' || line[pos] == '\t') ++pos;
00952          if (line[pos] != '#') continue;
00953          ++pos;
00954          while (line[pos] == ' ' || line[pos] == '\t') ++pos;
00955          if (line.compare(pos, 8, "include ") != 0) continue;
00956          pos += 8;
00957          while (line[pos] == ' ' || line[pos] == '\t') ++pos;
00958          if (line[pos] != '"' && line[pos] != '<') 
00959             continue;
00960          char delim = line[pos];
00961          if (delim == '<') delim = '>';
00962          ++pos;
00963          line.erase(0, pos);
00964          pos = 0;
00965          pos = line.find(delim);
00966          if (pos == std::string::npos) continue;
00967          line.erase(pos);
00968          if (filesToParse.find(line) == filesToParse.end()) {
00969             TString sysfilename;
00970             if (!GetHtml()->GetPathDefinition().GetFileNameFromInclude(line.c_str(), sysfilename))
00971                continue;
00972             listFilesToParse.push_back(line);
00973             filesToParse[line] = sysfilename;
00974             if (*iFile == implFileName.Data() || *iFile == declFileName.Data())
00975                outdot << "\"" << *iFile << "\" [style=filled,fillcolor=lightgray];" << endl;
00976          }
00977          outdot << "\"" << *iFile << "\" -> \"" << line << "\";" << endl;
00978       }
00979    }
00980 
00981    outdot << "}" << endl; // digraph
00982 
00983    return kTRUE;
00984 }
00985 
00986 //______________________________________________________________________________
00987 Bool_t TClassDocOutput::CreateDotClassChartLib(const char* filename) {
00988 // Build the library dependency graph for one class in 
00989 // GraphViz/Dot format
00990 //
00991 // Input: filename - output dot file incl. path
00992 
00993    std::ofstream outdot(filename);
00994    outdot << "strict digraph G {" << endl
00995       << "ratio=auto;" << endl
00996       << "rankdir=RL;" << endl
00997       << "compound=true;" << endl
00998       << "constraint=false;" << endl
00999       << "ranksep=0.7;" << endl
01000       << "nodesep=0.3;" << endl
01001       << "size=\"8,8\";" << endl
01002       << "ratio=compress;" << endl;
01003 
01004    TString libs(fCurrentClass->GetSharedLibs());
01005    outdot << "\"All Libraries\" [URL=\"LibraryDependencies.html\",shape=box,rank=max,fillcolor=lightgray,style=filled];" << endl;
01006 
01007    if (libs.Length()) {
01008       TString firstLib(libs);
01009       Ssiz_t end = firstLib.Index(' ');
01010       if (end != kNPOS) {
01011          firstLib.Remove(end, firstLib.Length());
01012          libs.Remove(0, end + 1);
01013       } else libs = "";
01014 
01015       {
01016          Ssiz_t posExt = firstLib.First(".");
01017          if (posExt != kNPOS)
01018             firstLib.Remove(posExt, firstLib.Length());
01019       }
01020 
01021       outdot << "\"All Libraries\" -> \"" << firstLib << "\" [style=invis];" << endl;
01022       outdot << "\"" << firstLib << "\" -> {" << endl;
01023 
01024       if (firstLib != "libCore")
01025          libs += " libCore";
01026       if (firstLib != "libCint")
01027          libs += " libCint";
01028       TString thisLib;
01029       for (Ssiz_t pos = 0; pos < libs.Length(); ++pos)
01030          if (libs[pos] != ' ')
01031             thisLib += libs[pos];
01032          else if (thisLib.Length()) {
01033             Ssiz_t posExt = thisLib.First(".");
01034             if (posExt != kNPOS)
01035                thisLib.Remove(posExt, thisLib.Length());
01036             outdot << " \"" << thisLib << "\";";
01037             thisLib = "";
01038          }
01039       // remaining lib
01040       if (thisLib.Length()) {
01041          Ssiz_t posExt = thisLib.First(".");
01042          if (posExt != kNPOS)
01043             thisLib.Remove(posExt, thisLib.Length());
01044          outdot << " \"" << thisLib << "\";";
01045          thisLib = "";
01046       }
01047       outdot << "}" << endl; // dependencies
01048    } else
01049       outdot << "\"No rlibmap information avaliable.\"" << endl;
01050 
01051    outdot << "}" << endl; // digraph
01052 
01053    return kTRUE;
01054 }
01055 
01056 //______________________________________________________________________________
01057 void TClassDocOutput::CreateClassHierarchy(std::ostream& out, const char* docFileName)
01058 {
01059 // Create the hierarchical class list part for the current class's
01060 // base classes. docFileName contains doc for fCurrentClass.
01061 //
01062 
01063    // Find basic base classes
01064    TList *bases = fCurrentClass->GetListOfBases();
01065    if (!bases || bases->IsEmpty())
01066       return;
01067 
01068    out << "<hr />" << endl;
01069 
01070    out << "<table><tr><td><ul><li><tt>";
01071    if (docFileName) {
01072       out << "<a name=\"" << fCurrentClass->GetName() << "\" href=\""
01073           << docFileName << "\">";
01074       ReplaceSpecialChars(out, fCurrentClass->GetName());
01075       out << "</a>";
01076    } else {
01077       ReplaceSpecialChars(out, fCurrentClass->GetName());
01078    }
01079 
01080    // find derived classes
01081    out << "</tt></li></ul></td>";
01082    fHierarchyLines = 0;
01083    DescendHierarchy(out, fCurrentClass);
01084 
01085    out << "</tr></table>" << endl;
01086 }
01087 
01088 //______________________________________________________________________________
01089 Bool_t TClassDocOutput::CreateHierarchyDot()
01090 {
01091 // Create a hierarchical class list
01092 // The algorithm descends from the base classes and branches into
01093 // all derived classes. Mixing classes are displayed several times.
01094 //
01095 //
01096 
01097    const char* title = "ClassHierarchy";
01098    TString filename(title);
01099    gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
01100 
01101    // open out file
01102    std::ofstream dotout(filename + ".dot");
01103 
01104    if (!dotout.good()) {
01105       Error("CreateHierarchy", "Can't open file '%s.dot' !",
01106             filename.Data());
01107       return kFALSE;
01108    }
01109 
01110    dotout << "digraph G {" << endl
01111           << "ratio=auto;" << endl
01112           << "rankdir=RL;" << endl;
01113 
01114    // loop on all classes
01115    TClassDocInfo* cdi = 0;
01116    TIter iClass(fHtml->GetListOfClasses());
01117    while ((cdi = (TClassDocInfo*)iClass())) {
01118 
01119       TDictionary *dict = cdi->GetClass();
01120       TClass *cl = dynamic_cast<TClass*>(dict);
01121       if (cl == 0) {
01122          if (!dict)
01123             Warning("THtml::CreateHierarchy", "skipping class %s\n", cdi->GetName());
01124          continue;
01125       }
01126 
01127       // Find immediate base classes
01128       TList *bases = cl->GetListOfBases();
01129       if (bases && !bases->IsEmpty()) {
01130          dotout << "\"" << cdi->GetName() << "\" -> { ";
01131          TIter iBase(bases);
01132          TBaseClass* base = 0;
01133          while ((base = (TBaseClass*) iBase())) {
01134             // write out current class
01135             if (base != bases->First())
01136                dotout << "; ";
01137             dotout << "\"" << base->GetName() << "\"";
01138          }
01139          dotout << "};" << endl;
01140       } else 
01141          // write out current class - no bases
01142          dotout << "\"" << cdi->GetName() << "\";" << endl;
01143 
01144    }
01145 
01146    dotout << "}";
01147    dotout.close();
01148 
01149    std::ofstream out(filename + ".html");
01150    if (!out.good()) {
01151       Error("CreateHierarchy", "Can't open file '%s.html' !",
01152             filename.Data());
01153       return kFALSE;
01154    }
01155 
01156    Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), (filename + ".html").Data());
01157    // write out header
01158    WriteHtmlHeader(out, "Class Hierarchy");
01159    out << "<h1>Class Hierarchy</h1>" << endl;
01160 
01161    WriteSearch(out);
01162 
01163    RunDot(filename, &out);
01164 
01165    out << "<img usemap=\"#Map" << title << "\" src=\"" << title << ".png\"/>" << endl;
01166    // write out footer
01167    WriteHtmlFooter(out);
01168    return kTRUE;
01169 }
01170 
01171 //______________________________________________________________________________
01172 void TClassDocOutput::CreateSourceOutputStream(std::ostream& out, const char* extension, 
01173                                      TString& sourceHtmlFileName) 
01174 {
01175    // Open a Class.cxx.html file, where Class is defined by classPtr, and .cxx.html by extension
01176    // It's created in fHtml->GetOutputDir()/src. If successful, the HTML header is written to out.
01177 
01178    TString sourceHtmlDir("src");
01179    gSystem->PrependPathName(fHtml->GetOutputDir(), sourceHtmlDir);
01180    // create directory if necessary
01181    {
01182       R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
01183 
01184       if (gSystem->AccessPathName(sourceHtmlDir))
01185          gSystem->MakeDirectory(sourceHtmlDir);
01186    }
01187    sourceHtmlFileName = fCurrentClass->GetName();
01188    NameSpace2FileName(sourceHtmlFileName);
01189    gSystem->PrependPathName(sourceHtmlDir, sourceHtmlFileName);
01190    sourceHtmlFileName += extension;
01191    dynamic_cast<std::ofstream&>(out).open(sourceHtmlFileName);
01192    if (!out) {
01193       Warning("LocateMethodsInSource", "Can't open beautified source file '%s' for writing!", 
01194          sourceHtmlFileName.Data());
01195       sourceHtmlFileName.Remove(0);
01196       return;
01197    }
01198 
01199    // write a HTML header
01200    TString title(fCurrentClass->GetName());
01201    title += " - source file";
01202    WriteHtmlHeader(out, title, "../", fCurrentClass);
01203    out << "<div id=\"codeAndLineNumbers\"><pre class=\"listing\">" << std::endl;
01204 }
01205 
01206 //______________________________________________________________________________
01207 void TClassDocOutput::DescendHierarchy(std::ostream& out, TClass* basePtr, Int_t maxLines, Int_t depth)
01208 {
01209 // Descend hierarchy recursively
01210 // loop over all classes and look for classes with base class basePtr
01211 
01212    if (maxLines)
01213       if (fHierarchyLines >= maxLines) {
01214          out << "<td></td>" << endl;
01215          return;
01216       }
01217 
01218    UInt_t numClasses = 0;
01219 
01220    TClassDocInfo* cdi = 0;
01221    TIter iClass(fHtml->GetListOfClasses());
01222    while ((cdi = (TClassDocInfo*)iClass()) && (!maxLines || fHierarchyLines<maxLines)) {
01223 
01224       TClass *classPtr = dynamic_cast<TClass*>(cdi->GetClass());
01225       if (!classPtr) continue;
01226 
01227       // find base classes with same name as basePtr
01228       TList* bases=classPtr->GetListOfBases();
01229       if (!bases) continue;
01230 
01231       TBaseClass *inheritFrom=(TBaseClass*)bases->FindObject(basePtr->GetName());
01232       if (!inheritFrom) continue;
01233 
01234       if (!numClasses)
01235          out << "<td>&larr;</td><td><table><tr>" << endl;
01236       else
01237          out << "</tr><tr>"<<endl;
01238       fHierarchyLines++;
01239       numClasses++;
01240       UInt_t bgcolor=255-depth*8;
01241       out << "<td bgcolor=\""
01242           << Form("#%02x%02x%02x", bgcolor, bgcolor, bgcolor)
01243           << "\">";
01244       out << "<table><tr><td>" << endl;
01245 
01246       TString htmlFile(cdi->GetHtmlFileName());
01247       if (htmlFile.Length()) {
01248          out << "<center><tt><a name=\"" << cdi->GetName() << "\" href=\""
01249              << htmlFile << "\">";
01250          ReplaceSpecialChars(out, cdi->GetName());
01251          out << "</a></tt></center>";
01252       } else {
01253          ReplaceSpecialChars(out, cdi->GetName());
01254       }
01255       // write title
01256       // commented out for now because it reduces overview
01257       /*
01258         len = strlen(classNames[i]);
01259         for (Int_t w = 0; w < (maxLen - len + 2); w++)
01260         out << ".";
01261         out << " ";
01262 
01263         out << "<a name=\"Title:";
01264         out << classPtr->GetName();
01265         out << "\">";
01266         ReplaceSpecialChars(out, classPtr->GetTitle());
01267         out << "</a></tt>" << endl;
01268       */
01269 
01270       out << "</td>" << endl;
01271       DescendHierarchy(out,classPtr,maxLines, depth+1);
01272       out << "</tr></table></td>" << endl;
01273 
01274    }  // loop over all classes
01275    if (numClasses)
01276       out << "</tr></table></td>" << endl;
01277    else
01278       out << "<td></td>" << endl;
01279 }
01280 
01281 //______________________________________________________________________________
01282 void TClassDocOutput::MakeTree(Bool_t force /*= kFALSE*/)
01283 {
01284    // Create an output file with a graphical representation of the class 
01285    // inheritance. If force, replace existing output file.
01286    // This routine does nothing if fHtml->HaveDot() is true - use 
01287    // ClassDotCharts() instead!
01288 
01289    // class tree only if no dot, otherwise it's part of charts
01290    if (!fCurrentClass || fHtml->HaveDot())
01291       return;
01292 
01293    TString htmlFile;
01294    fHtml->GetHtmlFileName(fCurrentClass, htmlFile);
01295    if (htmlFile.Length()
01296        && (htmlFile.BeginsWith("http://")
01297            || htmlFile.BeginsWith("https://")
01298            || gSystem->IsAbsoluteFileName(htmlFile))
01299        ) {
01300       htmlFile.Remove(0);
01301    }
01302 
01303    if (!htmlFile.Length()) {
01304       TString what(fCurrentClass->GetName());
01305       what += " (source not found)";
01306       Printf(fHtml->GetCounterFormat(), "-skipped-", "", what.Data());
01307       return;
01308    }
01309 
01310    R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
01311 
01312    // Create a canvas without linking against GUI libs
01313    Bool_t wasBatch = gROOT->IsBatch();
01314    if (!wasBatch)
01315       gROOT->SetBatch();
01316    TVirtualPad *psCanvas = (TVirtualPad*)gROOT->ProcessLineFast("new TCanvas(\"R__THtml\",\"psCanvas\",0,0,1000,1200);");
01317    if (!wasBatch)
01318       gROOT->SetBatch(kFALSE);
01319 
01320    if (!psCanvas) {
01321       Error("MakeTree", "Cannot create a TCanvas!");
01322       return;
01323    }
01324    
01325    // make a class tree
01326    ClassTree(psCanvas, force);
01327 
01328    psCanvas->Close();
01329    delete psCanvas;
01330 }
01331 
01332 //______________________________________________________________________________
01333 void TClassDocOutput::WriteClassDescription(std::ostream& out, const TString& description)
01334 {
01335    // Called by TDocParser::LocateMethods(), this hook writes out the class description
01336    // found by TDocParser. It's even called if none is found, i.e. if the first method
01337    // has occurred before a class description is found, so missing class descriptions
01338    // can be handled.
01339    // For HTML, its creates the description block, the list of functions and data
01340    // members, and the inheritance tree or, if Graphviz's dot is found, the class charts.
01341 
01342    // Class Description Title
01343    out << "<div class=\"dropshadow\"><div class=\"withshadow\">";
01344    TString anchor(fCurrentClass->GetName());
01345    NameSpace2FileName(anchor);
01346    out << "<h1><a name=\"" << anchor;
01347    out << ":description\"></a>";
01348 
01349    if (fHtml->IsNamespace(fCurrentClass))
01350       out << "namespace ";
01351    else
01352       out << "class ";
01353    ReplaceSpecialChars(out, fCurrentClass->GetName());
01354 
01355 
01356    // make a loop on base classes
01357    Bool_t first = kTRUE;
01358    TBaseClass *inheritFrom;
01359    TIter nextBase(fCurrentClass->GetListOfBases());
01360 
01361    while ((inheritFrom = (TBaseClass *) nextBase())) {
01362       if (first) {
01363          out << ": ";
01364          first = kFALSE;
01365       } else
01366          out << ", ";
01367       Long_t property = inheritFrom->Property();
01368       if (property & kIsPrivate)
01369          out << "private ";
01370       else if (property & kIsProtected)
01371          out << "protected ";
01372       else
01373          out << "public ";
01374 
01375       // get a class
01376       TClass *classInh = fHtml->GetClass(inheritFrom->GetName());
01377 
01378       TString htmlFile;
01379       fHtml->GetHtmlFileName(classInh, htmlFile);
01380 
01381       if (htmlFile.Length()) {
01382          // make a link to the base class
01383          out << "<a href=\"" << htmlFile << "\">";
01384          ReplaceSpecialChars(out, inheritFrom->GetName());
01385          out << "</a>";
01386       } else
01387          ReplaceSpecialChars(out, inheritFrom->GetName());
01388    }
01389    out << "</h1>" << endl;
01390 
01391    out << "<div class=\"classdescr\">" << endl;
01392 
01393    if (description.Length())
01394       out << "<pre>" << description << "</pre>";
01395 
01396    // typedefs pointing to this class:
01397    if (fCurrentClassesTypedefs && !fCurrentClassesTypedefs->IsEmpty()) {
01398       out << "<h4>This class is also known as (typedefs to this class)</h4>";
01399       TIter iTD(fCurrentClassesTypedefs);
01400       bool firsttd = true;
01401       TDataType* dt = 0;
01402       while ((dt = (TDataType*) iTD())) {
01403          if (!firsttd)
01404             out << ", ";
01405          else firsttd = false;
01406          fParser->DecorateKeywords(out, dt->GetName());
01407       }
01408    }
01409 
01410    out << "</div>" << std::endl 
01411        << "</div></div>" << std::endl;
01412 
01413    ListFunctions(out);
01414    ListDataMembers(out);
01415 
01416    // create dot class charts or an html inheritance tree
01417    out << "<h2><a id=\"" << anchor
01418       << ":Class_Charts\"></a>Class Charts</h2>" << endl;
01419    if (!fHtml->IsNamespace(fCurrentClass))
01420       if (!ClassDotCharts(out))
01421          ClassHtmlTree(out, fCurrentClass);
01422 
01423    // header for the following function docs:
01424    out << "<h2>Function documentation</h2>" << endl;
01425 }
01426 
01427 
01428 //______________________________________________________________________________
01429 void TClassDocOutput::WriteClassDocHeader(std::ostream& classFile)
01430 {
01431    // Write out the introduction of a class description (shortcuts and links)
01432 
01433    classFile << "<a name=\"TopOfPage\"></a>" << endl;
01434 
01435 
01436    // show box with lib, include
01437    // needs to go first to allow title on the left
01438    TString sTitle(fCurrentClass->GetName());
01439    ReplaceSpecialChars(sTitle);
01440    if (fHtml->IsNamespace(fCurrentClass))
01441       sTitle.Prepend("namespace ");
01442    else
01443       sTitle.Prepend("class ");
01444 
01445    TString sInclude;
01446    TString sLib;
01447    const char* lib=fCurrentClass->GetSharedLibs();
01448    GetHtml()->GetPathDefinition().GetIncludeAs(fCurrentClass, sInclude);
01449    if (lib) {
01450       char* libDup=StrDup(lib);
01451       char* libDupSpace=strchr(libDup,' ');
01452       if (libDupSpace) *libDupSpace=0;
01453       char* libDupEnd=libDup+strlen(libDup);
01454       while (libDupEnd!=libDup)
01455          if (*(--libDupEnd)=='.') {
01456             *libDupEnd=0;
01457             break;
01458          }
01459       sLib = libDup;
01460       delete[] libDup;
01461    }
01462    classFile << "<script type=\"text/javascript\">WriteFollowPageBox('" 
01463              << sTitle << "','" << sLib << "','" << sInclude << "');</script>" << endl;
01464 
01465    TString modulename;
01466    fHtml->GetModuleNameForClass(modulename, fCurrentClass);
01467    TModuleDocInfo* module = (TModuleDocInfo*) fHtml->GetListOfModules()->FindObject(modulename);
01468    WriteTopLinks(classFile, module, fCurrentClass->GetName(), kFALSE);
01469 
01470    classFile << "<div class=\"descrhead\"><div class=\"descrheadcontent\">" << endl // descrhead line 3
01471       << "<span class=\"descrtitle\">Source:</span>" << endl;
01472 
01473    // make a link to the '.cxx' file
01474    TString classFileName(fCurrentClass->GetName());
01475    NameSpace2FileName(classFileName);
01476 
01477    TString headerFileName;
01478    fHtml->GetDeclFileName(fCurrentClass, kFALSE, headerFileName);
01479    TString sourceFileName;
01480    fHtml->GetImplFileName(fCurrentClass, kFALSE, sourceFileName);
01481    if (headerFileName.Length())
01482       classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
01483                 << ".h.html\">header file</a>" << endl;
01484    else
01485       classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
01486                 << ".h.html\"></a>" << endl;
01487 
01488    if (sourceFileName.Length())
01489       classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
01490                 << ".cxx.html\">source file</a>" << endl;
01491    else
01492       classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
01493                 << ".cxx.html\"></a>" << endl;
01494 
01495    if (!fHtml->IsNamespace(fCurrentClass) && !fHtml->HaveDot()) {
01496       // make a link to the inheritance tree (postscript)
01497       classFile << "<a class=\"descrheadentry\" href=\"" << classFileName << "_Tree.pdf\"";
01498       classFile << ">inheritance tree (.pdf)</a> ";
01499    }
01500 
01501    const TString& viewCVSLink = GetHtml()->GetViewCVS();
01502    Bool_t mustReplace = viewCVSLink.Contains("%f");
01503    if (viewCVSLink.Length()) {
01504       if (headerFileName.Length()) {
01505          TString link(viewCVSLink);
01506          TString sHeader(headerFileName);
01507          if (GetHtml()->GetProductName() && !strcmp(GetHtml()->GetProductName(), "ROOT")
01508              && sHeader.BeginsWith("include")) {
01509             sHeader.Remove(0,7);
01510             if (sourceFileName && strstr(sourceFileName, "src")) {
01511                TString src(sourceFileName);
01512                src.Remove(src.Index("src"), src.Length());
01513                src += "inc";
01514                sHeader.Prepend(src);
01515             } else {
01516                TString src(fCurrentClass->GetSharedLibs());
01517                Ssiz_t posEndLib = src.Index(' ');
01518                if (posEndLib != kNPOS)
01519                   src.Remove(posEndLib, src.Length());
01520                if (src.BeginsWith("lib"))
01521                   src.Remove(0, 3);
01522                posEndLib = src.Index('.');
01523                if (posEndLib != kNPOS)
01524                   src.Remove(posEndLib, src.Length());
01525                src.ToLower();
01526                src += "/inc";
01527                sHeader.Prepend(src);
01528             }
01529             if (sHeader.BeginsWith("tmva/inc/TMVA"))
01530                sHeader.Remove(8, 5);
01531          }
01532          if (mustReplace) link.ReplaceAll("%f", sHeader);
01533          else link += sHeader;
01534          classFile << "<a class=\"descrheadentry\" href=\"" << link << "\">viewVC header</a> ";
01535       } else
01536          classFile << "<a class=\"descrheadentry\"> </a> ";
01537       if (sourceFileName.Length()) {
01538          TString link(viewCVSLink);
01539          if (mustReplace) link.ReplaceAll("%f", sourceFileName);
01540          else link += sourceFileName;
01541          classFile << "<a class=\"descrheadentry\" href=\"" << link << "\">viewVC source</a> ";
01542       } else
01543          classFile << "<a class=\"descrheadentry\"> </a> ";
01544    }
01545 
01546    TString currClassNameMangled(fCurrentClass->GetName());
01547    NameSpace2FileName(currClassNameMangled);
01548 
01549    TString wikiLink = GetHtml()->GetWikiURL();
01550    if (wikiLink.Length()) {
01551       if (wikiLink.Contains("%c")) wikiLink.ReplaceAll("%c", currClassNameMangled);
01552       else wikiLink += currClassNameMangled;
01553       classFile << "<a class=\"descrheadentry\" href=\"" << wikiLink << "\">wiki</a> ";
01554    }
01555 
01556    classFile << endl << "</div></div>" << endl; // descrhead line 3
01557 
01558    classFile << "<div class=\"descrhead\"><div class=\"descrheadcontent\">" << endl // descrhead line 4
01559       << "<span class=\"descrtitle\">Sections:</span>" << endl
01560       << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled;
01561    if (fHtml->IsNamespace(fCurrentClass))
01562       classFile << ":description\">namespace description</a> ";
01563    else
01564       classFile << ":description\">class description</a> ";
01565    classFile << endl
01566       << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Function_Members\">function members</a>" << endl
01567       << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Data_Members\">data members</a>" << endl
01568       << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Class_Charts\">class charts</a>" << endl
01569       << "</div></div>" << endl // descrhead line 4
01570       << "</div>" << endl; // toplinks, from TDocOutput::WriteTopLinks
01571 
01572    WriteLocation(classFile, module, fCurrentClass->GetName());
01573 }
01574 
01575 
01576 //______________________________________________________________________________
01577 void TClassDocOutput::WriteMethod(std::ostream& out, TString& ret, 
01578                                   TString& name, TString& params,
01579                                   const char* filename, TString& anchor,
01580                                   TString& comment, TString& codeOneLiner,
01581                                   TDocMethodWrapper* guessedMethod)
01582 {
01583    // Write method name with return type ret and parameters param to out.
01584    // Build a link using file and anchor. Cooment it with comment, and
01585    // show the code codeOneLiner (set if the func consists of only one line
01586    // of code, immediately surrounded by "{","}"). Also updates fMethodNames's
01587    // count of method names.
01588 
01589    fParser->DecorateKeywords(ret);
01590    out << "<div class=\"funcdoc\"><span class=\"funcname\">"
01591       << ret << " <a class=\"funcname\" name=\"";
01592    TString mangled(fCurrentClass->GetName());
01593    NameSpace2FileName(mangled);
01594    out << mangled << ":";
01595    mangled = name;
01596    NameSpace2FileName(mangled);
01597    if (guessedMethod && guessedMethod->GetOverloadIdx()) {
01598       mangled += "%";
01599       mangled += guessedMethod->GetOverloadIdx();
01600    }
01601    out << mangled << "\" href=\"src/" << filename;
01602    if (anchor.Length())
01603       out << "#" << anchor;
01604    out << "\">";
01605    ReplaceSpecialChars(out, name);
01606    out << "</a>";
01607    if (guessedMethod) {
01608       out << "(";
01609       TMethodArg* arg;
01610       TIter iParam(guessedMethod->GetMethod()->GetListOfMethodArgs());
01611       Bool_t first = kTRUE;
01612       while ((arg = (TMethodArg*) iParam())) {
01613          if (!first) out << ", ";
01614          else first = kFALSE;
01615          TString paramGuessed(arg->GetFullTypeName());
01616          paramGuessed += " ";
01617          paramGuessed += arg->GetName();
01618          if (arg->GetDefault() && strlen(arg->GetDefault())) {
01619             paramGuessed += " = ";
01620             paramGuessed += arg->GetDefault();
01621          }
01622          fParser->DecorateKeywords(paramGuessed);
01623          out << paramGuessed;
01624       }
01625       out << ")";
01626       if (guessedMethod->GetMethod()->Property() & kIsMethConst)
01627          out << " const";
01628    } else {
01629       fParser->DecorateKeywords(params);
01630       out << params;
01631    }
01632    out << "</span><br />" << std::endl;
01633 
01634    if (comment.Length())
01635       out << "<div class=\"funccomm\"><pre>" << comment << "</pre></div>" << std::endl;
01636 
01637    if (codeOneLiner.Length()) {
01638       out << std::endl << "<div class=\"code\"><code class=\"inlinecode\">" 
01639           << codeOneLiner << "</code></div>" << std::endl
01640           << "<div style=\"clear:both;\"></div>" << std::endl;
01641       codeOneLiner.Remove(0);
01642    }
01643    out << "</div>" << std::endl;
01644 }
01645 
01646 
01647 

Generated on Tue Jul 5 14:24:55 2011 for ROOT_528-00b_version by  doxygen 1.5.1