ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/Utils/src/TClassDocOutput.cxx
Revision: 1.1
Committed: Tue Aug 11 23:09:28 2009 UTC (15 years, 8 months ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_032, Mit_031, Mit_025c_branch2, Mit_025c_branch1, Mit_030, Mit_029c, Mit_029b, Mit_030_pre1, Mit_029a, Mit_029, Mit_029_pre1, Mit_028a, Mit_025c_branch0, Mit_028, Mit_027a, Mit_027, Mit_026, Mit_025e, Mit_025d, Mit_025c, Mit_025b, Mit_025a, Mit_025, Mit_025pre2, Mit_024b, Mit_025pre1, Mit_024a, Mit_024, Mit_023, Mit_022a, Mit_022, Mit_020d, TMit_020d, Mit_020c, Mit_021, Mit_021pre2, Mit_021pre1, Mit_020b, Mit_020a, Mit_020, Mit_020pre1, Mit_018, Mit_017, Mit_017pre3, Mit_017pre2, Mit_017pre1, Mit_016, Mit_015b, Mit_015a, Mit_015, Mit_014e, Mit_014d, Mit_014c, Mit_014b, Mit_014a, Mit_014, Mit_014pre3, Mit_014pre2, Mit_014pre1, Mit_013d, Mit_013c, Mit_013b, Mit_013a, Mit_013, Mit_013pre1, Mit_012i, Mit_012h, Mit_012g, Mit_012f, Mit_012e, Mit_012d, Mit_012c, Mit_012b, Mit_012a, Mit_012, Mit_011a, Mit_011, Mit_010a, HEAD
Branch point for: Mit_025c_branch
Log Message:
Added THtml from ROOT

File Contents

# User Rev Content
1 loizides 1.1 // @(#)root/html:$Id: TClassDocOutput.cxx 26715 2008-12-07 17:32:59Z axel $
2     // Author: Axel Naumann 2007-01-09
3    
4     /*************************************************************************
5     * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6     * All rights reserved. *
7     * *
8     * For the licensing terms see $ROOTSYS/LICENSE. *
9     * For the list of contributors see $ROOTSYS/README/CREDITS. *
10     *************************************************************************/
11    
12     #include "MitAna/Utils/interface/TClassDocOutput.h"
13    
14     #include "TBaseClass.h"
15     #include "TDataMember.h"
16     #include "TMethodArg.h"
17     #include "TDataType.h"
18     #include "MitAna/Utils/interface/TDocInfo.h"
19     #include "MitAna/Utils/interface/TDocParser.h"
20     #include "TEnv.h"
21     #include "TError.h"
22     #include "THtml.h"
23     #include "TMethod.h"
24     #include "TROOT.h"
25     #include "TSystem.h"
26     #include "TVirtualPad.h"
27     #include "TVirtualMutex.h"
28     #include "Riostream.h"
29     #include <sstream>
30    
31     //______________________________________________________________________________
32     //
33     // Write the documentation for a class or namespace. The documentation is
34     // parsed by TDocParser and then passed to TClassDocOutput to generate
35     // the class doc header, the class description, members overview, and method
36     // documentation. All generic output functionality is in TDocOutput; it is
37     // re-used in this derived class.
38     //
39     // You usually do not use this class yourself; it is invoked indirectly by
40     // THtml. Customization of the output should happen via the interfaces defined
41     // by THtml.
42     //______________________________________________________________________________
43    
44    
45     ClassImp(TClassDocOutput)
46    
47     //______________________________________________________________________________
48     TClassDocOutput::TClassDocOutput(THtml& html, TClass* cl, TList* typedefs):
49     TDocOutput(html), fHierarchyLines(0), fCurrentClass(cl),
50     fCurrentClassesTypedefs(typedefs), fParser(0)
51     {
52     // Create an object given the invoking THtml object, and the TClass
53     // object that we will generate output for.
54    
55     fParser = new TDocParser(*this, fCurrentClass);
56     }
57    
58     //______________________________________________________________________________
59     TClassDocOutput::~TClassDocOutput()
60     {
61     // Destructor, deletes fParser
62     delete fParser;
63     }
64    
65     //______________________________________________________________________________
66     void TClassDocOutput::Class2Html(Bool_t force)
67     {
68     // Create HTML files for a single class.
69     //
70    
71     gROOT->GetListOfGlobals(kTRUE);
72    
73     // create a filename
74     TString filename(fCurrentClass->GetName());
75     NameSpace2FileName(filename);
76    
77     gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
78    
79     filename += ".html";
80    
81     if (!force && !IsModified(fCurrentClass, kSource)
82     && !IsModified(fCurrentClass, kDoc)) {
83     Printf(fHtml->GetCounterFormat(), "-no change-", fHtml->GetCounter(), filename.Data());
84     return;
85     }
86    
87     // open class file
88     std::ofstream classFile(filename);
89    
90     if (!classFile.good()) {
91     Error("Make", "Can't open file '%s' !", filename.Data());
92     return;
93     }
94    
95     Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
96    
97     // write a HTML header for the classFile file
98     WriteHtmlHeader(classFile, fCurrentClass->GetName(), "", fCurrentClass);
99     WriteClassDocHeader(classFile);
100    
101     // copy .h file to the Html output directory
102     TString declf;
103     if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, declf))
104     CopyHtmlFile(declf);
105    
106     // process a '.cxx' file
107     fParser->Parse(classFile);
108    
109     // write classFile footer
110     WriteHtmlFooter(classFile, "",
111     fParser->GetSourceInfo(TDocParser::kInfoLastUpdate),
112     fParser->GetSourceInfo(TDocParser::kInfoAuthor),
113     fParser->GetSourceInfo(TDocParser::kInfoCopyright));
114     }
115    
116     //______________________________________________________________________________
117     void TClassDocOutput::ListFunctions(std::ostream& classFile)
118     {
119     // Write the list of functions
120    
121     // loop to get a pointers to method names
122    
123     TString currClassNameMangled(fCurrentClass->GetName());
124     NameSpace2FileName(currClassNameMangled);
125    
126     classFile << endl << "<div id=\"functions\">" << endl;
127     classFile << "<h2><a id=\"" << currClassNameMangled
128     << ":Function_Members\"></a>Function Members (Methods)</h2>" << endl;
129    
130     const char* tab4nbsp="&nbsp;&nbsp;&nbsp;&nbsp;";
131     TString declFile;
132     fHtml->GetDeclFileName(fCurrentClass, kFALSE, declFile);
133     if (fCurrentClass->Property() & kIsAbstract)
134     classFile << "&nbsp;<br /><b>"
135     << tab4nbsp << "This is an abstract class, constructors will not be documented.<br />" << endl
136     << tab4nbsp << "Look at the <a href=\""
137     << gSystem->BaseName(declFile)
138     << "\">header</a> to check for available constructors.</b><br />" << endl;
139    
140     Int_t minAccess = 0;
141     if (fHtml->IsNamespace(fCurrentClass))
142     minAccess = TDocParser::kPublic;
143     for (Int_t access = TDocParser::kPublic; access >= minAccess; --access) {
144    
145     const TList* methods = fParser->GetMethods((TDocParser::EAccess)access);
146     if (methods->GetEntries() == 0)
147     continue;
148    
149     classFile << "<div class=\"access\" ";
150     const char* accessID [] = {"priv", "prot", "publ"};
151     const char* accesstxt[] = {"private", "protected", "public"};
152    
153     classFile << "id=\"func" << accessID[access] << "\"><b>"
154     << accesstxt[access] << ":</b>" << endl
155     << "<table class=\"func\" id=\"tabfunc" << accessID[access] << "\" cellspacing=\"0\">" << endl;
156    
157     TIter iMethWrap(methods);
158     TDocParser::TMethodWrapper *methWrap = 0;
159     while ((methWrap = (TDocParser::TMethodWrapper*) iMethWrap())) {
160     const TMethod* method = methWrap->GetMethod();
161    
162     // it's a c'tor - Cint stores the class name as return type
163     Bool_t isctor = (!strcmp(method->GetName(), method->GetReturnTypeName()));
164     // it's a d'tor - Cint stores "void" as return type
165     Bool_t isdtor = (!isctor && method->GetName()[0] == '~');
166    
167     classFile << "<tr class=\"func";
168     if (method->GetClass() != fCurrentClass)
169     classFile << "inh";
170     classFile << "\"><td class=\"funcret\">";
171     if (kIsVirtual & method->Property()) {
172     if (!isdtor)
173     classFile << "virtual ";
174     else
175     classFile << " virtual";
176     }
177    
178     if (kIsStatic & method->Property())
179     classFile << "static ";
180    
181     if (!isctor && !isdtor)
182     fParser->DecorateKeywords(classFile, method->GetReturnTypeName());
183    
184     TString mangled(method->GetClass()->GetName());
185     NameSpace2FileName(mangled);
186     classFile << "</td><td class=\"funcname\"><a class=\"funcname\" href=\"";
187     if (method->GetClass() != fCurrentClass) {
188     TString htmlFile;
189     fHtml->GetHtmlFileName(method->GetClass(), htmlFile);
190     classFile << htmlFile;
191     }
192     classFile << "#" << mangled;
193     classFile << ":";
194     mangled = method->GetName();
195     NameSpace2FileName(mangled);
196     classFile << mangled << "\">";
197     if (method->GetClass() != fCurrentClass) {
198     classFile << "<span class=\"baseclass\">";
199     ReplaceSpecialChars(classFile, method->GetClass()->GetName());
200     classFile << "::</span>";
201     }
202     ReplaceSpecialChars(classFile, method->GetName());
203     classFile << "</a>";
204    
205     fParser->DecorateKeywords(classFile, const_cast<TMethod*>(method)->GetSignature());
206     bool propSignal = false;
207     bool propMenu = false;
208     bool propToggle = false;
209     bool propGetter = false;
210     if (method->GetTitle()) {
211     propSignal = (strstr(method->GetTitle(), "*SIGNAL*"));
212     propMenu = (strstr(method->GetTitle(), "*MENU*"));
213     propToggle = (strstr(method->GetTitle(), "*TOGGLE*"));
214     propGetter = (strstr(method->GetTitle(), "*GETTER"));
215     if (propSignal || propMenu || propToggle || propGetter) {
216     classFile << "<span class=\"funcprop\">";
217     if (propSignal) classFile << "<abbr title=\"emits a signal\">SIGNAL</abbr> ";
218     if (propMenu) classFile << "<abbr title=\"has a popup menu entry\">MENU</abbr> ";
219     if (propToggle) classFile << "<abbr title=\"toggles a state\">TOGGLE</abbr> ";
220     if (propGetter) {
221     TString getter(method->GetTitle());
222     Ssiz_t posGetter = getter.Index("*GETTER=");
223     getter.Remove(0, posGetter + 8);
224     classFile << "<abbr title=\"use " + getter + "() as getter\">GETTER</abbr> ";
225     }
226     classFile << "</span>";
227     }
228     }
229     classFile << "</td></tr>" << endl;
230     }
231     classFile << endl << "</table></div>" << endl;
232     }
233    
234     classFile << "</div>" << endl; // class="functions"
235     }
236    
237     //______________________________________________________________________________
238     void TClassDocOutput::ListDataMembers(std::ostream& classFile)
239     {
240     // Write the list of data members and enums
241    
242     // make a loop on data members
243     Bool_t haveDataMembers = (fParser->GetDataMembers(TDocParser::kPrivate)->GetEntries() ||
244     fParser->GetDataMembers(TDocParser::kProtected)->GetEntries() ||
245     fParser->GetDataMembers(TDocParser::kPublic)->GetEntries() ||
246     fParser->GetEnums(TDocParser::kPublic)->GetEntries() ||
247     fParser->GetEnums(TDocParser::kProtected)->GetEntries() ||
248     fParser->GetEnums(TDocParser::kPrivate)->GetEntries());
249    
250     if (!haveDataMembers) return;
251    
252     TString currClassNameMangled(fCurrentClass->GetName());
253     NameSpace2FileName(currClassNameMangled);
254    
255     classFile << endl << "<div id=\"datamembers\">" << endl;
256     classFile << "<h2><a name=\"" << currClassNameMangled
257     << ":Data_Members\"></a>Data Members</h2>" << endl;
258    
259     for (Int_t access = 5; access >= 0 && !fHtml->IsNamespace(fCurrentClass); --access) {
260     const TList* datamembers = 0;
261     if (access > 2) datamembers = fParser->GetEnums((TDocParser::EAccess) (access - 3));
262     else datamembers = fParser->GetDataMembers((TDocParser::EAccess) access);
263     if (datamembers->GetEntries() == 0)
264     continue;
265    
266     classFile << "<div class=\"access\" ";
267     const char* what = "data";
268     if (access > 2) what = "enum";
269     const char* accessID [] = {"priv", "prot", "publ"};
270     const char* accesstxt[] = {"private", "protected", "public"};
271    
272     classFile << "id=\"" << what << accessID[access%3] << "\"><b>"
273     << accesstxt[access%3] << ":</b>" << endl
274     << "<table class=\"data\" id=\"tab" << what << accessID[access%3] << "\" cellspacing=\"0\">" << endl;
275    
276     TIter iDM(datamembers);
277     TDataMember *member = 0;
278     TString prevEnumName;
279     Bool_t prevIsInh = kTRUE;
280    
281     while ((member = (TDataMember*) iDM())) {
282     Bool_t haveNewEnum = access > 2 && prevEnumName != member->GetTypeName();
283     if (haveNewEnum) {
284     if (prevEnumName.Length()) {
285     classFile << "<tr class=\"data";
286     if (prevIsInh)
287     classFile << "inh";
288     classFile << "\"><td class=\"datatype\">};</td><td></td><td></td></tr>" << endl;
289     }
290     prevEnumName = member->GetTypeName();
291     }
292    
293     classFile << "<tr class=\"data";
294     prevIsInh = (member->GetClass() != fCurrentClass);
295     if (prevIsInh)
296     classFile << "inh";
297     classFile << "\"><td class=\"datatype\">";
298     if (haveNewEnum) {
299     TString enumName(member->GetTypeName());
300     TString myScope(fCurrentClass->GetName());
301     myScope += "::";
302     enumName.ReplaceAll(myScope, "");
303     if (enumName.EndsWith("::"))
304     enumName += "<i>[unnamed]</i>";
305     Ssiz_t startClassName = 0;
306     if (!enumName.BeginsWith("enum "))
307     classFile << "enum ";
308     else
309     startClassName = 5;
310    
311     Ssiz_t endClassName = enumName.Last(':'); // need template handling here!
312     if (endClassName != kNPOS && endClassName > 0 && enumName[endClassName - 1] == ':') {
313     // TClass* cl = fHtml->GetClass(TString(enumName(startClassName, endClassName - startClassName - 1)));
314     TSubString substr(enumName(startClassName, endClassName - startClassName + 1));
315     // if (cl)
316     // ReferenceEntity(substr, cl);
317     enumName.Insert(substr.Start() + substr.Length(), "</span>");
318     enumName.Insert(substr.Start(), "<span class=\"baseclass\">");
319     }
320     classFile << enumName << " { ";
321     } else
322     if (access < 3) {
323     if (member->Property() & G__BIT_ISSTATIC)
324     classFile << "static ";
325     fParser->DecorateKeywords(classFile, member->GetFullTypeName());
326     }
327    
328     TString mangled(member->GetClass()->GetName());
329     NameSpace2FileName(mangled);
330     classFile << "</td><td class=\"dataname\"><a ";
331     if (member->GetClass() != fCurrentClass) {
332     classFile << "href=\"";
333     TString htmlFile;
334     fHtml->GetHtmlFileName(member->GetClass(), htmlFile);
335     classFile << htmlFile << "#";
336     } else
337     classFile << "name=\"";
338     classFile << mangled;
339     classFile << ":";
340     mangled = member->GetName();
341     NameSpace2FileName(mangled);
342     classFile << mangled << "\">";
343     if (member->GetClass() == fCurrentClass)
344     classFile << "</a>";
345     if (access < 3 && member->GetClass() != fCurrentClass) {
346     classFile << "<span class=\"baseclass\">";
347     ReplaceSpecialChars(classFile, member->GetClass()->GetName());
348     classFile << "::</span>";
349     }
350     ReplaceSpecialChars(classFile, member->GetName());
351    
352     // Add the dimensions to "array" members
353     for (Int_t indx = 0; indx < member->GetArrayDim(); ++indx)
354     if (member->GetMaxIndex(indx) <= 0)
355     break;
356     else
357     classFile << "[" << member->GetMaxIndex(indx) << "]";
358    
359     if (member->GetClass() != fCurrentClass)
360     classFile << "</a>";
361     classFile << "</td>";
362     if (member->GetTitle() && member->GetTitle()[0]) {
363     classFile << "<td class=\"datadesc\">";
364     ReplaceSpecialChars(classFile, member->GetTitle());
365     } else classFile << "<td>";
366     classFile << "</td></tr>" << endl;
367     } // for members
368    
369     if (prevEnumName.Length()) {
370     classFile << "<tr class=\"data";
371     if (prevIsInh)
372     classFile << "inh";
373     classFile << "\"><td class=\"datatype\">};</td><td></td><td></td></tr>" << endl;
374     }
375     classFile << endl << "</table></div>" << endl;
376     } // for access
377    
378     classFile << "</div>" << endl; // datamembers
379     }
380    
381     //______________________________________________________________________________
382     Bool_t TClassDocOutput::ClassDotCharts(std::ostream& out)
383     {
384     // This function builds the class charts for one class in GraphViz/Dot format,
385     // i.e. the inheritance diagram, the include dependencies, and the library
386     // dependency.
387     //
388     // Input: out - output file stream
389    
390     if (!fHtml->HaveDot())
391     return kFALSE;
392    
393     TString title(fCurrentClass->GetName());
394     NameSpace2FileName(title);
395    
396     TString dir("inh");
397     gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
398     gSystem->MakeDirectory(dir);
399    
400     dir = "inhmem";
401     gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
402     gSystem->MakeDirectory(dir);
403    
404     dir = "incl";
405     gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
406     gSystem->MakeDirectory(dir);
407    
408     dir = "lib";
409     gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
410     gSystem->MakeDirectory(dir);
411    
412     TString filenameInh(title);
413     gSystem->PrependPathName("inh", filenameInh);
414     gSystem->PrependPathName(fHtml->GetOutputDir(), filenameInh);
415     filenameInh += "_Inh";
416     if (!CreateDotClassChartInh(filenameInh + ".dot") ||
417     !RunDot(filenameInh, &out))
418     return kFALSE;
419    
420     TString filenameInhMem(title);
421     gSystem->PrependPathName("inhmem", filenameInhMem);
422     gSystem->PrependPathName(fHtml->GetOutputDir(), filenameInhMem);
423     filenameInhMem += "_InhMem";
424     if (CreateDotClassChartInhMem(filenameInhMem + ".dot"))
425     RunDot(filenameInhMem, &out);
426    
427     TString filenameIncl(title);
428     gSystem->PrependPathName("incl", filenameIncl);
429     gSystem->PrependPathName(fHtml->GetOutputDir(), filenameIncl);
430     filenameIncl += "_Incl";
431     if (CreateDotClassChartIncl(filenameIncl + ".dot"))
432     RunDot(filenameIncl, &out);
433    
434     TString filenameLib(title);
435     gSystem->PrependPathName("lib", filenameLib);
436     gSystem->PrependPathName(fHtml->GetOutputDir(), filenameLib);
437     filenameLib += "_Lib";
438     if (CreateDotClassChartLib(filenameLib + ".dot"))
439     RunDot(filenameLib, &out);
440    
441     out << "<div class=\"tabs\">" << endl
442     << "<a id=\"img" << title << "_Inh\" class=\"tabsel\" href=\"inh/" << title << "_Inh.gif\" onclick=\"javascript:return SetImg('Charts','inh/" << title << "_Inh.gif');\">Inheritance</a>" << endl
443     << "<a id=\"img" << title << "_InhMem\" class=\"tab\" href=\"inhmem/" << title << "_InhMem.gif\" onclick=\"javascript:return SetImg('Charts','inhmem/" << title << "_InhMem.gif');\">Inherited Members</a>" << endl
444     << "<a id=\"img" << title << "_Incl\" class=\"tab\" href=\"incl/" << title << "_Incl.gif\" onclick=\"javascript:return SetImg('Charts','incl/" << title << "_Incl.gif');\">Includes</a>" << endl
445     << "<a id=\"img" << title << "_Lib\" class=\"tab\" href=\"lib/" << title << "_Lib.gif\" onclick=\"javascript:return SetImg('Charts','lib/" << title << "_Lib.gif');\">Libraries</a><br/>" << endl
446     << "</div><div class=\"classcharts\"><div class=\"classchartswidth\"></div>" << endl
447     << "<img id=\"Charts\" alt=\"Class Charts\" class=\"classcharts\" usemap=\"#Map" << title << "_Inh\" src=\"inh/" << title << "_Inh.gif\"/></div>" << endl;
448    
449     return kTRUE;
450     }
451    
452     //______________________________________________________________________________
453     void TClassDocOutput::ClassHtmlTree(std::ostream& out, TClass * classPtr,
454     ETraverse dir, int depth)
455     {
456     // This function builds the class tree for one class in HTML
457     // (inherited and succeeding classes, called recursively)
458     //
459     //
460     // Input: out - output file stream
461     // classPtr - pointer to the class
462     // dir - direction to traverse tree: up, down or both
463     //
464    
465     if (dir == kBoth) {
466     out << "<!--INHERITANCE TREE-->" << endl;
467    
468     // draw class tree into nested tables recursively
469     out << "<table><tr><td width=\"10%\"></td><td width=\"70%\">"
470     << "<a href=\"ClassHierarchy.html\">Inheritance Chart</a>:</td></tr>";
471     out << "<tr class=\"inhtree\"><td width=\"10%\"></td><td width=\"70%\">";
472    
473     out << "<table class=\"inhtree\"><tr><td>" << endl;
474     out << "<table width=\"100%\" border=\"0\" ";
475     out << "cellpadding =\"0\" cellspacing=\"2\"><tr>" << endl;
476     } else {
477     out << "<table><tr>";
478     }
479    
480     ////////////////////////////////////////////////////////
481     // Loop up to mother classes
482     if (dir == kUp || dir == kBoth) {
483    
484     // make a loop on base classes
485     TBaseClass *inheritFrom;
486     TIter nextBase(classPtr->GetListOfBases());
487    
488     UInt_t bgcolor=255-depth*8;
489     Bool_t first = kTRUE;
490     while ((inheritFrom = (TBaseClass *) nextBase())) {
491    
492     if (first) {
493     out << "<td><table><tr>" << endl;
494     first = kFALSE;
495     } else
496     out << "</tr><tr>" << endl;
497     out << "<td bgcolor=\""
498     << Form("#%02x%02x%02x", bgcolor, bgcolor, bgcolor)
499     << "\" align=\"right\">" << endl;
500     // get a class
501     TClass *classInh = fHtml->GetClass((const char *) inheritFrom->GetName());
502     if (classInh)
503     ClassHtmlTree(out, classInh, kUp, depth+1);
504     else
505     out << "<tt>"
506     << (const char *) inheritFrom->GetName()
507     << "</tt>";
508     out << "</td>"<< endl;
509     }
510     if (!first) {
511     out << "</tr></table></td>" << endl; // put it in additional row in table
512     out << "<td>&larr;</td>";
513     }
514     }
515    
516     out << "<td>" << endl; // put it in additional row in table
517     ////////////////////////////////////////////////////////
518     // Output Class Name
519    
520     const char *className = classPtr->GetName();
521     TString htmlFile;
522     fHtml->GetHtmlFileName(classPtr, htmlFile);
523     TString anchor(className);
524     NameSpace2FileName(anchor);
525    
526     if (dir == kUp) {
527     if (htmlFile) {
528     out << "<center><tt><a name=\"" << anchor;
529     out << "\" href=\"" << htmlFile << "\">";
530     ReplaceSpecialChars(out, className);
531     out << "</a></tt></center>" << endl;
532     } else
533     ReplaceSpecialChars(out, className);
534     }
535    
536     if (dir == kBoth) {
537     if (htmlFile.Length()) {
538     out << "<center><big><b><tt><a name=\"" << anchor;
539     out << "\" href=\"" << htmlFile << "\">";
540     ReplaceSpecialChars(out, className);
541     out << "</a></tt></b></big></center>" << endl;
542     } else
543     ReplaceSpecialChars(out, className);
544     }
545    
546     out << "</td>" << endl; // put it in additional row in table
547    
548     ////////////////////////////////////////////////////////
549     // Loop down to child classes
550    
551     if (dir == kDown || dir == kBoth) {
552    
553     // 1. make a list of class names
554     // 2. use DescendHierarchy
555    
556     out << "<td><table><tr>" << endl;
557     fHierarchyLines = 0;
558     DescendHierarchy(out,classPtr,10);
559    
560     out << "</tr></table>";
561     if (dir==kBoth && fHierarchyLines>=10)
562     out << "</td><td align=\"left\">&nbsp;<a href=\"ClassHierarchy.html\">[more...]</a>";
563     out<<"</td>" << endl;
564    
565     // free allocated memory
566     }
567    
568     out << "</tr></table>" << endl;
569     if (dir == kBoth)
570     out << "</td></tr></table></td></tr></table>"<<endl;
571     }
572    
573    
574     //______________________________________________________________________________
575     void TClassDocOutput::ClassTree(TVirtualPad * psCanvas, Bool_t force)
576     {
577     // It makes a graphical class tree
578     //
579     //
580     // Input: psCanvas - pointer to the current canvas
581     // classPtr - pointer to the class
582     //
583    
584     if (!psCanvas || !fCurrentClass)
585     return;
586    
587     TString filename(fCurrentClass->GetName());
588     NameSpace2FileName(filename);
589    
590     gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
591    
592    
593     filename += "_Tree.pdf";
594    
595     if (IsModified(fCurrentClass, kTree) || force) {
596     // TCanvas already prints pdf being saved
597     // Printf(fHtml->GetCounterFormat(), "", "", filename);
598     fCurrentClass->Draw("same");
599     Int_t saveErrorIgnoreLevel = gErrorIgnoreLevel;
600     gErrorIgnoreLevel = kWarning;
601     psCanvas->SaveAs(filename);
602     gErrorIgnoreLevel = saveErrorIgnoreLevel;
603     } else
604     Printf(fHtml->GetCounterFormat(), "-no change-", "", filename.Data());
605     }
606    
607     //______________________________________________________________________________
608     Bool_t TClassDocOutput::CreateDotClassChartInh(const char* filename)
609     {
610     // Build the class tree for one class in GraphViz/Dot format
611     //
612     //
613     // Input: filename - output dot file incl. path
614    
615     std::ofstream outdot(filename);
616     outdot << "strict digraph G {" << endl
617     << "rankdir=RL;" << endl
618     << "ranksep=2;" << endl
619     << "nodesep=0;" << endl
620     << "size=\"8,10\";" << endl
621     << "ratio=auto;" << endl
622     << "margin=0;" << endl
623     << "node [shape=plaintext,fontsize=40,width=4,height=0.75];" << endl
624     << "\"" << fCurrentClass->GetName() << "\" [shape=ellipse];" << endl;
625    
626     std::stringstream ssDep;
627     std::list<TClass*> writeBasesFor;
628     writeBasesFor.push_back(fCurrentClass);
629     Bool_t haveBases = fCurrentClass->GetListOfBases() &&
630     fCurrentClass->GetListOfBases()->GetSize();
631     if (haveBases) {
632     outdot << "{" << endl;
633     while (!writeBasesFor.empty()) {
634     TClass* cl = writeBasesFor.front();
635     writeBasesFor.pop_front();
636     if (cl != fCurrentClass) {
637     outdot << " \"" << cl->GetName() << "\"";
638     const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
639     if (htmlFileName)
640     outdot << " [URL=\"" << htmlFileName << "\"]";
641     outdot << ";" << endl;
642     }
643     if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
644     ssDep << " \"" << cl->GetName() << "\" -> {";
645     TIter iBase(cl->GetListOfBases());
646     TBaseClass* base = 0;
647     while ((base = (TBaseClass*)iBase())) {
648     ssDep << " \"" << base->GetName() << "\";";
649     writeBasesFor.push_back(base->GetClassPointer());
650     }
651     ssDep << "}" << endl;
652     }
653     }
654     outdot << "}" << endl; // cluster
655     }
656    
657     std::map<TClass*, Int_t> derivesFromMe;
658     std::map<TClass*, unsigned int> entriesPerDerived;
659     std::set<TClass*> wroteNode;
660     wroteNode.insert(fCurrentClass);
661     static const unsigned int maxClassesPerDerived = 20;
662     fHtml->GetDerivedClasses(fCurrentClass, derivesFromMe);
663     outdot << "{" << endl;
664     for (Int_t level = 1; kTRUE; ++level) {
665     Bool_t levelExists = kFALSE;
666     for (std::map<TClass*, Int_t>::iterator iDerived = derivesFromMe.begin();
667     iDerived != derivesFromMe.end(); ++iDerived) {
668     if (iDerived->second != level) continue;
669     levelExists = kTRUE;
670     TIter iBaseOfDerived(iDerived->first->GetListOfBases());
671     TBaseClass* baseDerived = 0;
672     Bool_t writeNode = kFALSE;
673     TClass* writeAndMoreFor = 0;
674     while ((baseDerived = (TBaseClass*) iBaseOfDerived())) {
675     TClass* clBaseDerived = baseDerived->GetClassPointer();
676     if (clBaseDerived->InheritsFrom(fCurrentClass)
677     && wroteNode.find(clBaseDerived) != wroteNode.end()) {
678     unsigned int& count = entriesPerDerived[clBaseDerived];
679     if (count < maxClassesPerDerived) {
680     writeNode = kTRUE;
681     ssDep << "\"" << iDerived->first->GetName() << "\" -> \""
682     << clBaseDerived->GetName() << "\";" << endl;
683     ++count;
684     } else if (count == maxClassesPerDerived) {
685     writeAndMoreFor = clBaseDerived;
686     ssDep << "\"...andmore" << clBaseDerived->GetName() << "\"-> \""
687     << clBaseDerived->GetName() << "\";" << endl;
688     ++count;
689     }
690     }
691     }
692    
693     if (writeNode) {
694     wroteNode.insert(iDerived->first);
695     outdot << " \"" << iDerived->first->GetName() << "\"";
696     const char* htmlFileName = fHtml->GetHtmlFileName(iDerived->first->GetName());
697     if (htmlFileName)
698     outdot << " [URL=\"" << htmlFileName << "\"]";
699     outdot << ";" << endl;
700     } else if (writeAndMoreFor) {
701     outdot << " \"...andmore" << writeAndMoreFor->GetName()
702     << "\" [label=\"...and more\",fontname=\"Times-Italic\",fillcolor=lightgrey,style=filled];" << endl;
703     }
704     }
705     if (!levelExists) break;
706     }
707     outdot << "}" << endl; // cluster
708    
709     outdot << ssDep.str();
710    
711     outdot << "}" << endl; // digraph
712    
713     return kTRUE;
714     }
715    
716     //______________________________________________________________________________
717     Bool_t TClassDocOutput::CreateDotClassChartInhMem(const char* filename) {
718     // Build the class tree of inherited members for one class in GraphViz/Dot format
719     //
720     // Input: filename - output dot file incl. path
721    
722     std::ofstream outdot(filename);
723     outdot << "strict digraph G {" << endl
724     << "ratio=auto;" << endl
725     << "rankdir=RL;" << endl
726     << "compound=true;" << endl
727     << "constraint=false;" << endl
728     << "ranksep=0.1;" << endl
729     << "nodesep=0;" << endl
730     << "margin=0;" << endl;
731     outdot << " node [style=filled,width=0.7,height=0.15,fixedsize=true,shape=plaintext,fontsize=10];" << endl;
732    
733     std::stringstream ssDep;
734     const int numColumns = 3;
735    
736     std::list<TClass*> writeBasesFor;
737     writeBasesFor.push_back(fCurrentClass);
738     while (!writeBasesFor.empty()) {
739     TClass* cl = writeBasesFor.front();
740     writeBasesFor.pop_front();
741    
742     const char* htmlFileName = fHtml->GetHtmlFileName(cl->GetName());
743    
744     outdot << "subgraph \"cluster" << cl->GetName() << "\" {" << endl
745     << " color=lightgray;" << endl
746     << " label=\"" << cl->GetName() << "\";" << endl;
747     if (cl != fCurrentClass && htmlFileName)
748     outdot << " URL=\"" << htmlFileName << "\"" << endl;
749    
750     //Bool_t haveMembers = (cl->GetListOfDataMembers() && cl->GetListOfDataMembers()->GetSize());
751     Bool_t haveFuncs = cl->GetListOfMethods() && cl->GetListOfMethods()->GetSize();
752    
753     // DATA MEMBERS
754     {
755     // make sure each member name is listed only once
756     // that's useless for data members, but symmetric to what we have for methods
757     std::map<std::string, TDataMember*> dmMap;
758    
759     {
760     TIter iDM(cl->GetListOfDataMembers());
761     TDataMember* dm = 0;
762     while ((dm = (TDataMember*) iDM()))
763     dmMap[dm->GetName()] = dm;
764     }
765    
766     outdot << "subgraph \"clusterData0" << cl->GetName() << "\" {" << endl
767     << " color=white;" << endl
768     << " label=\"\";" << endl
769     << " \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
770     TString prevColumnNode;
771     Int_t pos = dmMap.size();
772     Int_t column = 0;
773     Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
774     for (std::map<std::string, TDataMember*>::iterator iDM = dmMap.begin();
775     iDM != dmMap.end(); ++iDM, --pos) {
776     TDataMember* dm = iDM->second;
777     TString nodeName(cl->GetName());
778     nodeName += "::";
779     nodeName += dm->GetName();
780     if (iDM == dmMap.begin())
781     prevColumnNode = nodeName;
782    
783     outdot << "\"" << nodeName << "\" [label=\""
784     << dm->GetName() << "\"";
785     if (dm->Property() & kIsPrivate)
786     outdot << ",color=\"#FFCCCC\"";
787     else if (dm->Property() & kIsProtected)
788     outdot << ",color=\"#FFFF77\"";
789     else
790     outdot << ",color=\"#CCFFCC\"";
791     outdot << "];" << endl;
792     if (pos % newColumnEvery == 1) {
793     ++column;
794     outdot << "};" << endl // end dataR
795     << "subgraph \"clusterData" << column << cl->GetName() << "\" {" << endl
796     << " color=white;" << endl
797     << " label=\"\";" << endl
798     << " \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
799     } else if (iDM != dmMap.begin() && pos % newColumnEvery == 0) {
800     ssDep << "\"" << prevColumnNode
801     << "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
802     prevColumnNode = nodeName;
803     }
804     }
805    
806     while (column < numColumns - 1) {
807     ++column;
808     outdot << " \"clusterNode" << column << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
809     }
810    
811     outdot << "};" << endl; // subgraph dataL/R
812     } // DATA MEMBERS
813    
814     // FUNCTION MEMBERS
815     if (haveFuncs) {
816     // make sure each member name is listed only once
817     std::map<std::string, TMethod*> methMap;
818    
819     {
820     TIter iMeth(cl->GetListOfMethods());
821     TMethod* meth = 0;
822     while ((meth = (TMethod*) iMeth()))
823     methMap[meth->GetName()] = meth;
824     }
825    
826     outdot << "subgraph \"clusterFunc0" << cl->GetName() << "\" {" << endl
827     << " color=white;" << endl
828     << " label=\"\";" << endl
829     << " \"clusterNode0" << cl->GetName() << "\" [height=0,width=0,style=invis];" << endl;
830    
831     TString prevColumnNodeFunc;
832     Int_t pos = methMap.size();
833     Int_t column = 0;
834     Int_t newColumnEvery = (pos + numColumns - 1) / numColumns;
835     for (std::map<std::string, TMethod*>::iterator iMeth = methMap.begin();
836     iMeth != methMap.end(); ++iMeth, --pos) {
837     TMethod* meth = iMeth->second;
838     TString nodeName(cl->GetName());
839     nodeName += "::";
840     nodeName += meth->GetName();
841     if (iMeth == methMap.begin())
842     prevColumnNodeFunc = nodeName;
843    
844     outdot << "\"" << nodeName << "\" [label=\"" << meth->GetName() << "\"";
845     if (cl != fCurrentClass &&
846     fCurrentClass->GetMethodAny(meth->GetName()))
847     outdot << ",color=\"#777777\"";
848     else if (meth->Property() & kIsPrivate)
849     outdot << ",color=\"#FFCCCC\"";
850     else if (meth->Property() & kIsProtected)
851     outdot << ",color=\"#FFFF77\"";
852     else
853     outdot << ",color=\"#CCFFCC\"";
854     outdot << "];" << endl;
855     if (pos % newColumnEvery == 1) {
856     ++column;
857     outdot << "};" << endl // end funcR
858     << "subgraph \"clusterFunc" << column << cl->GetName() << "\" {" << endl
859     << " color=white;" << endl
860     << " label=\"\";" << endl;
861     } else if (iMeth != methMap.begin() && pos % newColumnEvery == 0) {
862     ssDep << "\"" << prevColumnNodeFunc
863     << "\" -> \"" << nodeName << "\""<< " [style=invis,weight=100];" << endl;
864     prevColumnNodeFunc = nodeName;
865     }
866     }
867     outdot << "};" << endl; // subgraph funcL/R
868     }
869    
870     outdot << "}" << endl; // cluster class
871    
872     for (Int_t pos = 0; pos < numColumns - 1; ++pos)
873     ssDep << "\"clusterNode" << pos << cl->GetName() << "\" -> \"clusterNode" << pos + 1 << cl->GetName() << "\" [style=invis];" << endl;
874    
875     if (cl->GetListOfBases() && cl->GetListOfBases()->GetSize()) {
876     TIter iBase(cl->GetListOfBases());
877     TBaseClass* base = 0;
878     while ((base = (TBaseClass*)iBase())) {
879     ssDep << " \"clusterNode" << numColumns - 1 << cl->GetName() << "\" -> "
880     << " \"clusterNode0" << base->GetName() << "\" [ltail=\"cluster" << cl->GetName()
881     << "\",lhead=\"cluster" << base->GetName() << "\"";
882     if (base != cl->GetListOfBases()->First())
883     ssDep << ",weight=0";
884     ssDep << "];" << endl;
885     writeBasesFor.push_back(base->GetClassPointer());
886     }
887     }
888     }
889    
890     outdot << ssDep.str();
891    
892     outdot << "}" << endl; // digraph
893    
894     return kTRUE;
895     }
896    
897     //______________________________________________________________________________
898     Bool_t TClassDocOutput::CreateDotClassChartIncl(const char* filename) {
899     // Build the include dependency graph for one class in
900     // GraphViz/Dot format
901     //
902     // Input: filename - output dot file incl. path
903    
904     R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
905    
906     std::map<std::string, std::string> filesToParse;
907     std::list<std::string> listFilesToParse;
908     TString declFileName;
909     TString implFileName;
910     fHtml->GetImplFileName(fCurrentClass, kFALSE, implFileName);
911     if (fHtml->GetDeclFileName(fCurrentClass, kFALSE, declFileName)) {
912     TString real;
913     if (fHtml->GetDeclFileName(fCurrentClass, kTRUE, real)) {
914     filesToParse[declFileName.Data()] = real.Data();
915     listFilesToParse.push_back(declFileName.Data());
916     }
917     }
918     /* do it only for the header
919     if (implFileName && strlen(implFileName)) {
920     char* real = gSystem->Which(fHtml->GetInputPath(), implFileName, kReadPermission);
921     if (real) {
922     filesToParse[implFileName] = real;
923     listFilesToParse.push_back(implFileName);
924     delete real;
925     }
926     }
927     */
928    
929     std::ofstream outdot(filename);
930     outdot << "strict digraph G {" << endl
931     << "ratio=compress;" << endl
932     << "rankdir=TB;" << endl
933     << "concentrate=true;" << endl
934     << "ranksep=0;" << endl
935     << "nodesep=0;" << endl
936     << "size=\"8,10\";" << endl
937     << "node [fontsize=20,shape=plaintext];" << endl;
938    
939     for (std::list<std::string>::iterator iFile = listFilesToParse.begin();
940     iFile != listFilesToParse.end(); ++iFile) {
941     ifstream in(filesToParse[*iFile].c_str());
942     std::string line;
943     while (in && !in.eof()) {
944     std::getline(in, line);
945     size_t pos = 0;
946     while (line[pos] == ' ' || line[pos] == '\t') ++pos;
947     if (line[pos] != '#') continue;
948     ++pos;
949     while (line[pos] == ' ' || line[pos] == '\t') ++pos;
950     if (line.compare(pos, 8, "include ") != 0) continue;
951     pos += 8;
952     while (line[pos] == ' ' || line[pos] == '\t') ++pos;
953     if (line[pos] != '"' && line[pos] != '<')
954     continue;
955     char delim = line[pos];
956     if (delim == '<') delim = '>';
957     ++pos;
958     line.erase(0, pos);
959     pos = 0;
960     pos = line.find(delim);
961     if (pos == std::string::npos) continue;
962     line.erase(pos);
963     if (filesToParse.find(line) == filesToParse.end()) {
964     TString sysfilename;
965     if (!GetHtml()->GetPathDefinition().GetFileNameFromInclude(line.c_str(), sysfilename))
966     continue;
967     listFilesToParse.push_back(line);
968     filesToParse[line] = sysfilename;
969     if (*iFile == implFileName.Data() || *iFile == declFileName.Data())
970     outdot << "\"" << *iFile << "\" [style=filled,fillcolor=lightgray];" << endl;
971     }
972     outdot << "\"" << *iFile << "\" -> \"" << line << "\";" << endl;
973     }
974     }
975    
976     outdot << "}" << endl; // digraph
977    
978     return kTRUE;
979     }
980    
981     //______________________________________________________________________________
982     Bool_t TClassDocOutput::CreateDotClassChartLib(const char* filename) {
983     // Build the library dependency graph for one class in
984     // GraphViz/Dot format
985     //
986     // Input: filename - output dot file incl. path
987    
988     std::ofstream outdot(filename);
989     outdot << "strict digraph G {" << endl
990     << "ratio=auto;" << endl
991     << "rankdir=RL;" << endl
992     << "compound=true;" << endl
993     << "constraint=false;" << endl
994     << "ranksep=0.7;" << endl
995     << "nodesep=0.3;" << endl
996     << "size=\"8,8\";" << endl
997     << "ratio=compress;" << endl;
998    
999     TString libs(fCurrentClass->GetSharedLibs());
1000     outdot << "\"All Libraries\" [URL=\"LibraryDependencies.html\",shape=box,rank=max,fillcolor=lightgray,style=filled];" << endl;
1001    
1002     if (libs.Length()) {
1003     TString firstLib(libs);
1004     Ssiz_t end = firstLib.Index(' ');
1005     if (end != kNPOS) {
1006     firstLib.Remove(end, firstLib.Length());
1007     libs.Remove(0, end + 1);
1008     } else libs = "";
1009    
1010     {
1011     Ssiz_t posExt = firstLib.First(".");
1012     if (posExt != kNPOS)
1013     firstLib.Remove(posExt, firstLib.Length());
1014     }
1015    
1016     outdot << "\"All Libraries\" -> \"" << firstLib << "\" [style=invis];" << endl;
1017     outdot << "\"" << firstLib << "\" -> {" << endl;
1018    
1019     if (firstLib != "libCore")
1020     libs += " libCore";
1021     if (firstLib != "libCint")
1022     libs += " libCint";
1023     TString thisLib;
1024     for (Ssiz_t pos = 0; pos < libs.Length(); ++pos)
1025     if (libs[pos] != ' ')
1026     thisLib += libs[pos];
1027     else if (thisLib.Length()) {
1028     Ssiz_t posExt = thisLib.First(".");
1029     if (posExt != kNPOS)
1030     thisLib.Remove(posExt, thisLib.Length());
1031     outdot << " \"" << thisLib << "\";";
1032     thisLib = "";
1033     }
1034     // remaining lib
1035     if (thisLib.Length()) {
1036     Ssiz_t posExt = thisLib.First(".");
1037     if (posExt != kNPOS)
1038     thisLib.Remove(posExt, thisLib.Length());
1039     outdot << " \"" << thisLib << "\";";
1040     thisLib = "";
1041     }
1042     outdot << "}" << endl; // dependencies
1043     } else
1044     outdot << "\"No rlibmap information avaliable.\"" << endl;
1045    
1046     outdot << "}" << endl; // digraph
1047    
1048     return kTRUE;
1049     }
1050    
1051     //______________________________________________________________________________
1052     void TClassDocOutput::CreateClassHierarchy(std::ostream& out, const char* docFileName)
1053     {
1054     // Create the hierarchical class list part for the current class's
1055     // base classes. docFileName contains doc for fCurrentClass.
1056     //
1057    
1058     // Find basic base classes
1059     TList *bases = fCurrentClass->GetListOfBases();
1060     if (!bases || bases->IsEmpty())
1061     return;
1062    
1063     out << "<hr />" << endl;
1064    
1065     out << "<table><tr><td><ul><li><tt>";
1066     if (docFileName) {
1067     out << "<a name=\"" << fCurrentClass->GetName() << "\" href=\""
1068     << docFileName << "\">";
1069     ReplaceSpecialChars(out, fCurrentClass->GetName());
1070     out << "</a>";
1071     } else {
1072     ReplaceSpecialChars(out, fCurrentClass->GetName());
1073     }
1074    
1075     // find derived classes
1076     out << "</tt></li></ul></td>";
1077     fHierarchyLines = 0;
1078     DescendHierarchy(out, fCurrentClass);
1079    
1080     out << "</tr></table>" << endl;
1081     }
1082    
1083     //______________________________________________________________________________
1084     Bool_t TClassDocOutput::CreateHierarchyDot()
1085     {
1086     // Create a hierarchical class list
1087     // The algorithm descends from the base classes and branches into
1088     // all derived classes. Mixing classes are displayed several times.
1089     //
1090     //
1091    
1092     const char* title = "ClassHierarchy";
1093     TString filename(title);
1094     gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
1095    
1096     // open out file
1097     std::ofstream dotout(filename + ".dot");
1098    
1099     if (!dotout.good()) {
1100     Error("CreateHierarchy", "Can't open file '%s.dot' !",
1101     filename.Data());
1102     return kFALSE;
1103     }
1104    
1105     dotout << "digraph G {" << endl
1106     << "ratio=auto;" << endl
1107     << "rankdir=RL;" << endl;
1108    
1109     // loop on all classes
1110     TClassDocInfo* cdi = 0;
1111     TIter iClass(fHtml->GetListOfClasses());
1112     while ((cdi = (TClassDocInfo*)iClass())) {
1113    
1114     TDictionary *dict = cdi->GetClass();
1115     TClass *cl = dynamic_cast<TClass*>(dict);
1116     if (cl == 0) {
1117     if (!dict)
1118     Warning("THtml::CreateHierarchy", "skipping class %s\n", cdi->GetName());
1119     continue;
1120     }
1121    
1122     // Find immediate base classes
1123     TList *bases = cl->GetListOfBases();
1124     if (bases && !bases->IsEmpty()) {
1125     dotout << "\"" << cdi->GetName() << "\" -> { ";
1126     TIter iBase(bases);
1127     TBaseClass* base = 0;
1128     while ((base = (TBaseClass*) iBase())) {
1129     // write out current class
1130     if (base != bases->First())
1131     dotout << "; ";
1132     dotout << "\"" << base->GetName() << "\"";
1133     }
1134     dotout << "};" << endl;
1135     } else
1136     // write out current class - no bases
1137     dotout << "\"" << cdi->GetName() << "\";" << endl;
1138    
1139     }
1140    
1141     dotout << "}";
1142     dotout.close();
1143    
1144     std::ofstream out(filename + ".html");
1145     if (!out.good()) {
1146     Error("CreateHierarchy", "Can't open file '%s.html' !",
1147     filename.Data());
1148     return kFALSE;
1149     }
1150    
1151     Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), (filename + ".html").Data());
1152     // write out header
1153     WriteHtmlHeader(out, "Class Hierarchy");
1154     out << "<h1>Class Hierarchy</h1>" << endl;
1155    
1156     WriteSearch(out);
1157    
1158     RunDot(filename, &out);
1159    
1160     out << "<img usemap=\"#Map" << title << "\" src=\"" << title << ".gif\"/>" << endl;
1161     // write out footer
1162     WriteHtmlFooter(out);
1163     return kTRUE;
1164     }
1165    
1166     //______________________________________________________________________________
1167     void TClassDocOutput::CreateSourceOutputStream(std::ostream& out, const char* extension,
1168     TString& sourceHtmlFileName)
1169     {
1170     // Open a Class.cxx.html file, where Class is defined by classPtr, and .cxx.html by extension
1171     // It's created in fHtml->GetOutputDir()/src. If successful, the HTML header is written to out.
1172    
1173     TString sourceHtmlDir("src");
1174     gSystem->PrependPathName(fHtml->GetOutputDir(), sourceHtmlDir);
1175     // create directory if necessary
1176     {
1177     R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1178    
1179     if (gSystem->AccessPathName(sourceHtmlDir))
1180     gSystem->MakeDirectory(sourceHtmlDir);
1181     }
1182     sourceHtmlFileName = fCurrentClass->GetName();
1183     NameSpace2FileName(sourceHtmlFileName);
1184     gSystem->PrependPathName(sourceHtmlDir, sourceHtmlFileName);
1185     sourceHtmlFileName += extension;
1186     dynamic_cast<std::ofstream&>(out).open(sourceHtmlFileName);
1187     if (!out) {
1188     Warning("LocateMethodsInSource", "Can't open beautified source file '%s' for writing!",
1189     sourceHtmlFileName.Data());
1190     sourceHtmlFileName.Remove(0);
1191     return;
1192     }
1193    
1194     // write a HTML header
1195     TString title(fCurrentClass->GetName());
1196     title += " - source file";
1197     WriteHtmlHeader(out, title, "../", fCurrentClass);
1198     out << "<pre class=\"code\">" << std::endl;
1199     }
1200    
1201     //______________________________________________________________________________
1202     void TClassDocOutput::DescendHierarchy(std::ostream& out, TClass* basePtr, Int_t maxLines, Int_t depth)
1203     {
1204     // Descend hierarchy recursively
1205     // loop over all classes and look for classes with base class basePtr
1206    
1207     if (maxLines)
1208     if (fHierarchyLines >= maxLines) {
1209     out << "<td></td>" << endl;
1210     return;
1211     }
1212    
1213     UInt_t numClasses = 0;
1214    
1215     TClassDocInfo* cdi = 0;
1216     TIter iClass(fHtml->GetListOfClasses());
1217     while ((cdi = (TClassDocInfo*)iClass()) && (!maxLines || fHierarchyLines<maxLines)) {
1218    
1219     TClass *classPtr = dynamic_cast<TClass*>(cdi->GetClass());
1220     if (!classPtr) continue;
1221    
1222     // find base classes with same name as basePtr
1223     TList* bases=classPtr->GetListOfBases();
1224     if (!bases) continue;
1225    
1226     TBaseClass *inheritFrom=(TBaseClass*)bases->FindObject(basePtr->GetName());
1227     if (!inheritFrom) continue;
1228    
1229     if (!numClasses)
1230     out << "<td>&larr;</td><td><table><tr>" << endl;
1231     else
1232     out << "</tr><tr>"<<endl;
1233     fHierarchyLines++;
1234     numClasses++;
1235     UInt_t bgcolor=255-depth*8;
1236     out << "<td bgcolor=\""
1237     << Form("#%02x%02x%02x", bgcolor, bgcolor, bgcolor)
1238     << "\">";
1239     out << "<table><tr><td>" << endl;
1240    
1241     TString htmlFile(cdi->GetHtmlFileName());
1242     if (htmlFile.Length()) {
1243     out << "<center><tt><a name=\"" << cdi->GetName() << "\" href=\""
1244     << htmlFile << "\">";
1245     ReplaceSpecialChars(out, cdi->GetName());
1246     out << "</a></tt></center>";
1247     } else {
1248     ReplaceSpecialChars(out, cdi->GetName());
1249     }
1250     // write title
1251     // commented out for now because it reduces overview
1252     /*
1253     len = strlen(classNames[i]);
1254     for (Int_t w = 0; w < (maxLen - len + 2); w++)
1255     out << ".";
1256     out << " ";
1257    
1258     out << "<a name=\"Title:";
1259     out << classPtr->GetName();
1260     out << "\">";
1261     ReplaceSpecialChars(out, classPtr->GetTitle());
1262     out << "</a></tt>" << endl;
1263     */
1264    
1265     out << "</td>" << endl;
1266     DescendHierarchy(out,classPtr,maxLines, depth+1);
1267     out << "</tr></table></td>" << endl;
1268    
1269     } // loop over all classes
1270     if (numClasses)
1271     out << "</tr></table></td>" << endl;
1272     else
1273     out << "<td></td>" << endl;
1274     }
1275    
1276     //______________________________________________________________________________
1277     void TClassDocOutput::MakeTree(Bool_t force /*= kFALSE*/)
1278     {
1279     // Create an output file with a graphical representation of the class
1280     // inheritance. If force, replace existing output file.
1281     // This routine does nothing if fHtml->HaveDot() is true - use
1282     // ClassDotCharts() instead!
1283    
1284     // class tree only if no dot, otherwise it's part of charts
1285     if (!fCurrentClass || fHtml->HaveDot())
1286     return;
1287    
1288     TString htmlFile;
1289     fHtml->GetHtmlFileName(fCurrentClass, htmlFile);
1290     if (htmlFile.Length()
1291     && (htmlFile.BeginsWith("http://")
1292     || htmlFile.BeginsWith("https://")
1293     || gSystem->IsAbsoluteFileName(htmlFile))
1294     ) {
1295     htmlFile.Remove(0);
1296     }
1297    
1298     if (!htmlFile.Length()) {
1299     TString what(fCurrentClass->GetName());
1300     what += " (source not found)";
1301     Printf(fHtml->GetCounterFormat(), "-skipped-", "", what.Data());
1302     return;
1303     }
1304    
1305     R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1306    
1307     // Create a canvas without linking against GUI libs
1308     Bool_t wasBatch = gROOT->IsBatch();
1309     if (!wasBatch)
1310     gROOT->SetBatch();
1311     TVirtualPad *psCanvas = (TVirtualPad*)gROOT->ProcessLineFast("new TCanvas(\"R__THtml\",\"psCanvas\",0,0,1000,1200);");
1312     if (!wasBatch)
1313     gROOT->SetBatch(kFALSE);
1314    
1315     if (!psCanvas) {
1316     Error("MakeTree", "Cannot create a TCanvas!");
1317     return;
1318     }
1319    
1320     // make a class tree
1321     ClassTree(psCanvas, force);
1322    
1323     psCanvas->Close();
1324     delete psCanvas;
1325     }
1326    
1327     //______________________________________________________________________________
1328     void TClassDocOutput::WriteClassDescription(std::ostream& out, const TString& description)
1329     {
1330     // Called by TDocParser::LocateMethods(), this hook writes out the class description
1331     // found by TDocParser. It's even called if none is found, i.e. if the first method
1332     // has occurred before a class description is found, so missing class descriptions
1333     // can be handled.
1334     // For HTML, its creates the description block, the list of functions and data
1335     // members, and the inheritance tree or, if Graphviz's dot is found, the class charts.
1336    
1337     // Class Description Title
1338     out << "<div class=\"dropshadow\"><div class=\"withshadow\">";
1339     TString anchor(fCurrentClass->GetName());
1340     NameSpace2FileName(anchor);
1341     out << "<h1><a name=\"" << anchor;
1342     out << ":description\"></a>";
1343    
1344     if (fHtml->IsNamespace(fCurrentClass))
1345     out << "namespace ";
1346     else
1347     out << "class ";
1348     ReplaceSpecialChars(out, fCurrentClass->GetName());
1349    
1350    
1351     // make a loop on base classes
1352     Bool_t first = kTRUE;
1353     TBaseClass *inheritFrom;
1354     TIter nextBase(fCurrentClass->GetListOfBases());
1355    
1356     while ((inheritFrom = (TBaseClass *) nextBase())) {
1357     if (first) {
1358     out << ": ";
1359     first = kFALSE;
1360     } else
1361     out << ", ";
1362     Long_t property = inheritFrom->Property();
1363     if (property & kIsPrivate)
1364     out << "private ";
1365     else if (property & kIsProtected)
1366     out << "protected ";
1367     else
1368     out << "public ";
1369    
1370     // get a class
1371     TClass *classInh = fHtml->GetClass(inheritFrom->GetName());
1372    
1373     TString htmlFile;
1374     fHtml->GetHtmlFileName(classInh, htmlFile);
1375    
1376     if (htmlFile.Length()) {
1377     // make a link to the base class
1378     out << "<a href=\"" << htmlFile << "\">";
1379     ReplaceSpecialChars(out, inheritFrom->GetName());
1380     out << "</a>";
1381     } else
1382     ReplaceSpecialChars(out, inheritFrom->GetName());
1383     }
1384     out << "</h1>" << endl;
1385    
1386     out << "<div class=\"classdescr\">" << endl;
1387    
1388     if (description.Length())
1389     out << "<pre>" << description << "</pre>";
1390    
1391     // typedefs pointing to this class:
1392     if (fCurrentClassesTypedefs && !fCurrentClassesTypedefs->IsEmpty()) {
1393     out << "<h4>This class is also known as (typedefs to this class)</h4>";
1394     TIter iTD(fCurrentClassesTypedefs);
1395     bool firsttd = true;
1396     TDataType* dt = 0;
1397     while ((dt = (TDataType*) iTD())) {
1398     if (!firsttd)
1399     out << ", ";
1400     else firsttd = false;
1401     fParser->DecorateKeywords(out, dt->GetName());
1402     }
1403     }
1404    
1405     out << "</div>" << std::endl
1406     << "</div></div>" << std::endl;
1407    
1408     ListFunctions(out);
1409     ListDataMembers(out);
1410    
1411     // create dot class charts or an html inheritance tree
1412     out << "<h2><a id=\"" << anchor
1413     << ":Class_Charts\"></a>Class Charts</h2>" << endl;
1414     if (!fHtml->IsNamespace(fCurrentClass))
1415     if (!ClassDotCharts(out))
1416     ClassHtmlTree(out, fCurrentClass);
1417    
1418     // header for the following function docs:
1419     out << "<h2>Function documentation</h2>" << endl;
1420     }
1421    
1422    
1423     //______________________________________________________________________________
1424     void TClassDocOutput::WriteClassDocHeader(std::ostream& classFile)
1425     {
1426     // Write out the introduction of a class description (shortcuts and links)
1427    
1428     classFile << "<a name=\"TopOfPage\"></a>" << endl;
1429    
1430    
1431     // show box with lib, include
1432     // needs to go first to allow title on the left
1433     TString sTitle(fCurrentClass->GetName());
1434     ReplaceSpecialChars(sTitle);
1435     if (fHtml->IsNamespace(fCurrentClass))
1436     sTitle.Prepend("namespace ");
1437     else
1438     sTitle.Prepend("class ");
1439    
1440     TString sInclude;
1441     TString sLib;
1442     const char* lib=fCurrentClass->GetSharedLibs();
1443     GetHtml()->GetPathDefinition().GetIncludeAs(fCurrentClass, sInclude);
1444     if (lib) {
1445     char* libDup=StrDup(lib);
1446     char* libDupSpace=strchr(libDup,' ');
1447     if (libDupSpace) *libDupSpace=0;
1448     char* libDupEnd=libDup+strlen(libDup);
1449     while (libDupEnd!=libDup)
1450     if (*(--libDupEnd)=='.') {
1451     *libDupEnd=0;
1452     break;
1453     }
1454     sLib = libDup;
1455     delete[] libDup;
1456     }
1457     classFile << "<script type=\"text/javascript\">WriteFollowPageBox('"
1458     << sTitle << "','" << sLib << "','" << sInclude << "');</script>" << endl;
1459    
1460     TString modulename;
1461     fHtml->GetModuleNameForClass(modulename, fCurrentClass);
1462     TModuleDocInfo* module = (TModuleDocInfo*) fHtml->GetListOfModules()->FindObject(modulename);
1463     WriteTopLinks(classFile, module, fCurrentClass->GetName());
1464    
1465     classFile << "<div class=\"descrhead\">" << endl
1466     << "<span class=\"descrtitle\">Source:</span>" << endl;
1467    
1468     // make a link to the '.cxx' file
1469     TString classFileName(fCurrentClass->GetName());
1470     NameSpace2FileName(classFileName);
1471    
1472     TString headerFileName;
1473     fHtml->GetDeclFileName(fCurrentClass, kFALSE, headerFileName);
1474     TString sourceFileName;
1475     fHtml->GetImplFileName(fCurrentClass, kFALSE, sourceFileName);
1476     if (headerFileName.Length())
1477     classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
1478     << ".h.html\">header file</a>" << endl;
1479    
1480     if (sourceFileName.Length())
1481     classFile << "<a class=\"descrheadentry\" href=\"src/" << classFileName
1482     << ".cxx.html\">source file</a>" << endl;
1483    
1484     if (!fHtml->IsNamespace(fCurrentClass) && !fHtml->HaveDot()) {
1485     // make a link to the inheritance tree (postscript)
1486     classFile << "<a class=\"descrheadentry\" href=\"" << classFileName << "_Tree.pdf\"";
1487     classFile << ">inheritance tree (.pdf)</a> ";
1488     }
1489    
1490     const TString& viewCVSLink = GetHtml()->GetViewCVS();
1491     Bool_t mustReplace = viewCVSLink.Contains("%f");
1492     if (viewCVSLink.Length()) {
1493     if (headerFileName.Length()) {
1494     TString link(viewCVSLink);
1495     TString sHeader(headerFileName);
1496     if (GetHtml()->GetProductName() && !strcmp(GetHtml()->GetProductName(), "ROOT")
1497     && sHeader.BeginsWith("include")) {
1498     sHeader.Remove(0,7);
1499     if (sourceFileName && strstr(sourceFileName, "src")) {
1500     TString src(sourceFileName);
1501     src.Remove(src.Index("src"), src.Length());
1502     src += "inc";
1503     sHeader.Prepend(src);
1504     } else {
1505     TString src(fCurrentClass->GetSharedLibs());
1506     Ssiz_t posEndLib = src.Index(' ');
1507     if (posEndLib != kNPOS)
1508     src.Remove(posEndLib, src.Length());
1509     if (src.BeginsWith("lib"))
1510     src.Remove(0, 3);
1511     posEndLib = src.Index('.');
1512     if (posEndLib != kNPOS)
1513     src.Remove(posEndLib, src.Length());
1514     src.ToLower();
1515     src += "/inc";
1516     sHeader.Prepend(src);
1517     }
1518     if (sHeader.BeginsWith("tmva/inc/TMVA"))
1519     sHeader.Remove(8, 5);
1520     }
1521     if (mustReplace) link.ReplaceAll("%f", sHeader);
1522     else link += sHeader;
1523     classFile << "<a class=\"descrheadentry\" href=\"" << link << "\">viewVC header</a> ";
1524     }
1525     if (sourceFileName.Length()) {
1526     TString link(viewCVSLink);
1527     if (mustReplace) link.ReplaceAll("%f", sourceFileName);
1528     else link += sourceFileName;
1529     classFile << "<a class=\"descrheadentry\" href=\"" << link << "\">viewVC source</a> ";
1530     }
1531     }
1532    
1533     TString currClassNameMangled(fCurrentClass->GetName());
1534     NameSpace2FileName(currClassNameMangled);
1535    
1536     TString wikiLink = GetHtml()->GetWikiURL();
1537     if (wikiLink.Length()) {
1538     if (wikiLink.Contains("%c")) wikiLink.ReplaceAll("%c", currClassNameMangled);
1539     else wikiLink += currClassNameMangled;
1540     classFile << "<a class=\"descrheadentry\" href=\"" << wikiLink << "\">wiki</a> ";
1541     }
1542    
1543     classFile << endl << "</div>" << endl;
1544    
1545     classFile << "<div class=\"descrhead\">" << endl
1546     << "<span class=\"descrtitle\">Sections:</span>" << endl
1547     << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled;
1548     if (fHtml->IsNamespace(fCurrentClass))
1549     classFile << ":description\">namespace description</a> ";
1550     else
1551     classFile << ":description\">class description</a> ";
1552     classFile << endl
1553     << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Function_Members\">function members</a>" << endl
1554     << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Data_Members\">data members</a>" << endl
1555     << "<a class=\"descrheadentry\" href=\"#" << currClassNameMangled << ":Class_Charts\">class charts</a>" << endl
1556     << "</div>" << endl
1557     << "</div>" << endl;
1558     }
1559    
1560    
1561     //______________________________________________________________________________
1562     void TClassDocOutput::WriteMethod(std::ostream& out, TString& ret,
1563     TString& name, TString& params,
1564     const char* filename, TString& anchor,
1565     TString& comment, TString& codeOneLiner,
1566     TMethod* guessedMethod)
1567     {
1568     // Write method name with return type ret and parameters param to out.
1569     // Build a link using file and anchor. Cooment it with comment, and
1570     // show the code codeOneLiner (set if the func consists of only one line
1571     // of code, immediately surrounded by "{","}"). Also updates fMethodNames's
1572     // count of method names.
1573    
1574     fParser->DecorateKeywords(ret);
1575     out << "<div class=\"funcdoc\"><span class=\"funcname\">"
1576     << ret << " <a class=\"funcname\" name=\"";
1577     TString mangled(fCurrentClass->GetName());
1578     NameSpace2FileName(mangled);
1579     out << mangled << ":";
1580     mangled = name;
1581     NameSpace2FileName(mangled);
1582     out << mangled << "\" href=\"src/" << filename;
1583     if (anchor.Length())
1584     out << "#" << anchor;
1585     out << "\">";
1586     ReplaceSpecialChars(out, name);
1587     out << "</a>";
1588     if (guessedMethod) {
1589     out << "(";
1590     TMethodArg* arg;
1591     TIter iParam(guessedMethod->GetListOfMethodArgs());
1592     Bool_t first = kTRUE;
1593     while ((arg = (TMethodArg*) iParam())) {
1594     if (!first) out << ", ";
1595     else first = kFALSE;
1596     TString paramGuessed(arg->GetFullTypeName());
1597     paramGuessed += " ";
1598     paramGuessed += arg->GetName();
1599     if (arg->GetDefault() && strlen(arg->GetDefault())) {
1600     paramGuessed += " = ";
1601     paramGuessed += arg->GetDefault();
1602     }
1603     fParser->DecorateKeywords(paramGuessed);
1604     out << paramGuessed;
1605     }
1606     out << ")";
1607     if (guessedMethod->Property() & kIsMethConst)
1608     out << " const";
1609     } else {
1610     fParser->DecorateKeywords(params);
1611     out << params;
1612     }
1613     out << "</span><br />" << std::endl;
1614    
1615     if (comment.Length())
1616     out << "<div class=\"funccomm\"><pre>" << comment << "</pre></div>" << std::endl;
1617    
1618     if (codeOneLiner.Length()) {
1619     out << std::endl << "<div class=\"code\"><code class=\"inlinecode\">"
1620     << codeOneLiner << "</code></div>" << std::endl
1621     << "<div style=\"clear:both;\"></div>" << std::endl;
1622     codeOneLiner.Remove(0);
1623     }
1624     out << "</div>" << std::endl;
1625     }
1626    
1627    
1628