Logo ROOT   6.16/01
Reference Guide
TDocOutput.cxx
Go to the documentation of this file.
1// @(#)root/html:$Id: 7ff9b72609794c66acf6b369c4eeddfbfc63cf55 $
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 "TDocOutput.h"
13
14#include "Riostream.h"
15#include "TClassDocOutput.h"
16#include "TClassEdit.h"
17#include "TDataMember.h"
18#include "TDataType.h"
19#include "TDocInfo.h"
20#include "TDocParser.h"
21#include "TEnv.h"
22#include "TGlobal.h"
23#include "THtml.h"
24#include "TInterpreter.h"
25#include "TMethod.h"
26#include "TPRegexp.h"
27#include "TROOT.h"
28#include "TSystem.h"
29#include "TUrl.h"
30#include "TVirtualMutex.h"
31#include "TVirtualPad.h"
32#include "TVirtualViewer3D.h"
33#include <vector>
34#include <list>
35#include <set>
36#include <sstream>
37#include <stdlib.h>
38
39namespace {
40
41 typedef std::vector<std::string> Words_t;
42 typedef Words_t::const_iterator SectionStart_t;
43
44 class TSectionInfo {
45 public:
46 TSectionInfo(SectionStart_t start, size_t chars, size_t size):
47 fStart(start), fChars(chars), fSize(size) {};
48
49 SectionStart_t fStart;
50 size_t fChars;
51 size_t fSize;
52 };
53 typedef std::list<TSectionInfo> SectionStarts_t;
54
55 static void Sections_BuildIndex(SectionStarts_t& sectionStarts,
56 SectionStart_t begin, SectionStart_t end,
57 size_t maxPerSection)
58 {
59 // for each assumed section border, check that previous entry's
60 // char[selectionChar] differs, else move section start forward
61
62 SectionStart_t cursor = begin;
63 if (sectionStarts.empty() || sectionStarts.back().fStart != cursor)
64 sectionStarts.push_back(TSectionInfo(cursor, 1, 0));
65
66 SectionStarts_t::iterator prevSection = sectionStarts.end();
67 --prevSection;
68
69 while (cursor != end) {
70 size_t numLeft = end - cursor;
71 size_t assumedNumSections = (numLeft + maxPerSection - 1 ) / maxPerSection;
72 size_t step = ((numLeft + assumedNumSections - 1) / assumedNumSections);
73 if (!step || step >= numLeft) return;
74 cursor += step;
75 if (cursor == end) break;
76
77 SectionStart_t addWhichOne = prevSection->fStart;
78
79 size_t selectionChar=1;
80 for (; selectionChar <= cursor->length() && addWhichOne == prevSection->fStart;
81 ++selectionChar) {
82 SectionStart_t checkPrev = cursor;
83 while (--checkPrev != prevSection->fStart
84 && !strncasecmp(checkPrev->c_str(), cursor->c_str(), selectionChar)) { }
85
86 SectionStart_t checkNext = cursor;
87 while (++checkNext != end
88 && !strncasecmp(checkNext->c_str(), cursor->c_str(), selectionChar)) { }
89
90 // if the previous matching one is closer but not previous section start, take it!
91 if (checkPrev != prevSection->fStart) {
92 if ((cursor - checkPrev) <= (checkNext - cursor))
93 addWhichOne = ++checkPrev;
94 else if (checkNext != end
95 && (size_t)(checkNext - cursor) < maxPerSection) {
96 addWhichOne = checkNext;
97 }
98 }
99 }
100 if (addWhichOne == prevSection->fStart)
101 addWhichOne = cursor;
102
103 selectionChar = 1;
104 while (selectionChar <= prevSection->fStart->length()
105 && selectionChar <= addWhichOne->length()
106 && !strncasecmp(prevSection->fStart->c_str(), addWhichOne->c_str(), selectionChar))
107 ++selectionChar;
108
109 sectionStarts.push_back(TSectionInfo(addWhichOne, selectionChar, 0));
110 cursor = addWhichOne;
111 ++prevSection;
112 } // while cursor != end
113 }
114
115 static void Sections_SetSize(SectionStarts_t& sectionStarts, const Words_t &words)
116 {
117 // Update the length of the sections
118 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
119 iSectionStart != sectionStarts.end(); ++iSectionStart) {
120 SectionStarts_t::iterator next = iSectionStart;
121 ++next;
122 if (next == sectionStarts.end()) {
123 iSectionStart->fSize = (words.end() - iSectionStart->fStart);
124 break;
125 }
126 iSectionStart->fSize = (next->fStart - iSectionStart->fStart);
127 }
128 }
129
130 static void Sections_PostMerge(SectionStarts_t& sectionStarts, const size_t maxPerSection)
131 {
132 // Merge sections that ended up being too small, up to maxPerSection entries
133 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
134 iSectionStart != sectionStarts.end();) {
135 SectionStarts_t::iterator iNextSectionStart = iSectionStart;
136 ++iNextSectionStart;
137 if (iNextSectionStart == sectionStarts.end()) break;
138 if (iNextSectionStart->fSize + iSectionStart->fSize < maxPerSection) {
139 iSectionStart->fSize += iNextSectionStart->fSize;
140 sectionStarts.erase(iNextSectionStart);
141 } else ++iSectionStart;
142 }
143 }
144
145 static void GetIndexChars(const Words_t& words, UInt_t numSectionsIn,
146 std::vector<std::string> &sectionMarkersOut)
147 {
148 // Given a list of words (class names, in this case), this function builds an
149 // optimal set of about numSectionIn sections (even if almost all words start
150 // with a "T"...), and returns the significant characters for each section start
151 // in sectionMarkersOut.
152
153 const size_t maxPerSection = (words.size() + numSectionsIn - 1)/ numSectionsIn;
154 SectionStarts_t sectionStarts;
155 Sections_BuildIndex(sectionStarts, words.begin(), words.end(), maxPerSection);
156 Sections_SetSize(sectionStarts, words);
157 Sections_PostMerge(sectionStarts, maxPerSection);
158
159 // convert to index markers
160 sectionMarkersOut.clear();
161 sectionMarkersOut.resize(sectionStarts.size());
162 size_t idx = 0;
163 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
164 iSectionStart != sectionStarts.end(); ++iSectionStart)
165 sectionMarkersOut[idx++] =
166 iSectionStart->fStart->substr(0, iSectionStart->fChars);
167 }
168
169 static void GetIndexChars(const std::list<std::string>& wordsIn, UInt_t numSectionsIn,
170 std::vector<std::string> &sectionMarkersOut)
171 {
172 // initialize word vector
173 Words_t words(wordsIn.size());
174 size_t idx = 0;
175 for (std::list<std::string>::const_iterator iWord = wordsIn.begin(); iWord != wordsIn.end(); ++iWord)
176 words[idx++] = *iWord;
177 GetIndexChars(words, numSectionsIn, sectionMarkersOut);
178 }
179
180}
181
182extern "C" { // std::qsort on solaris wants the sorter to be extern "C"
183
184 /////////////////////////////////////////////////////////////////////////////
185 /// Friend function for sorting strings, case insensitive
186 ///
187 ///
188 /// Input: name1 - pointer to the first string
189 /// name2 - pointer to the second string
190 ///
191 /// NOTE: This function compares its arguments and returns an integer less
192 /// than, equal to, or greater than zero, depending on whether name1
193 /// is lexicographically less than, equal to, or greater than name2,
194 /// but characters are forced to lower-case prior to comparison.
195 ///
196 ///
197
198 static int CaseInsensitiveSort(const void *name1, const void *name2)
199 {
200 return (strcasecmp(*((char **) name1), *((char **) name2)));
201 }
202}
203
204namespace {
205
206 // std::list::sort(with_stricmp_predicate) doesn't work with Solaris CC...
207 static void sort_strlist_stricmp(std::vector<std::string>& l)
208 {
209 // sort strings ignoring case - easier for humans
210 struct posList {
211 const char* str;
212 size_t pos;
213 };
214 posList* carr = new posList[l.size()];
215 size_t idx = 0;
216 for (size_t iS = 0, iSE = l.size(); iS < iSE; ++iS) {
217 carr[idx].pos = iS;
218 carr[idx++].str = l[iS].c_str();
219 }
220 qsort(&carr[0].str, idx, sizeof(posList), CaseInsensitiveSort);
221 std::vector<std::string> lsort(l.size());
222 for (size_t iS = 0, iSE = l.size(); iS < iSE; ++iS) {
223 lsort[iS].swap(l[carr[iS].pos]);
224 }
225 delete [] carr;
226 l.swap(lsort);
227 }
228
229}
230
231//______________________________________________________________________________
232//
233// THtml generated documentation is written to file by TDocOutput. So far only
234// output of HTML is implemented. Customization of the output should be done
235// with THtml's interfaces - TDocOutput should not be used nor re-implemented
236// directly.
237//
238// TDocOutput generates the index tables:
239// * classes (THtml invokes TClassDocOutput for each),
240// * inheritance hierarchy,
241// * types and typedefs,
242// * libraries,
243// * the product index, and
244// * the module index (including the links to per-module documentation).
245// It invokes AT&T's GraphViz tool (dot) if available; charts benefit a lot
246// from it.
247//
248// TDocOutput also writes all pages' header and footer, which can be customized
249// by calling THtml::SetHeader(), THtml::SetFooter().
250//______________________________________________________________________________
251
253
254////////////////////////////////////////////////////////////////////////////////
255
256TDocOutput::TDocOutput(THtml& html): fHtml(&html)
257{}
258
259////////////////////////////////////////////////////////////////////////////////
260
262{}
263
264////////////////////////////////////////////////////////////////////////////////
265/// Add a link around str, with title comment.
266/// Update str so it surrounds the link.
267
268void TDocOutput::AddLink(TSubString& str, TString& link, const char* comment)
269{
270 // prepend "./" to allow callers to replace a different relative directory
271 if (ReferenceIsRelative(link) && !link.BeginsWith("./"))
272 link.Prepend("./");
273 link.Prepend("<a href=\"");
274 link += "\"";
275 if (comment && strlen(comment)) {
276 link += " title=\"";
277 TString description(comment);
278 ReplaceSpecialChars(description);
279 description.ReplaceAll("\"", "&quot;");
280 link += description;
281 link += "\"";
282 }
283 link += ">";
284
285 str.String().Insert(str.Start() + str.Length(), "</a>");
286 str.String().Insert(str.Start(), link);
287
288 TString &strString = str.String();
289 TSubString update = strString(str.Start(), str.Length() + link.Length() + 4);
290 str = update;
291}
292
293////////////////////////////////////////////////////////////////////////////////
294/// adjust the path of links for source files, which are in src/, but need
295/// to point to relpath (usually "../"). Simply replaces "=\"./" by "=\"../"
296
297void TDocOutput::AdjustSourcePath(TString& line, const char* relpath /*= "../"*/)
298{
299 TString replWithRelPath("=\"@!@");
300 line.ReplaceAll("=\"../", replWithRelPath + "../" + relpath);
301 line.ReplaceAll("=\"./", replWithRelPath + relpath);
302 line.ReplaceAll("=\"@!@","=\"");
303}
304
305////////////////////////////////////////////////////////////////////////////////
306/// Convert a text file into a html file.
307/// outfilename doesn't have an extension yet; up to us to decide.
308/// We generate HTML, so our extension is ".html".
309/// See THtml::Convert() for the other parameters.
310
311void TDocOutput::Convert(std::istream& in, const char* infilename,
312 const char* outfilename, const char *title,
313 const char *relpath /*= "../"*/, Int_t includeOutput /*=0*/,
314 const char* context /*= ""*/,
315 TGClient* gclient /*= 0*/)
316{
317 TString htmlFilename(outfilename);
318 htmlFilename += ".html";
319
320 std::ofstream out(htmlFilename);
321
322 if (!out.good()) {
323 Error("Convert", "Can't open file '%s' !", htmlFilename.Data());
324 return;
325 }
326
327 // write a HTML header
328 WriteHtmlHeader(out, title, relpath);
329
330 if (context && context[0])
331 out << context << std::endl;
332 else if (title && title[0])
333 out << "<h1 class=\"convert\">" << title << "</h1>" << std::endl;
334
335 Int_t numReuseCanvases = 0;
336 if (includeOutput && !(includeOutput & THtml::kForceOutput)) {
337 void* dirHandle = gSystem->OpenDirectory(gSystem->DirName(htmlFilename));
338 if (dirHandle) {
339 FileStat_t infile_stat;
340 if (!gSystem->GetPathInfo(infilename, infile_stat)) {
341 // can stat.
342 const char* outfile = 0;
343 TString firstCanvasFileBase(gSystem->BaseName(outfilename));
344 firstCanvasFileBase += "_0.png";
345 // first check whether the firstCanvasFile exists:
346 Bool_t haveFirstCanvasFile = false;
347 while ((outfile = gSystem->GetDirEntry(dirHandle))) {
348 if (firstCanvasFileBase == outfile) {
349 haveFirstCanvasFile = true;
350 break;
351 }
352 }
353 gSystem->FreeDirectory(dirHandle);
354
355 FileStat_t outfile_stat;
356 TString firstCanvasFile = outfilename;
357 firstCanvasFile += "_0.png";
358 Int_t maxIdx = -1;
359 if (haveFirstCanvasFile && !gSystem->GetPathInfo(firstCanvasFile, outfile_stat)
360 && outfile_stat.fMtime > infile_stat.fMtime) {
361 // the first canvas file exists and it is newer than the script, so we reuse
362 // the canvas files. We need to know how many there are:
363 dirHandle = gSystem->OpenDirectory(gSystem->DirName(htmlFilename));
364 TString stem(gSystem->BaseName(outfilename));
365 stem += "_";
366 TString dir(gSystem->DirName(htmlFilename));
367 while ((outfile = gSystem->GetDirEntry(dirHandle))) {
368 if (strncmp(outfile, stem, stem.Length()))
369 continue;
370 const char* posext = strrchr(outfile, '.');
371 if (!posext || strcmp(posext, ".png"))
372 continue;
373
374 // extract the mod time of the PNG file
375 if (gSystem->GetPathInfo(dir + "/" + outfile, outfile_stat))
376 // can't stat!
377 continue;
378
379 if (outfile_stat.fMtime > infile_stat.fMtime) {
380 ++numReuseCanvases;
381 // The canvas PNG is newer than the script, so
382 // extract the index of the canvas
383 TString idxStr(outfile + stem.Length());
384 idxStr.Remove(idxStr.Length() - 4);
385 Int_t idx = idxStr.Atoi();
386 if (maxIdx < idx)
387 maxIdx = idx;
388 }
389 }
390 gSystem->FreeDirectory(dirHandle);
391 if (maxIdx + 1 != numReuseCanvases)
392 // bad: the number of canvases to reuse noes not correspond to the highest index we saw.
393 // we will need to regenerate everything.
394 numReuseCanvases = 0;
395 }
396 } // infile can be stat'ed
397 } // can open output directory
398 } // canvases wanted
399
400 if (numReuseCanvases)
401 Printf("Convert: %s (reusing %d saved canvas%s)", htmlFilename.Data(), numReuseCanvases, (numReuseCanvases > 1 ? "es" : ""));
402 else
403 Printf("Convert: %s", htmlFilename.Data());
404
405 UInt_t nCanvases = numReuseCanvases;
406 if (includeOutput) {
407 if (!numReuseCanvases) {
408 // need to run the script
409 if (includeOutput & THtml::kSeparateProcessOutput) {
410 TString baseInFileName = gSystem->BaseName(infilename);
411 TPMERegexp reOutFile(baseInFileName + "_[[:digit:]]+\\.png");
412
413 // remove all files matching what saveScriptOutput.C could produce:
414 void* outdirH = gSystem->OpenDirectory(gSystem->DirName(outfilename));
415 if (outdirH) {
416 // the directory exists.
417 const char* outdirE = 0;
418 while ((outdirE = gSystem->GetDirEntry(outdirH))) {
419 if (reOutFile.Match(outdirE)) {
420 gSystem->Unlink(outdirE);
421 }
422 }
423 gSystem->FreeDirectory(outdirH);
424 }
425
426 gSystem->Exec(TString::Format("ROOT_HIST=0 root.exe -l -q %s $ROOTSYS/etc/html/saveScriptOutput.C\\(\\\"%s\\\",\\\"%s\\\",%d\\)",
427 gROOT->IsBatch() ? "-b" : "",
428 infilename,
429 gSystem->DirName(outfilename),
430 includeOutput & THtml::kCompiledOutput));
431
432 // determine how many output files were created:
433 outdirH = gSystem->OpenDirectory(gSystem->DirName(outfilename));
434 if (outdirH) {
435 // the directory exists.
436 const char* outdirE = 0;
437 while ((outdirE = gSystem->GetDirEntry(outdirH))) {
438 if (reOutFile.Match(outdirE)) {
439 ++nCanvases;
440 }
441 }
442 gSystem->FreeDirectory(outdirH);
443 }
444 } else {
445 // run in this ROOT process
446 TString pwd(gSystem->pwd());
447 gSystem->cd(gSystem->DirName(infilename));
448
449 TList* gClientGetListOfWindows = 0;
450 TObject* gClientGetDefaultRoot = 0;
451 std::set<TObject*> previousWindows;
452 if (gclient) {
453 gROOT->ProcessLine(TString::Format("*((TList**)0x%lx) = ((TGClient*)0x%lx)->GetListOfWindows();",
454 (ULong_t)&gClientGetListOfWindows, (ULong_t)gclient));
455 gROOT->ProcessLine(TString::Format("*((TObject**)0x%lx) = ((TGClient*)0x%lx)->GetDefaultRoot();",
456 (ULong_t)&gClientGetDefaultRoot, (ULong_t)gclient));
457 TObject* win = 0;
458 TIter iWin(gClientGetListOfWindows);
459 while((win = iWin())) {
460 TObject* winGetParent = 0;
461 gROOT->ProcessLine(TString::Format("*((TObject**)0x%lx) = ((TGWindow*)0x%lx)->GetParent();",
462 (ULong_t)&winGetParent, (ULong_t)win));
463 if (winGetParent == gClientGetDefaultRoot)
464 previousWindows.insert(win);
465 }
466 } else {
467 if (gROOT->GetListOfCanvases()->GetSize())
468 previousWindows.insert(gROOT->GetListOfCanvases()->Last());
469 }
470 TIter iTimer(gSystem->GetListOfTimers());
471 std::set<TObject*> timersBefore;
472 TObject* timerOld = 0;
473 while ((timerOld = iTimer()))
474 timersBefore.insert(timerOld);
475
476 TString cmd(".x ");
477 cmd += gSystem->BaseName(infilename);
478 if (includeOutput & THtml::kCompiledOutput)
479 cmd += "+";
480 gInterpreter->SaveContext();
481 gInterpreter->SaveGlobalsContext();
482 Int_t err;
483 gROOT->ProcessLine(cmd, &err);
485 gSystem->cd(pwd);
486
487 if (err == TInterpreter::kNoError) {
488 if (gclient) {
489 TClass* clRootCanvas = TClass::GetClass("TRootCanvas");
490 TClass* clGMainFrame = TClass::GetClass("TGMainFrame");
491 TObject* win = 0;
492 TIter iWin(gClientGetListOfWindows);
493 while((win = iWin())) {
494 TObject* winGetParent = 0;
495 gROOT->ProcessLine(TString::Format("*((TObject**)0x%lx) = ((TGWindow*)0x%lx)->GetParent();",
496 (ULong_t)&winGetParent, (ULong_t)win));
497 Bool_t winIsMapped = kFALSE;
498 if (winGetParent == gClientGetDefaultRoot)
499 gROOT->ProcessLine(TString::Format("*((Bool_t*)0x%lx) = ((TGWindow*)0x%lx)->IsMapped();",
500 (ULong_t)&winIsMapped, (ULong_t)win));
501 if (winIsMapped && previousWindows.find(win) == previousWindows.end()
502 && win->InheritsFrom(clGMainFrame)) {
503 gROOT->ProcessLine(TString::Format("((TGWindow*)0x%lx)->MapRaised();", (ULong_t)win));
504 Bool_t isRootCanvas = win->InheritsFrom(clRootCanvas);
505 Bool_t hasEditor = false;
506 if (isRootCanvas) {
507 gROOT->ProcessLine(TString::Format("*((Bool_t*)0x%lx) = ((TRootCanvas*)0x%lx)->HasEditor();",
508 (ULong_t)&hasEditor, (ULong_t)win));
509 }
510 if (isRootCanvas && !hasEditor) {
511 TVirtualPad* pad = 0;
512 gROOT->ProcessLine(TString::Format("*((TVirtualPad**)0x%lx) = ((TRootCanvas*)0x%lx)->Canvas();",
513 (ULong_t)&pad, (ULong_t)win));
514 if (!pad->HasViewer3D() || pad->GetViewer3D()->InheritsFrom("TViewer3DPad")) {
515 pad->SaveAs(TString::Format("%s_%d.png", outfilename, nCanvases++));
516 }
517 } else
518 gROOT->ProcessLine(TString::Format("((TGWindow*)0x%lx)->SaveAs(\"%s_%d.png\");",
519 (ULong_t)win, outfilename, nCanvases++));
520 }
521 }
522 } else {
523 // no gClient
524 TVirtualPad* pad = 0;
525 TVirtualPad* last = 0;
526 if (!previousWindows.empty())
527 last = (TVirtualPad*) *previousWindows.begin();
528 TIter iCanvas(gROOT->GetListOfCanvases());
529 while ((pad = (TVirtualPad*) iCanvas())) {
530 if (last) {
531 if (last == pad) last = 0;
532 continue;
533 }
534 pad->SaveAs(TString::Format("%s_%d.png", outfilename, nCanvases++));
535 }
536 }
537 gInterpreter->Reset();
538 gInterpreter->ResetGlobals();
539 TIter iTimerRemove(gSystem->GetListOfTimers());
540 TTimer* timer = 0;
541 while ((timer = (TTimer*) iTimerRemove()))
542 if (timersBefore.find(timer) == timersBefore.end())
543 gSystem->RemoveTimer(timer);
544 }
545 } // run script in this ROOT process
546 }
547 out << "<table><tr><td style=\"vertical-align:top;padding-right:2em;\">" << std::endl;
548 }
549 out << "<div class=\"listing\"><pre class=\"listing\">" << std::endl;
550
551 TDocParser parser(*this);
552 parser.Convert(out, in, relpath, (includeOutput) /* determines whether it's code or not */,
553 kFALSE /*interpretDirectives*/);
554
555 out << "</pre></div>" << std::endl;
556
557 WriteLineNumbers(out, parser.GetLineNumber(), gSystem->BaseName(infilename));
558
559 if (includeOutput) {
560 out << "</td><td style=\"vertical-align:top;\">" << std::endl;
561 out << "<table>" << std::endl;
562 for (UInt_t i = 0; i < nCanvases; ++i) {
563 TString pngname = TString::Format("%s_%d.png", gSystem->BaseName(outfilename), i);
564 out << "<tr><td><a href=\"" << pngname << "\">" << std::endl
565 << "<img src=\"" << pngname << "\" id=\"canv" << i << "\" alt=\"thumb\" style=\"border:none;width:22em;\" "
566 "onmouseover=\"javascript:canv" << i << ".style.width='auto';\" />" << std::endl
567 << "</a></td></tr>" << std::endl;
568 }
569 out << "</table>" << std::endl;
570 out << "</td></tr></table>" << std::endl;
571 }
572
573 // write a HTML footer
574 WriteHtmlFooter(out, relpath);
575}
576
577////////////////////////////////////////////////////////////////////////////////
578/// Copy file to HTML directory
579///
580///
581/// Input: sourceName - source file name (fully qualified i.e. file system path)
582/// destName - optional destination name, if not
583/// specified it would be the same
584/// as the source file name
585///
586/// Output: TRUE if file is successfully copied, or
587/// FALSE if it's not
588///
589///
590/// NOTE: The destination directory is always fHtml->GetOutputDir()
591///
592
593Bool_t TDocOutput::CopyHtmlFile(const char *sourceName, const char *destName)
594{
595 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
596
597 TString sourceFile(sourceName);
598
599 if (!sourceFile.Length()) {
600 Error("Copy", "Can't copy file '%s' to '%s' directory - source file name invalid!", sourceName,
601 fHtml->GetOutputDir().Data());
602 return kFALSE;
603 }
604
605 // destination file name
606 TString destFile;
607 if (!destName || !*destName)
608 destFile = gSystem->BaseName(sourceFile);
609 else
610 destFile = gSystem->BaseName(destName);
611
613
614 // Get info about a file
615 Long64_t size;
616 Long_t id, flags, sModtime, dModtime;
617 sModtime = 0;
618 dModtime = 0;
619 if (gSystem->GetPathInfo(sourceFile, &id, &size, &flags, &sModtime)
620 || gSystem->GetPathInfo(destFile, &id, &size, &flags, &dModtime)
621 || sModtime > dModtime)
622 if (gSystem->CopyFile(sourceFile, destFile, kTRUE) < 0) {
623 Error("Copy", "Can't copy file '%s' to '%s'!",
624 sourceFile.Data(), destFile.Data());
625 return kFALSE;
626 }
627
628 return kTRUE;
629}
630
631
632
633////////////////////////////////////////////////////////////////////////////////
634/// Create a hierarchical class list
635/// The algorithm descends from the base classes and branches into
636/// all derived classes. Mixing classes are displayed several times.
637///
638///
639
641{
642 // if (CreateHierarchyDot()) return;
643
644 TString filename("ClassHierarchy.html");
646
647 // open out file
648 std::ofstream out(filename);
649
650 if (!out.good()) {
651 Error("CreateHierarchy", "Can't open file '%s' !", filename.Data());
652 return;
653 }
654
655 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
656
657 // write out header
658 WriteHtmlHeader(out, "Class Hierarchy");
659
660 WriteTopLinks(out, 0);
661
662 out << "<h1>Class Hierarchy</h1>" << std::endl;
663
664
665 // loop on all classes
666 TClassDocInfo* cdi = 0;
667 TIter iClass(fHtml->GetListOfClasses());
668 while ((cdi = (TClassDocInfo*)iClass())) {
669 if (!cdi->HaveSource())
670 continue;
671
672 // get class
673 TDictionary *dictPtr = cdi->GetClass();
674 TClass *basePtr = dynamic_cast<TClass*>(dictPtr);
675 if (basePtr == 0) {
676 if (!dictPtr)
677 Warning("THtml::CreateHierarchy", "skipping class %s\n", cdi->GetName());
678 continue;
679 }
680
681 TClassDocOutput cdo(*fHtml, basePtr, 0);
682 cdo.CreateClassHierarchy(out, cdi->GetHtmlFileName());
683 }
684
685 // write out footer
686 WriteHtmlFooter(out);
687}
688
689////////////////////////////////////////////////////////////////////////////////
690/// Create index of all classes
691///
692
694{
695 // create CSS file, we need it
697
698 TString filename("ClassIndex.html");
700
701 // open indexFile file
702 std::ofstream indexFile(filename.Data());
703
704 if (!indexFile.good()) {
705 Error("CreateClassIndex", "Can't open file '%s' !", filename.Data());
706 return;
707 }
708
709 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
710
711 // write indexFile header
712 WriteHtmlHeader(indexFile, "Class Index");
713
714 WriteTopLinks(indexFile, 0);
715
716 indexFile << "<h1>Class Index</h1>" << std::endl;
717
718 WriteModuleLinks(indexFile);
719
720 std::vector<std::string> indexChars;
721 if (fHtml->GetListOfClasses()->GetSize() > 10) {
722 std::vector<std::string> classNames;
723 {
724 TIter iClass(fHtml->GetListOfClasses());
725 TClassDocInfo* cdi = 0;
726 while ((cdi = (TClassDocInfo*)iClass()))
727 if (cdi->IsSelected() && cdi->HaveSource())
728 classNames.push_back(cdi->GetName());
729 }
730
731 if (classNames.size() > 10) {
732 indexFile << "<div id=\"indxShortX\"><h4>Jump to</h4>" << std::endl;
733 // find index chars
734 GetIndexChars(classNames, 50 /*sections*/, indexChars);
735 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
736 indexFile << "<a href=\"#idx" << iIdxEntry << "\">";
737 ReplaceSpecialChars(indexFile, indexChars[iIdxEntry].c_str());
738 indexFile << "</a>" << std::endl;
739 }
740 indexFile << "</div><br />" << std::endl;
741 }
742 }
743
744 indexFile << "<ul id=\"indx\">" << std::endl;
745
746 // loop on all classes
747 UInt_t currentIndexEntry = 0;
748 TIter iClass(fHtml->GetListOfClasses());
749 TClassDocInfo* cdi = 0;
750 Int_t i = 0;
751 while ((cdi = (TClassDocInfo*)iClass())) {
752 if (!cdi->IsSelected() || !cdi->HaveSource())
753 continue;
754
755 // get class
756 TDictionary *currentDict = cdi->GetClass();
757 TClass* currentClass = dynamic_cast<TClass*>(currentDict);
758 if (!currentClass) {
759 if (!currentDict)
760 Warning("THtml::CreateClassIndex", "skipping class %s\n", cdi->GetName());
761 continue;
762 }
763
764 indexFile << "<li class=\"idxl" << (i++)%2 << "\">";
765 if (currentIndexEntry < indexChars.size()
766 && !strncmp(indexChars[currentIndexEntry].c_str(), cdi->GetName(),
767 indexChars[currentIndexEntry].length()))
768 indexFile << "<a name=\"idx" << currentIndexEntry++ << "\"></a>";
769
770 TString htmlFile(cdi->GetHtmlFileName());
771 if (htmlFile.Length()) {
772 indexFile << "<a href=\"";
773 indexFile << htmlFile;
774 indexFile << "\"><span class=\"typename\">";
775 ReplaceSpecialChars(indexFile, cdi->GetName());
776 indexFile << "</span></a> ";
777 } else {
778 indexFile << "<span class=\"typename\">";
779 ReplaceSpecialChars(indexFile, cdi->GetName());
780 indexFile << "</span> ";
781 }
782
783 // write title == short doc
784 ReplaceSpecialChars(indexFile, currentClass->GetTitle());
785 indexFile << "</li>" << std::endl;
786 }
787
788 indexFile << "</ul>" << std::endl;
789
790 // write indexFile footer
791 WriteHtmlFooter(indexFile);
792}
793
794
795////////////////////////////////////////////////////////////////////////////////
796/// Create the class index for each module, picking up documentation from the
797/// module's TModuleDocInfo::GetInputPath() plus the (possibly relative)
798/// THtml::GetModuleDocPath(). Also creates the library dependency plot if dot
799/// exists, see THtml::HaveDot().
800
802{
803 const char* title = "LibraryDependencies";
804 TString dotfilename(title);
805 gSystem->PrependPathName(fHtml->GetOutputDir(), dotfilename);
806
807 std::ofstream libDepDotFile(dotfilename + ".dot");
808 libDepDotFile << "digraph G {" << std::endl
809 << "ratio=compress;" << std::endl
810 << "node [fontsize=22,labeldistance=0.1];" << std::endl
811 << "edge [len=0.01];" << std::endl
812 << "fontsize=22;" << std::endl
813 << "size=\"16,16\";" << std::endl
814 << "overlap=false;" << std::endl
815 << "splines=true;" << std::endl
816 << "K=0.1;" << std::endl;
817
818 TModuleDocInfo* module = 0;
819 TIter iterModule(fHtml->GetListOfModules());
820
821 std::stringstream sstrCluster;
822 std::stringstream sstrDeps;
823 while ((module = (TModuleDocInfo*)iterModule())) {
824 if (!module->IsSelected())
825 continue;
826
827 std::vector<std::string> indexChars;
828 TString filename(module->GetName());
829 filename.ToUpper();
830 filename.ReplaceAll("/","_");
831 filename += "_Index.html";
833 std::ofstream outputFile(filename.Data());
834 if (!outputFile.good()) {
835 Error("CreateModuleIndex", "Can't open file '%s' !", filename.Data());
836 continue;
837 }
838 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
839
840 TString htmltitle("Index of ");
841 TString moduletitle(module->GetName());
842 moduletitle.ToUpper();
843 htmltitle += moduletitle;
844 WriteHtmlHeader(outputFile, htmltitle);
845
846 WriteTopLinks(outputFile, module);
847
848 outputFile << "<h2>" << htmltitle << "</h2>" << std::endl;
849
850 // Module doc
851 if (GetHtml()->GetModuleDocPath().Length()) {
852 TString outdir(module->GetName());
853 gSystem->PrependPathName(GetHtml()->GetOutputDir(), outdir);
854
855 TString moduleDocDir;
856 GetHtml()->GetPathDefinition().GetDocDir(module->GetName(), moduleDocDir);
857 ProcessDocInDir(outputFile, moduleDocDir, outdir, module->GetName());
858 }
859
860 WriteModuleLinks(outputFile, module);
861
862 std::list<std::string> classNames;
863 {
864 TIter iClass(module->GetClasses());
865 TClassDocInfo* cdi = 0;
866 while ((cdi = (TClassDocInfo*) iClass())) {
867 if (!cdi->IsSelected() || !cdi->HaveSource())
868 continue;
869 classNames.push_back(cdi->GetName());
870
871 if (classNames.size() > 1) continue;
872
873 TClass* cdiClass = dynamic_cast<TClass*>(cdi->GetClass());
874 if (!cdiClass)
875 continue;
876
877 TString libs(cdiClass->GetSharedLibs());
878 Ssiz_t posDepLibs = libs.Index(' ');
879 TString thisLib(libs);
880 if (posDepLibs != kNPOS)
881 thisLib.Remove(posDepLibs, thisLib.Length());
882
883 {
884 Ssiz_t posExt = thisLib.First('.');
885 if (posExt != kNPOS)
886 thisLib.Remove(posExt, thisLib.Length());
887 }
888
889 if (!thisLib.Length())
890 continue;
891
892 // allocate entry, even if no dependencies
893 TLibraryDocInfo *libdeps =
895 if (!libdeps) {
896 libdeps = new TLibraryDocInfo(thisLib);
897 fHtml->GetLibraryDependencies()->Add(libdeps);
898 }
899 libdeps->AddModule(module->GetName());
900 if (posDepLibs != kNPOS) {
901 std::string lib;
902 for(Ssiz_t pos = posDepLibs + 1; libs[pos]; ++pos) {
903 if (libs[pos] == ' ') {
904 if (thisLib.Length() && lib.length()) {
905 size_t posExt = lib.find('.');
906 if (posExt != std::string::npos)
907 lib.erase(posExt);
908 libdeps->AddDependency(lib);
909 }
910 lib.erase();
911 } else
912 lib += libs[pos];
913 }
914 if (lib.length() && thisLib.Length()) {
915 size_t posExt = lib.find('.');
916 if (posExt != std::string::npos)
917 lib.erase(posExt);
918 libdeps->AddDependency(lib);
919 }
920 } // if dependencies
921 } // while next class in module
922 } // just a scope block
923
924 TIter iClass(module->GetClasses());
925 TClassDocInfo* cdi = 0;
926 UInt_t count = 0;
927 UInt_t currentIndexEntry = 0;
928 while ((cdi = (TClassDocInfo*) iClass())) {
929 if (!cdi->IsSelected() || !cdi->HaveSource())
930 continue;
931
932 TDictionary *classPtr = cdi->GetClass();
933 if (!classPtr) {
934 Error("CreateModuleIndex", "Unknown class '%s' !", cdi->GetName());
935 continue;
936 }
937
938 if (!count) {
939 outputFile << "<h2>Class Index</h2>" << std::endl;
940
941 if (classNames.size() > 10) {
942 outputFile << "<div id=\"indxShortX\"><h4>Jump to</h4>" << std::endl;
943 UInt_t numSections = classNames.size() / 10;
944 if (numSections < 10) numSections = 10;
945 if (numSections > 50) numSections = 50;
946 // find index chars
947 GetIndexChars(classNames, numSections, indexChars);
948 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
949 outputFile << "<a href=\"#idx" << iIdxEntry << "\">";
950 ReplaceSpecialChars(outputFile, indexChars[iIdxEntry].c_str());
951 outputFile << "</a>" << std::endl;
952 }
953 outputFile << "</div><br />" << std::endl;
954 }
955
956 outputFile << "<ul id=\"indx\">" << std::endl;
957 }
958
959 // write a classname to an index file
960 outputFile << "<li class=\"idxl" << (count++)%2 << "\">";
961 if (currentIndexEntry < indexChars.size()
962 && !strncmp(indexChars[currentIndexEntry].c_str(), cdi->GetName(),
963 indexChars[currentIndexEntry].length()))
964 outputFile << "<a name=\"idx" << currentIndexEntry++ << "\"></a>";
965
966 TString htmlFile(cdi->GetHtmlFileName());
967 if (htmlFile.Length()) {
968 outputFile << "<a href=\"";
969 outputFile << htmlFile;
970 outputFile << "\"><span class=\"typename\">";
971 ReplaceSpecialChars(outputFile, classPtr->GetName());
972 outputFile << "</span></a> ";
973 } else {
974 outputFile << "<span class=\"typename\">";
975 ReplaceSpecialChars(outputFile, classPtr->GetName());
976 outputFile << "</span> ";
977 }
978
979 // write title
980 ReplaceSpecialChars(outputFile, classPtr->GetTitle());
981 outputFile << "</li>" << std::endl;
982 }
983
984
985 if (count)
986 outputFile << "</ul>" << std::endl;
987
988 // write outputFile footer
989 WriteHtmlFooter(outputFile);
990 } // while next module
991
992 // libCint is missing as we don't have class doc for it
993 // We need it for dependencies nevertheless, so add it by hand.
994 /*
995 sstrCluster << "subgraph clusterlibCint {" << std::endl
996 << "style=filled;" << std::endl
997 << "color=lightgray;" << std::endl
998 << "label=\"libCint\";" << std::endl
999 << "\"CINT\" [style=filled,color=white,fontsize=10]" << std::endl
1000 << "}" << std::endl;
1001 */
1002
1003 // simplify the library dependencies, by removing direct links
1004 // that are equivalent to indirect ones, e.g. instead of having both
1005 // A->C, A->B->C, keep only A->B->C.
1006
1008 TLibraryDocInfo* libinfo = 0;
1009 while ((libinfo = (TLibraryDocInfo*)iLib())) {
1010 if (!libinfo->GetName() || !libinfo->GetName()[0]) continue;
1011
1012 std::set<std::string>& deps = libinfo->GetDependencies();
1013 for (std::set<std::string>::iterator iDep = deps.begin();
1014 iDep != deps.end(); ) {
1015 Bool_t already_indirect = kFALSE;
1016 for (std::set<std::string>::const_iterator iDep2 = deps.begin();
1017 !already_indirect && iDep2 != deps.end(); ++iDep2) {
1018 if (iDep == iDep2) continue;
1019 TLibraryDocInfo* libinfo2 = (TLibraryDocInfo*)
1020 fHtml->GetLibraryDependencies()->FindObject(iDep2->c_str());
1021 if (!libinfo2) continue;
1022 const std::set<std::string>& deps2 = libinfo2->GetDependencies();
1023 already_indirect |= deps2.find(*iDep) != deps2.end();
1024 }
1025 if (already_indirect) {
1026 std::set<std::string>::iterator iRemove = iDep;
1027 // Advance the iterator before erasing the element which invalidates the iterator.
1028 ++iDep;
1029 deps.erase(iRemove);
1030 } else {
1031 ++iDep;
1032 }
1033 } // for library dependencies of module in library
1034 } // for libraries
1035
1036 iLib.Reset();
1037 while ((libinfo = (TLibraryDocInfo*)iLib())) {
1038 if (!libinfo->GetName() || !libinfo->GetName()[0]) continue;
1039
1040 const std::set<std::string>& modules = libinfo->GetModules();
1041 if (modules.size() > 1) {
1042 sstrCluster << "subgraph cluster" << libinfo->GetName() << " {" << std::endl
1043 << "style=filled;" << std::endl
1044 << "color=lightgray;" << std::endl
1045 << "label=\"";
1046 if (!strcmp(libinfo->GetName(), "libCore"))
1047 sstrCluster << "Everything depends on ";
1048 sstrCluster << libinfo->GetName() << "\";" << std::endl;
1049
1050 for (std::set<std::string>::const_iterator iModule = modules.begin();
1051 iModule != modules.end(); ++iModule) {
1052 TString modURL(*iModule);
1053 modURL.ReplaceAll("/", "_");
1054 modURL.ToUpper();
1055 sstrCluster << "\"" << *iModule << "\" [style=filled,color=white,URL=\""
1056 << modURL << "_Index.html\"];" << std::endl;
1057 }
1058 sstrCluster << std::endl
1059 << "}" << std::endl;
1060 } else {
1061 // only one module
1062 TString modURL(*modules.begin());
1063 modURL.ReplaceAll("/", "_");
1064 modURL.ToUpper();
1065 sstrCluster << "\"" << *modules.begin()
1066 << "\" [label=\"" << libinfo->GetName()
1067 << "\",style=filled,color=lightgray,shape=box,URL=\""
1068 << modURL << "_Index.html\"];" << std::endl;
1069 }
1070
1071 // GetSharedLib doesn't mention libCore or libCint; add them by hand
1072 /*
1073 if (iLibDep->first != "libCore")
1074 sstrDeps << "\"" << iModule->first << "\" -> \"BASE\" [lhead=clusterlibCore];" << std::endl;
1075 sstrDeps << "\"" << iModule->first << "\" -> \"CINT\" [lhead=clusterlibCint];" << std::endl;
1076 */
1077
1078 const std::string& mod = *(modules.begin());
1079 const std::set<std::string>& deps = libinfo->GetDependencies();
1080 for (std::set<std::string>::const_iterator iDep = deps.begin();
1081 iDep != deps.end(); ++iDep) {
1082 // cannot create dependency on iDep directly, use its first module instead.
1083 TLibraryDocInfo* depLibInfo = (TLibraryDocInfo*)
1084 fHtml->GetLibraryDependencies()->FindObject(iDep->c_str());
1085 if (!depLibInfo || depLibInfo->GetModules().empty())
1086 continue; // ouch!
1087
1088 const std::string& moddep = *(depLibInfo->GetModules().begin());
1089 sstrDeps << "\"" << mod << "\" -> \"" << moddep << "\";" << std::endl;
1090 }
1091 // make sure libCore ends up at the bottom
1092 sstrDeps << "\"" << mod << "\" -> \"CONT\" [style=invis];" << std::endl;
1093 } // for libs
1094
1095 libDepDotFile << sstrCluster.str() << std::endl
1096 << sstrDeps.str();
1097 libDepDotFile << "}" << std::endl;
1098 libDepDotFile.close();
1099
1100 std::ofstream out(dotfilename + ".html");
1101 if (!out.good()) {
1102 Error("CreateModuleIndex", "Can't open file '%s.html' !",
1103 dotfilename.Data());
1104 return;
1105 }
1106
1107 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), (dotfilename + ".html").Data());
1108 // write out header
1109 WriteHtmlHeader(out, "Library Dependencies");
1110
1111 WriteTopLinks(out, 0);
1112
1113 out << "<h1>Library Dependencies</h1>" << std::endl;
1114
1115 RunDot(dotfilename, &out, kFdp);
1116
1117 out << "<img alt=\"Library Dependencies\" class=\"classcharts\" usemap=\"#Map" << title << "\" src=\"" << title << ".png\"/>" << std::endl;
1118
1119 // write out footer
1120 WriteHtmlFooter(out);
1121}
1122
1123////////////////////////////////////////////////////////////////////////////////
1124/// Fetch documentation from THtml::GetProductDocDir() and put it into the
1125/// product index page.
1126
1128{
1129 //TString outFile(GetHtml()->GetProductName());
1130 //outFile += ".html";
1131 TString outFile("index.html");
1132 gSystem->PrependPathName(GetHtml()->GetOutputDir(), outFile);
1133 std::ofstream out(outFile);
1134
1135 if (!out.good()) {
1136 Error("CreateProductIndex", "Can't open file '%s' !", outFile.Data());
1137 return;
1138 }
1139
1140 Printf(fHtml->GetCounterFormat(), "", "", outFile.Data());
1141
1142 WriteHtmlHeader(out, GetHtml()->GetProductName() + " Reference Guide");
1143
1144 WriteTopLinks(out, 0);
1145
1146 out << "<h1>" << GetHtml()->GetProductName() + " Reference Guide</h1>" << std::endl;
1147
1148 TString prodDoc;
1149 if (GetHtml()->GetPathDefinition().GetDocDir("", prodDoc))
1150 ProcessDocInDir(out, prodDoc, GetHtml()->GetOutputDir(), "./");
1151
1152 WriteModuleLinks(out);
1153
1154 out << "<h2>Chapters</h2>" << std::endl
1155 << "<h3><a href=\"./ClassIndex.html\">Class Index</a></h3>" << std::endl
1156 << "<p>A complete list of all classes defined in " << GetHtml()->GetProductName() << "</p>" << std::endl
1157 << "<h3><a href=\"./ClassHierarchy.html\">Class Hierarchy</a></h3>" << std::endl
1158 << "<p>A hierarchy graph of all classes, showing each class's base and derived classes</p>" << std::endl
1159 << "<h3><a href=\"./ListOfTypes.html\">Type Index</a></h3>" << std::endl
1160 << "<p>A complete list of all types</p>" << std::endl
1161 << "<h3><a href=\"./LibraryDependencies.html\">Library Dependency</a></h3>" << std::endl
1162 << "<p>A diagram showing all of " << GetHtml()->GetProductName() << "'s libraries and their dependencies</p>" << std::endl;
1163
1164 WriteHtmlFooter(out);
1165}
1166
1167////////////////////////////////////////////////////////////////////////////////
1168/// Create a forwarding page for each typedef pointing to a class.
1169
1171{
1172 TDocParser parser(*this);
1173
1174 TIter iClass(GetHtml()->GetListOfClasses());
1175 TClassDocInfo* cdi = 0;
1176 while ((cdi = (TClassDocInfo*) iClass())) {
1177 if (cdi->GetListOfTypedefs().IsEmpty())
1178 continue;
1179 TIter iTypedefs(&cdi->GetListOfTypedefs());
1180 TDataType* dt = 0;
1181 while ((dt = (TDataType*) iTypedefs())) {
1182 if (gDebug > 0)
1183 Info("CreateClassTypeDefs", "Creating typedef %s to class %s",
1184 dt->GetName(), cdi->GetName());
1185 // create a filename
1186 TString filename(dt->GetName());
1187 NameSpace2FileName(filename);
1188
1190
1191 filename += ".html";
1192
1193 // open class file
1194 std::ofstream outfile(filename);
1195
1196 if (!outfile.good()) {
1197 Error("CreateClassTypeDefs", "Can't open file '%s' !", filename.Data());
1198 continue;
1199 }
1200
1201 WriteHtmlHeader(outfile, dt->GetName());
1202
1203 outfile << "<a name=\"TopOfPage\"></a>" << std::endl;
1204
1205 TString dtName(dt->GetName());
1206 ReplaceSpecialChars(dtName);
1207 TString sTitle("typedef ");
1208 sTitle += dtName;
1209
1210 TClass* cls = dynamic_cast<TClass*>(cdi->GetClass());
1211 if (cls) {
1212 // show box with lib, include
1213 // needs to go first to allow title on the left
1214 TString sInclude;
1215 TString sLib;
1216 const char* lib=cls->GetSharedLibs();
1217 GetHtml()->GetPathDefinition().GetIncludeAs(cls, sInclude);
1218 if (lib) {
1219 char* libDup=StrDup(lib);
1220 char* libDupSpace=strchr(libDup,' ');
1221 if (libDupSpace) *libDupSpace = 0;
1222 char* libDupEnd=libDup+strlen(libDup);
1223 while (libDupEnd!=libDup)
1224 if (*(--libDupEnd)=='.') {
1225 *libDupEnd=0;
1226 break;
1227 }
1228 sLib = libDup;
1229 delete[] libDup;
1230 }
1231 outfile << "<script type=\"text/javascript\">WriteFollowPageBox('"
1232 << sTitle << "','" << sLib << "','" << sInclude << "');</script>" << std::endl;
1233 }
1234
1235 TString modulename;
1236 fHtml->GetModuleNameForClass(modulename, cls);
1237 TModuleDocInfo* module = (TModuleDocInfo*) fHtml->GetListOfModules()->FindObject(modulename);
1238 WriteTopLinks(outfile, module, dt->GetName());
1239
1240 outfile << "<div class=\"dropshadow\"><div class=\"withshadow\">";
1241 outfile << "<h1>" << sTitle << "</h1>" << std::endl
1242 << "<div class=\"classdescr\">" << std::endl;
1243
1244 outfile << dtName << " is a typedef to ";
1245 std::string shortClsName(fHtml->ShortType(cdi->GetName()));
1246 parser.DecorateKeywords(outfile, shortClsName.c_str());
1247 outfile << std::endl
1248 << "</div>" << std::endl
1249 << "</div></div><div style=\"clear:both;\"></div>" << std::endl;
1250
1251 // the typedef isn't a data member, but the CSS is applicable nevertheless
1252 outfile << std::endl << "<div id=\"datamembers\">" << std::endl
1253 << "<table class=\"data\" cellspacing=\"0\">" << std::endl;
1254 outfile << "<tr class=\"data";
1255 outfile << "\"><td class=\"datatype\">typedef ";
1256 parser.DecorateKeywords(outfile, dt->GetFullTypeName());
1257 outfile << "</td><td class=\"dataname\">";
1258 ReplaceSpecialChars(outfile, dt->GetName());
1259 if (dt->GetTitle() && dt->GetTitle()[0]) {
1260 outfile << "</td><td class=\"datadesc\">";
1261 ReplaceSpecialChars(outfile, dt->GetTitle());
1262 } else outfile << "</td><td>";
1263 outfile << "</td></tr>" << std::endl
1264 << "</table></div>" << std::endl;
1265
1266 // write footer
1267 WriteHtmlFooter(outfile);
1268
1269 }
1270 }
1271}
1272
1273////////////////////////////////////////////////////////////////////////////////
1274/// Create index of all data types
1275
1277{
1278 // open file
1279 TString outFile("ListOfTypes.html");
1281 std::ofstream typesList(outFile);
1282
1283 if (!typesList.good()) {
1284 Error("CreateTypeIndex", "Can't open file '%s' !", outFile.Data());
1285 return;
1286 }
1287
1288 Printf(fHtml->GetCounterFormat(), "", "", outFile.Data());
1289
1290 // write typesList header
1291 WriteHtmlHeader(typesList, "List of data types");
1292 typesList << "<h2> List of data types </h2>" << std::endl;
1293
1294 typesList << "<dl><dd>" << std::endl;
1295
1296 // make loop on data types
1297 std::vector<std::string> typeNames(gROOT->GetListOfTypes()->GetSize());
1298
1299 {
1300 TDataType *type;
1301 TIter nextType(gROOT->GetListOfTypes());
1302 size_t tnIdx = 0;
1303
1304 while ((type = (TDataType *) nextType()))
1305 // no templates ('<' and '>'), no idea why the '(' is in here...
1306 if (*type->GetTitle() && !strchr(type->GetName(), '(')
1307 && !( strchr(type->GetName(), '<') && strchr(type->GetName(),'>'))
1308 && type->GetName())
1309 typeNames[tnIdx++] = type->GetName();
1310 typeNames.resize(tnIdx);
1311 }
1312
1313 sort_strlist_stricmp(typeNames);
1314
1315 std::vector<std::string> indexChars;
1316 if (typeNames.size() > 10) {
1317 typesList << "<div id=\"indxShortX\"><h4>Jump to</h4>" << std::endl;
1318 // find index chars
1319 GetIndexChars(typeNames, 10 /*sections*/, indexChars);
1320 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
1321 typesList << "<a href=\"#idx" << iIdxEntry << "\">";
1322 ReplaceSpecialChars(typesList, indexChars[iIdxEntry].c_str());
1323 typesList << "</a>" << std::endl;
1324 }
1325 typesList << "</div><br />" << std::endl;
1326 }
1327
1328 typesList << "<ul id=\"indx\">" << std::endl;
1329
1330 int idx = 0;
1331 UInt_t currentIndexEntry = 0;
1332
1333 for (std::vector<std::string>::iterator iTypeName = typeNames.begin();
1334 iTypeName != typeNames.end(); ++iTypeName) {
1335 TDataType* type = gROOT->GetType(iTypeName->c_str(), kFALSE);
1336 typesList << "<li class=\"idxl" << idx%2 << "\">";
1337 if (currentIndexEntry < indexChars.size()
1338 && !strncmp(indexChars[currentIndexEntry].c_str(), iTypeName->c_str(),
1339 indexChars[currentIndexEntry].length()))
1340 typesList << "<a name=\"idx" << currentIndexEntry++ << "\"></a>" << std::endl;
1341 typesList << "<a name=\"";
1342 ReplaceSpecialChars(typesList, iTypeName->c_str());
1343 typesList << "\"><span class=\"typename\">";
1344 ReplaceSpecialChars(typesList, iTypeName->c_str());
1345 typesList << "</span></a> ";
1346 ReplaceSpecialChars(typesList, type->GetTitle());
1347 typesList << "</li>" << std::endl;
1348 ++idx;
1349 }
1350 typesList << "</ul>" << std::endl;
1351
1352 // write typesList footer
1353 WriteHtmlFooter(typesList);
1354
1355 // close file
1356 typesList.close();
1357
1358}
1359
1360
1361////////////////////////////////////////////////////////////////////////////////
1362/// Add some colors etc to a source entity, contained in str.
1363/// The type of what's contained in str is given by type.
1364/// It's called e.g. by TDocParser::BeautifyLine().
1365/// This function should assume that only str.Begin() is valid.
1366/// When inserting into str.String(), str.Begin() must be updated.
1367
1369{
1370 Ssiz_t originalLen = str.Length();
1371
1372 switch (type) {
1373 case TDocParser::kCode: break;
1375 str.Insert(pos, "<span class=\"comment\">");
1376 break;
1378 break;
1380 str.Insert(pos, "<span class=\"string\">");
1381 break;
1383 str.Insert(pos, "<span class=\"keyword\">");
1384 break;
1385 case TDocParser::kCPP:
1386 str.Insert(pos, "<span class=\"cpp\">");
1387 break;
1389 str.Insert(pos, "<pre>");
1390 break;
1391 default:
1392 Error("DecorateEntityBegin", "Unhandled / invalid entity type %d!", (Int_t)type);
1393 return;
1394 }
1395
1396 Ssiz_t addedLen = str.Length() - originalLen;
1397 pos += addedLen;
1398}
1399
1400////////////////////////////////////////////////////////////////////////////////
1401/// Add some colors etc to a source entity, contained in str.
1402/// The type of what's contained in str is given by type.
1403/// It's called e.g. by TDocParser::BeautifyLine().
1404/// This function should assume that only str."End()"
1405/// (i.e. str.Begin()+str.Length()) is valid.
1406/// When inserting into str.String(), str.Length() must be updated.
1407
1409{
1410 Ssiz_t originalLen = str.Length();
1411
1412 switch (type) {
1413 case TDocParser::kCode: break;
1415 str.Insert(pos, "</span>");
1416 break;
1418 break;
1420 str.Insert(pos, "</span>");
1421 break;
1423 str.Insert(pos, "</span>");
1424 break;
1425 case TDocParser::kCPP:
1426 str.Insert(pos, "</span>");
1427 break;
1429 str.Insert(pos, "</pre>");
1430 break;
1431 default:
1432 Error("DecorateEntityBegin", "Unhandled / invalid entity type %d!", (Int_t)type);
1433 return;
1434 }
1435 Ssiz_t addedLen = str.Length() - originalLen;
1436 pos += addedLen;
1437}
1438
1439////////////////////////////////////////////////////////////////////////////////
1440/// Special author treatment; called when TDocParser::fSourceInfo[kInfoAuthor] is set.
1441/// Modifies the author(s) description, which is a comma separated list of tokens
1442/// either in the format
1443/// (i) "FirstName LastName " or
1444/// (ii) "FirstName LastName <link> more stuff"
1445/// The first one generates an XWho link (CERN compatible),
1446/// the second a http link (WORLD compatible), <link> being e.g.
1447/// <mailto:user@host.bla> or <http://www.host.bla/page>.
1448
1450{
1451 TString original(authors);
1452 authors = "";
1453
1454 TString author;
1455 Ssiz_t pos = 0;
1456 Bool_t firstAuthor = kTRUE;
1457 while (original.Tokenize(author, pos, ",")) {
1458 author.Strip(TString::kBoth);
1459
1460 if (!firstAuthor)
1461 authors += ", ";
1462 firstAuthor = kFALSE;
1463
1464 // do we have a link for the current name?
1465 Ssiz_t cLink = author.First('<'); // look for link start tag
1466 if (cLink != kNPOS) {
1467 // split NAME <LINK> POST
1468 // into <a href="LINK">NAME</a> POST
1469 Ssiz_t endLink = author.Index(">", cLink + 1);
1470 if(endLink == kNPOS)
1471 endLink = author.Length();
1472 authors += "<a href=\"";
1473 authors += author(cLink + 1, endLink - (cLink + 1));
1474 authors += "\">";
1475 authors += author(0, cLink);
1476 authors += "</a>";
1477 if (endLink != author.Length())
1478 authors += author(endLink + 1, author.Length());
1479 } else {
1480 authors += "<a href=\"";
1481 authors += fHtml->GetXwho();
1482
1483 // separate Firstname Middlename Lastname by '+'
1484 TString namePart;
1485 Ssiz_t posNamePart = 0;
1486 Bool_t firstNamePart = kTRUE;
1487 while (author.Tokenize(namePart, posNamePart, " ")) {
1488 namePart.Strip(TString::kBoth);
1489 if (!namePart.Length())
1490 continue;
1491 if (isdigit(namePart[0])) continue; //likely a date
1492 if (!firstNamePart)
1493 authors += '+';
1494 firstNamePart = kFALSE;
1495 authors += namePart;
1496 }
1497 authors += "\">";
1498 authors += author;
1499 authors += "</a>";
1500 }
1501 } // while next author
1502}
1503
1504////////////////////////////////////////////////////////////////////////////////
1505/// Check if file is modified
1506///
1507///
1508/// Input: classPtr - pointer to the class
1509/// type - file type to compare with
1510/// values: kSource, kInclude, kTree
1511///
1512/// Output: TRUE - if file is modified since last time
1513/// FALSE - if file is up to date
1514///
1515
1517{
1518 TString sourceFile;
1519 TString classname(classPtr->GetName());
1520 TString filename;
1521 TString dir;
1522
1523 switch (type) {
1524 case kSource:
1525 {
1526 TString declFile;
1527 if (classPtr->GetImplFileLine()) {
1528 fHtml->GetImplFileName(classPtr, kTRUE, sourceFile);
1529 }
1530 fHtml->GetDeclFileName(classPtr, kTRUE, declFile);
1531 Long64_t size;
1532 Long_t id, flags, iModtime, dModtime;
1533 if (!(gSystem->GetPathInfo(sourceFile, &id, &size, &flags, &iModtime))) {
1534 if (!(gSystem->GetPathInfo(declFile, &id, &size, &flags, &dModtime))) {
1535 if (iModtime < dModtime) {
1536 // decl is newer than impl
1537 sourceFile = declFile;
1538 }
1539 }
1540 }
1541 dir = "src";
1543 filename = classname;
1544 NameSpace2FileName(filename);
1545 gSystem->PrependPathName(dir, filename);
1546 if (classPtr->GetImplFileLine())
1547 filename += ".cxx.html";
1548 else
1549 filename += ".h.html";
1550 break;
1551 }
1552
1553 case kInclude:
1554 fHtml->GetDeclFileName(classPtr, kFALSE, filename);
1555 filename = gSystem->BaseName(filename);
1556 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
1558 break;
1559
1560 case kTree:
1561 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
1562 NameSpace2FileName(classname);
1563 gSystem->PrependPathName(fHtml->GetOutputDir(), classname);
1564 filename = classname;
1565 filename += "_Tree.pdf";
1566 break;
1567
1568 case kDoc:
1569 {
1570 TString declFile;
1571 if (classPtr->GetImplFileLine()) {
1572 fHtml->GetImplFileName(classPtr, kTRUE, sourceFile);
1573 }
1574 fHtml->GetDeclFileName(classPtr, kTRUE, declFile);
1575 Long64_t size;
1576 Long_t id, flags, iModtime, dModtime;
1577 if (!(gSystem->GetPathInfo(sourceFile, &id, &size, &flags, &iModtime))) {
1578 if (!(gSystem->GetPathInfo(declFile, &id, &size, &flags, &dModtime))) {
1579 if (iModtime < dModtime) {
1580 // decl is newer than impl
1581 sourceFile = declFile;
1582 }
1583 }
1584 }
1585 filename = classname;
1586 NameSpace2FileName(filename);
1588 filename += ".html";
1589 break;
1590 }
1591
1592 default:
1593 Error("IsModified", "Unknown file type !");
1594 }
1595
1596 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1597
1598 // Get info about a file
1599 Long64_t size;
1600 Long_t id, flags, sModtime, dModtime;
1601
1602 if (!(gSystem->GetPathInfo(sourceFile, &id, &size, &flags, &sModtime))) {
1603 if (!(gSystem->GetPathInfo(filename, &id, &size, &flags, &dModtime))) {
1604 return (sModtime > dModtime);
1605 }
1606 }
1607
1608 return kTRUE;
1609}
1610
1611
1612////////////////////////////////////////////////////////////////////////////////
1613/// Replace "::" in name by "__"
1614/// Replace "<", ">", " ", ",", "~", "=" in name by "_"
1615/// Replace "A::X<A::Y>" by "A::X<-p0Y>",
1616/// "A::B::X<A::B::Y>" by "A::B::X<-p1Y>", etc
1617
1619{
1620 TString encScope(name);
1621 Ssiz_t posTemplate = encScope.Index('<');
1622 if (posTemplate != kNPOS) {
1623 // strip default template params
1625 TString templateArgs = encScope(posTemplate, encScope.Length());
1626 encScope.Remove(posTemplate, encScope.Length());
1627 // shorten the name a bit:
1628 // convert A::B::X<A::B::Y> to A::X<-p1Y>, i.e.
1629 // the filename A__X_A__Y_ to A__X_-p1Y_
1630 // The rule: if the enclosing scope up to the N-th scope matches,
1631 // the name becomes -pN
1632 Ssiz_t posName = encScope.Last(':');
1633 if (posName != kNPOS) {
1634 Int_t numDblColumn = encScope.CountChar(':');
1635 while (numDblColumn > 1) {
1636 encScope.Remove(posName + 1, encScope.Length());
1637 numDblColumn -= 2;
1638 templateArgs.ReplaceAll(encScope, TString::Format("-p%d", numDblColumn / 2));
1639 encScope.Remove(encScope.Length() - 2, 2);
1640 posName = encScope.Last(':');
1641 if (posName == kNPOS)
1642 break; // should be handled by numDblColumn...
1643 }
1644 name.Replace(posTemplate, name.Length(), templateArgs);
1645 }
1646 }
1647
1648 if (name.Length() > 240) { // really 240! It might get some extra prefix or extension
1649 // 8.3 is dead, but e.g. ext2 can only hold 255 chars in a file name.
1650 // So mangle name to "beginning_of_name"-h"hash"."extension", where
1651 // beginning_of_name is short enough such that the full name is <255 characters.
1652
1653 TString hash;
1655 hash.Prepend("-h");
1656 Ssiz_t posDot = name.Last('.');
1657 TString ext;
1658 if (posDot != kNPOS)
1659 ext = name(posDot, name.Length());
1660 Ssiz_t namelen = 240 - hash.Length() - ext.Length();
1661 name = name(0, namelen) + hash + ext;
1662 }
1663
1664 const char* replaceWhat = ":<> ,~=";
1665 for (Ssiz_t i=0; i < name.Length(); ++i)
1666 if (strchr(replaceWhat, name[i]))
1667 name[i] = '_';
1668}
1669
1670////////////////////////////////////////////////////////////////////////////////
1671/// Write links to files indir/*.txt, indir/*.html (non-recursive) to out.
1672/// If one of the files is called "index.{html,txt}" it will be
1673/// included in out (instead of copying it to outdir and generating a link
1674/// to linkdir). txt files are passed through Convert().
1675/// The files' links are sorted alphabetically.
1676
1677void TDocOutput::ProcessDocInDir(std::ostream& out, const char* indir,
1678 const char* outdir, const char* linkdir)
1679{
1680 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1681
1682 void * dirHandle = gSystem->OpenDirectory(indir);
1683 if (!dirHandle) return;
1684
1685 const char* entry = 0;
1686 std::list<std::string> files;
1687 while ((entry = gSystem->GetDirEntry(dirHandle))) {
1688 FileStat_t stat;
1689 TString filename(entry);
1690 gSystem->PrependPathName(indir, filename);
1691 if (gSystem->GetPathInfo(filename, stat)) // funny ret
1692 continue;
1693 if (!R_ISREG(stat.fMode)) continue;
1694
1695 if (TString(entry).BeginsWith("index.", TString::kIgnoreCase)) {
1696 // This is the part we put directly (verbatim) into the module index.
1697 // If it ends on ".txt" we run Convert first.
1698 if (filename.EndsWith(".txt", TString::kIgnoreCase)) {
1699 std::ifstream in(filename);
1700 if (in) {
1701 out << "<pre>"; // this is what e.g. the html directive expects
1702 TDocParser parser(*this);
1703 parser.Convert(out, in, "./", kFALSE /* no code */, kTRUE /*process Directives*/);
1704 out << "</pre>";
1705 }
1706 } else if (filename.EndsWith(".html", TString::kIgnoreCase)) {
1707 std::ifstream in(filename);
1708 TString line;
1709 while (in) {
1710 if (!line.ReadLine(in)) break;
1711 out << line << std::endl;
1712 }
1713 } else
1714 files.push_back(filename.Data());
1715 } else
1716 files.push_back(filename.Data());
1717 }
1718
1719 std::stringstream furtherReading;
1720 files.sort();
1721 for (std::list<std::string>::const_iterator iFile = files.begin();
1722 iFile != files.end(); ++iFile) {
1723 TString filename(iFile->c_str());
1724 if (gSystem->AccessPathName(outdir))
1725 if (gSystem->mkdir(outdir, kTRUE) == -1)
1726 // bad - but let's still try to create the output
1727 Error("CreateModuleIndex", "Cannot create output directory %s", outdir);
1728
1729 TString outfile(gSystem->BaseName(filename));
1730 gSystem->PrependPathName(outdir, outfile);
1731
1732 if (!filename.EndsWith(".txt", TString::kIgnoreCase)
1733 && !filename.EndsWith(".html", TString::kIgnoreCase)) {
1734 // copy to outdir, who know whether it's needed...
1735 if (gSystem->CopyFile(filename, outfile, kTRUE) == -1) {
1736 Error("CreateModuleIndex", "Cannot copy file %s to %s",
1737 filename.Data(), outfile.Data());
1738 continue;
1739 }
1740 continue;
1741 }
1742
1743 // Just copy and link this page.
1744 if (outfile.EndsWith(".txt", TString::kIgnoreCase)) {
1745 // convert first
1746 outfile.Remove(outfile.Length()-3, 3);
1747 outfile += "html";
1748 std::ifstream inFurther(filename);
1749 std::ofstream outFurther(outfile);
1750 if (inFurther && outFurther) {
1751 outFurther << "<pre>"; // this is what e.g. the html directive expects
1752 TDocParser parser(*this);
1753 parser.Convert(outFurther, inFurther, "../", kFALSE /*no code*/, kTRUE /*process Directives*/);
1754 outFurther << "</pre>";
1755 }
1756 } else {
1757 if (gSystem->CopyFile(filename, outfile, kTRUE) == -1)
1758 continue;
1759 }
1760 TString showname(gSystem->BaseName(outfile));
1761 furtherReading << "<a class=\"linkeddoc\" href=\"" << linkdir << "/" << showname << "\">";
1762 showname.Remove(showname.Length() - 5, 5); // .html
1763 showname.ReplaceAll("_", " ");
1764 ReplaceSpecialChars(furtherReading, showname);
1765 furtherReading << "</a> " << std::endl;
1766 }
1767
1768 gSystem->FreeDirectory(dirHandle);
1769 if (furtherReading.str().length())
1770 out << "<h3>Further Reading</h3><div id=\"furtherreading\">" << std::endl
1771 << furtherReading.str() << "</div><h3>List of Classes</h3>" << std::endl;
1772}
1773
1774////////////////////////////////////////////////////////////////////////////////
1775/// Create a reference to a class documentation page.
1776/// str encloses the text to create the reference for (e.g. name of instance).
1777/// comment will be added e.g. as tooltip text.
1778/// After the reference is put into str.String(), str will enclose the reference
1779/// and the original text. Example:
1780/// Input:
1781/// str.String(): "a gHtml test"
1782/// str.Begin(): 2
1783/// str.Length(): 5
1784/// Output:
1785/// str.String(): "a <a href="THtml.html">gHtml</a> test"
1786/// str.Begin(): 2
1787/// str.Length(): 30
1788
1789void TDocOutput::ReferenceEntity(TSubString& str, TClass* entity, const char* comment /*= 0*/)
1790{
1791 TString link;
1792 fHtml->GetHtmlFileName(entity, link);
1793
1794 if (comment && !strcmp(comment, entity->GetName()))
1795 comment = "";
1796
1797 AddLink(str, link, comment);
1798}
1799
1800////////////////////////////////////////////////////////////////////////////////
1801/// Create a reference to a data member documentation page.
1802/// str encloses the text to create the reference for (e.g. name of instance).
1803/// comment will be added e.g. as tooltip text.
1804/// After the reference is put into str.String(), str will enclose the reference
1805/// and the original text. Example:
1806/// Input:
1807/// str.String(): "a gHtml test"
1808/// str.Begin(): 2
1809/// str.Length(): 5
1810/// Output:
1811/// str.String(): "a <a href="THtml.html">gHtml</a> test"
1812/// str.Begin(): 2
1813/// str.Length(): 30
1814
1815void TDocOutput::ReferenceEntity(TSubString& str, TDataMember* entity, const char* comment /*= 0*/)
1816{
1817 TString link;
1818 TClass* scope = entity->GetClass();
1819 fHtml->GetHtmlFileName(scope, link);
1820 link += "#";
1821
1822 TString mangledName;
1823 if (scope) {
1824 mangledName = scope->GetName();
1825 NameSpace2FileName(mangledName);
1826 link += mangledName;
1827 link += ":";
1828 }
1829
1830 mangledName = entity->GetName();
1831 NameSpace2FileName(mangledName);
1832 link += mangledName;
1833
1834 TString description;
1835 if (!comment) {
1836 description = entity->GetFullTypeName();
1837 description += " ";
1838 if (scope) {
1839 description += scope->GetName();
1840 description += "::";
1841 }
1842 description += entity->GetName();
1843 comment = description.Data();
1844 }
1845
1846 if (comment && !strcmp(comment, entity->GetName()))
1847 comment = "";
1848
1849 AddLink(str, link, comment);
1850}
1851
1852////////////////////////////////////////////////////////////////////////////////
1853/// Create a reference to a type documentation page.
1854/// str encloses the text to create the reference for (e.g. name of instance).
1855/// comment will be added e.g. as tooltip text.
1856/// After the reference is put into str.String(), str will enclose the reference
1857/// and the original text. Example:
1858/// Input:
1859/// str.String(): "a gHtml test"
1860/// str.Begin(): 2
1861/// str.Length(): 5
1862/// Output:
1863/// str.String(): "a <a href="THtml.html">gHtml</a> test"
1864/// str.Begin(): 2
1865/// str.Length(): 30
1866
1867void TDocOutput::ReferenceEntity(TSubString& str, TDataType* entity, const char* comment /*= 0*/)
1868{
1869 TString mangledEntity(entity->GetName());
1870 NameSpace2FileName(mangledEntity);
1871
1872 TString link;
1873 TClassDocInfo* cdi = 0;
1874 bool isClassTypedef = entity->GetType() == -1;
1875 if (isClassTypedef)
1876 /* is class/ struct / union */
1877 isClassTypedef = isClassTypedef && (entity->Property() & 7);
1878 if (isClassTypedef) {
1879 std::string shortTypeName(fHtml->ShortType(entity->GetFullTypeName()));
1880 cdi = (TClassDocInfo*) GetHtml()->GetListOfClasses()->FindObject(shortTypeName.c_str());
1881 }
1882 if (cdi) {
1883 link = mangledEntity + ".html";
1884 } else {
1885 link = "ListOfTypes.html#";
1886 link += mangledEntity;
1887 }
1888
1889 if (comment && !strcmp(comment, entity->GetName()))
1890 comment = "";
1891
1892 AddLink(str, link, comment);
1893}
1894
1895////////////////////////////////////////////////////////////////////////////////
1896/// Create a reference to a method documentation page.
1897/// str encloses the text to create the reference for (e.g. name of instance).
1898/// comment will be added e.g. as tooltip text.
1899/// After the reference is put into str.String(), str will enclose the reference
1900/// and the original text. Example:
1901/// Input:
1902/// str.String(): "a gHtml test"
1903/// str.Begin(): 2
1904/// str.Length(): 5
1905/// Output:
1906/// str.String(): "a <a href="THtml.html">gHtml</a> test"
1907/// str.Begin(): 2
1908/// str.Length(): 30
1909
1910void TDocOutput::ReferenceEntity(TSubString& str, TMethod* entity, const char* comment /*= 0*/)
1911{
1912 TString link;
1913 TClass* scope = entity->GetClass();
1914 fHtml->GetHtmlFileName(scope, link);
1915 link += "#";
1916
1917 TString mangledName(scope->GetName());
1918 NameSpace2FileName(mangledName);
1919 link += mangledName;
1920 link += ":";
1921
1922 mangledName = entity->GetName();
1923 NameSpace2FileName(mangledName);
1924 link += mangledName;
1925
1926 TString description;
1927 if (!comment && entity->GetClass()) {
1928 TIter iMeth(scope->GetListOfMethods());
1929 TMethod* mCand = 0;
1930 while ((mCand = (TMethod*)iMeth()))
1931 if (!strcmp(mCand->GetName(), entity->GetName())) {
1932 if (description.Length()) {
1933 description += " or overloads";
1934 break;
1935 }
1936 description = mCand->GetPrototype();
1937 }
1938 comment = description.Data();
1939 }
1940
1941 if (comment && !strcmp(comment, entity->GetName()))
1942 comment = "";
1943
1944 AddLink(str, link, comment);
1945}
1946
1947////////////////////////////////////////////////////////////////////////////////
1948/// Check whether reference is a relative reference, and can (or should)
1949/// be prependen by relative paths. For HTML, check that it doesn't start
1950/// with "http://" or "https://"
1951
1952Bool_t TDocOutput::ReferenceIsRelative(const char* reference) const
1953{
1954 return !reference ||
1955 strncmp(reference, "http", 4) ||
1956 (strncmp(reference + 4, "://", 3) && strncmp(reference + 4, "s://", 4));
1957}
1958
1959////////////////////////////////////////////////////////////////////////////////
1960/// Replace ampersand, less-than and greater-than character, writing to out.
1961/// If 0 is returned, no replacement needs to be done.
1962
1964{
1965 /*
1966 if (fEscFlag) {
1967 fEscFlag = kFALSE;
1968 return buf;
1969 } else if (c == fEsc) {
1970 // text.Remove(pos, 1); - NO! we want to keep it nevertheless!
1971 fEscFlag = kTRUE;
1972 return buf;
1973 }
1974
1975 */
1976 switch (c) {
1977 case '<': return "&lt;";
1978 case '&': return "&amp;";
1979 case '>': return "&gt;";
1980 };
1981 return 0;
1982}
1983
1984////////////////////////////////////////////////////////////////////////////////
1985/// Replace ampersand, less-than and greater-than character
1986///
1987///
1988/// Input: text - text where replacement will happen,
1989/// pos - index of char to be replaced; will point to next char to be
1990/// replaced when function returns
1991///
1992
1994{
1995 const char c = text[pos];
1996 const char* replaced = ReplaceSpecialChars(c);
1997 if (replaced) {
1998 text.Replace(pos, 1, replaced);
1999 pos += strlen(replaced) - 1;
2000 }
2001 ++pos;
2002}
2003
2004////////////////////////////////////////////////////////////////////////////////
2005/// Replace ampersand, less-than and greater-than character
2006///
2007///
2008/// Input: text - text where replacement will happen,
2009///
2010
2012 Ssiz_t pos = 0;
2013 while (pos < text.Length())
2015}
2016
2017////////////////////////////////////////////////////////////////////////////////
2018/// Replace ampersand, less-than and greater-than characters, writing to out
2019///
2020///
2021/// Input: out - output file stream
2022/// string - pointer to an array of characters
2023///
2024
2025void TDocOutput::ReplaceSpecialChars(std::ostream& out, const char *string)
2026{
2027 while (string && *string) {
2028 const char* replaced = ReplaceSpecialChars(*string);
2029 if (replaced)
2030 out << replaced;
2031 else
2032 out << *string;
2033 string++;
2034 }
2035}
2036
2037////////////////////////////////////////////////////////////////////////////////
2038/// Run filename".dot", creating filename".png", and - if outMap is !=0,
2039/// filename".map", which gets then included literally into outMap.
2040
2041Bool_t TDocOutput::RunDot(const char* filename, std::ostream* outMap /* =0 */,
2042 EGraphvizTool gvwhat /*= kDot*/) {
2043 if (!fHtml->HaveDot())
2044 return kFALSE;
2045
2046 TString runDot;
2047 switch (gvwhat) {
2048 case kNeato: runDot = "neato"; break;
2049 case kFdp: runDot = "fdp"; break;
2050 case kCirco: runDot = "circo"; break;
2051 default: runDot = "dot";
2052 };
2053 if (fHtml->GetDotDir() && *fHtml->GetDotDir())
2055 runDot += " -q1 -Tpng -o";
2056 runDot += filename;
2057 runDot += ".png ";
2058 if (outMap) {
2059 runDot += "-Tcmap -o";
2060 runDot += filename;
2061 runDot += ".map ";
2062 }
2063 runDot += filename;
2064 runDot += ".dot";
2065
2066 if (gDebug > 3)
2067 Info("RunDot", "Running: %s", runDot.Data());
2068 Int_t retDot = gSystem->Exec(runDot);
2069 if (gDebug < 4 && !retDot)
2070 gSystem->Unlink(Form("%s.dot", filename));
2071
2072 if (!retDot && outMap) {
2073 std::ifstream inmap(Form("%s.map", filename));
2074 std::string line;
2075 std::getline(inmap, line);
2076 if (inmap && !inmap.eof()) {
2077 *outMap << "<map name=\"Map" << gSystem->BaseName(filename)
2078 << "\" id=\"Map" << gSystem->BaseName(filename) << "\">" << std::endl;
2079 while (inmap && !inmap.eof()) {
2080 if (line.compare(0, 6, "<area ") == 0) {
2081 size_t posEndTag = line.find('>');
2082 if (posEndTag != std::string::npos)
2083 line.replace(posEndTag, 1, "/>");
2084 }
2085 *outMap << line << std::endl;
2086 std::getline(inmap, line);
2087 }
2088 *outMap << "</map>" << std::endl;
2089 }
2090 inmap.close();
2091 if (gDebug < 7)
2092 gSystem->Unlink(Form("%s.map", filename));
2093 }
2094
2095 if (retDot) {
2096 Error("RunDot", "Error running %s!", runDot.Data());
2098 return kFALSE;
2099 }
2100
2101 return kTRUE;
2102}
2103
2104
2105////////////////////////////////////////////////////////////////////////////////
2106/// Write HTML header
2107///
2108/// Internal method invoked by the overload
2109
2110void TDocOutput::WriteHtmlHeader(std::ostream& out, const char *titleNoSpecial,
2111 const char* dir /*=""*/, TClass *cls /*=0*/,
2112 const char* header)
2113{
2114 std::ifstream addHeaderFile(header);
2115
2116 if (!addHeaderFile.good()) {
2117 Warning("THtml::WriteHtmlHeader",
2118 "Can't open html header file %s\n", header);
2119 return;
2120 }
2121
2122 TString declFileName;
2123 if (cls) fHtml->GetDeclFileName(cls, kFALSE, declFileName);
2124 TString implFileName;
2125 if (cls) fHtml->GetImplFileName(cls, kFALSE, implFileName);
2126
2127 const TString& charset = GetHtml()->GetCharset();
2128 TDatime date;
2129 TString strDate(date.AsString());
2130 TString line;
2131
2132 while (!addHeaderFile.eof()) {
2133
2134 line.ReadLine(addHeaderFile, kFALSE);
2135 if (addHeaderFile.eof())
2136 break;
2137
2138 if (line) {
2139
2140 if (!cls && (
2141 line.Index("%CLASS%") != kNPOS ||
2142 line.Index("%INCFILE%") != kNPOS ||
2143 line.Index("%SRCFILE%") != kNPOS))
2144 continue; // skip class line for non-class files
2145
2146 TString txt(line);
2147
2148 txt.ReplaceAll("%TITLE%", titleNoSpecial);
2149 txt.ReplaceAll("%DATE%", strDate);
2150 txt.ReplaceAll("%RELDIR%", dir);
2151 txt.ReplaceAll("%CHARSET%", charset);
2152
2153 if (cls) {
2154 txt.ReplaceAll("%CLASS%", cls->GetName());
2155 txt.ReplaceAll("%INCFILE%", declFileName);
2156 txt.ReplaceAll("%SRCFILE%", implFileName);
2157 }
2158
2159 out << txt << std::endl;
2160 }
2161 }
2162}
2163
2164////////////////////////////////////////////////////////////////////////////////
2165/// Write HTML header
2166///
2167///
2168/// Input: out - output file stream
2169/// title - title for the HTML page
2170/// cls - current class
2171/// dir - relative directory to reach the top
2172/// ("" for html doc, "../" for src/*cxx.html etc)
2173///
2174/// evaluates the Root.Html.Header setting:
2175/// * if not set, the standard header is written. (ROOT)
2176/// * if set, and ends with a "+", the standard header is written and this file
2177/// included afterwards. (ROOT, USER)
2178/// * if set but doesn't end on "+" the file specified will be written instead
2179/// of the standard header (USER)
2180///
2181/// Any occurrence of "%TITLE%" (without the quotation marks) in the user
2182/// provided header file will be replaced by the value of this method's
2183/// parameter "title" before written to the output file. %CLASS% is replaced by
2184/// the class name, %INCFILE% by the header file name as given by
2185/// TClass::GetDeclFileName() and %SRCFILE% by the source file name as given by
2186/// TClass::GetImplFileName(). If the header is written for a non-class page,
2187/// i.e. cls==0, lines containing %CLASS%, %INCFILE%, or %SRCFILE% will be
2188/// skipped.
2189
2190void TDocOutput::WriteHtmlHeader(std::ostream& out, const char *title,
2191 const char* dir /*=""*/, TClass *cls/*=0*/)
2192{
2193 TString userHeader = GetHtml()->GetHeader();
2194 TString noSpecialCharTitle(title);
2195 ReplaceSpecialChars(noSpecialCharTitle);
2196
2197 Ssiz_t lenUserHeader = userHeader.Length();
2198 // standard header output if Root.Html.Header is not set, or it's set and it ends with a "+".
2199 Bool_t bothHeaders = lenUserHeader > 0 && userHeader[lenUserHeader - 1] == '+';
2200 if (lenUserHeader == 0 || bothHeaders) {
2201 TString header("header.html");
2203 WriteHtmlHeader(out, noSpecialCharTitle, dir, cls, header);
2204 }
2205
2206 if (lenUserHeader != 0) {
2207 if (bothHeaders)
2208 userHeader.Remove(lenUserHeader - 1);
2209 WriteHtmlHeader(out, noSpecialCharTitle, dir, cls, userHeader);
2210 };
2211}
2212
2213////////////////////////////////////////////////////////////////////////////////
2214/// Write HTML footer
2215///
2216/// Internal method invoked by the overload
2217
2218void TDocOutput::WriteHtmlFooter(std::ostream& out, const char* /*dir*/,
2219 const char* lastUpdate, const char* author,
2220 const char* copyright, const char* footer)
2221{
2222 static const char* templateSITags[TDocParser::kNumSourceInfos] = { "%UPDATE%", "%AUTHOR%", "%COPYRIGHT%", "%CHANGED%", "%GENERATED%"};
2223
2224 TString today;
2225 TDatime dtToday;
2226 today.Form("%d-%02d-%02d %02d:%02d", dtToday.GetYear(), dtToday.GetMonth(), dtToday.GetDay(), dtToday.GetHour(), dtToday.GetMinute());
2227
2228 TString datimeString;
2229 if (!lastUpdate || !lastUpdate[0]) {
2230 lastUpdate = today;
2231 }
2232 const char* siValues[TDocParser::kNumSourceInfos] = { lastUpdate, author, copyright, lastUpdate, today };
2233
2234 std::ifstream addFooterFile(footer);
2235
2236 if (!addFooterFile.good()) {
2237 Warning("THtml::WriteHtmlFooter",
2238 "Can't open html footer file %s\n", footer);
2239 return;
2240 }
2241
2242 TString line;
2243 while (!addFooterFile.eof()) {
2244
2245 line.ReadLine(addFooterFile, kFALSE);
2246 if (addFooterFile.eof())
2247 break;
2248
2249 if (!line)
2250 continue;
2251
2252 for (Int_t siTag = 0; siTag < (Int_t) TDocParser::kNumSourceInfos; ++siTag) {
2253 Ssiz_t siPos = line.Index(templateSITags[siTag]);
2254 if (siPos != kNPOS) {
2255 if (siValues[siTag] && siValues[siTag][0])
2256 line.Replace(siPos, strlen(templateSITags[siTag]), siValues[siTag]);
2257 else
2258 line = ""; // skip e.g. %AUTHOR% lines if no author is set
2259 }
2260 }
2261
2262 out << line << std::endl;
2263 }
2264
2265}
2266
2267////////////////////////////////////////////////////////////////////////////////
2268/// Write HTML footer
2269///
2270///
2271/// Input: out - output file stream
2272/// dir - usually equal to "" or "../", depends of
2273/// current file directory position, i.e. if
2274/// file is in the fHtml->GetOutputDir(), then dir will be ""
2275/// lastUpdate - last update string
2276/// author - author's name
2277/// copyright - copyright note
2278///
2279/// Allows optional user provided footer to be written. Root.Html.Footer holds
2280/// the file name for this footer. For details see THtml::WriteHtmlHeader (here,
2281/// the "+" means the user's footer is written in front of Root's!) Occurrences
2282/// of %AUTHOR%, %CHANGED%, %GENERATED%, and %COPYRIGHT% in the user's file are replaced by
2283/// their corresponding values (author, lastUpdate, today, and copyright) before
2284/// written to out.
2285/// If no author is set (author == "", e.g. for ClassIndex.html") skip the whole
2286/// line of the footer template containing %AUTHOR%. Accordingly for %COPYRIGHT%.
2287
2288void TDocOutput::WriteHtmlFooter(std::ostream& out, const char *dir,
2289 const char *lastUpdate, const char *author,
2290 const char *copyright)
2291{
2292 out << std::endl;
2293
2294 TString userFooter = GetHtml()->GetFooter();
2295
2296 if (userFooter.Length() != 0) {
2297 TString footer(userFooter);
2298 if (footer.EndsWith("+"))
2299 footer.Remove(footer.Length() - 1);
2300 WriteHtmlFooter(out, dir, lastUpdate, author, copyright, footer);
2301 };
2302
2303 if (userFooter.Length() == 0 || userFooter.EndsWith("+")) {
2304 TString footer("footer.html");
2306 WriteHtmlFooter(out, dir, lastUpdate, author, copyright, footer);
2307 }
2308}
2309
2310////////////////////////////////////////////////////////////////////////////////
2311/// Create a div containing links to all topmost modules
2312
2313void TDocOutput::WriteModuleLinks(std::ostream& out)
2314{
2315 if (fHtml->GetListOfModules()->GetSize()) {
2316 out << "<div id=\"indxModules\"><h4>Modules</h4>" << std::endl;
2317 // find index chars
2319 TIter iModule(fHtml->GetListOfModules());
2320 TModuleDocInfo* module = 0;
2321 while ((module = (TModuleDocInfo*) iModule())) {
2322 if (!module->GetName() || strchr(module->GetName(), '/'))
2323 continue;
2324 if (module->IsSelected()) {
2325 TString name(module->GetName());
2326 name.ToUpper();
2327 out << "<a href=\"" << name << "_Index.html\">"
2328 << name << "</a>" << std::endl;
2329 }
2330 }
2331 out<< "</div><br />" << std::endl;
2332 }
2333}
2334
2335////////////////////////////////////////////////////////////////////////////////
2336/// Create a div containing the line numbers (for a source listing) 1 to nLines.
2337/// Create links to the source file's line number and anchors, such that one can
2338/// jump to SourceFile.cxx.html#27 (using the anchor), and one can copy and paste
2339/// the link into e.g. gdb to get the text "SourceFile.cxx:27".
2340
2341void TDocOutput::WriteLineNumbers(std::ostream& out, Long_t nLines, const TString& infileBase) const
2342{
2343 out << "<div id=\"linenums\">";
2344 for (Long_t i = 0; i < nLines; ++i) {
2345 // &nbsp; to force correct line height
2346 out << "<div class=\"ln\">&nbsp;<span class=\"lnfile\">" << infileBase
2347 << ":</span><a name=\"" << i + 1 << "\" href=\"#" << i + 1
2348 << "\" class=\"ln\">" << i + 1 << "</a></div>";
2349 }
2350 out << "</div>" << std::endl;
2351
2352}
2353
2354////////////////////////////////////////////////////////////////////////////////
2355/// Create a div containing links to all modules
2356
2357void TDocOutput::WriteModuleLinks(std::ostream& out, TModuleDocInfo* super)
2358{
2359 if (super->GetSub().GetSize()) {
2360 TString superName(super->GetName());
2361 superName.ToUpper();
2362 out << "<div id=\"indxModules\"><h4>" << superName << " Modules</h4>" << std::endl;
2363 // find index chars
2364 super->GetSub().Sort();
2365 TIter iModule(&super->GetSub());
2366 TModuleDocInfo* module = 0;
2367 while ((module = (TModuleDocInfo*) iModule())) {
2368 if (module->IsSelected()) {
2369 TString name(module->GetName());
2370 name.ToUpper();
2371 TString link(name);
2372 link.ReplaceAll("/", "_");
2373 Ssiz_t posSlash = name.Last('/');
2374 if (posSlash != kNPOS)
2375 name.Remove(0, posSlash + 1);
2376 out << "<a href=\"" << link << "_Index.html\">" << name << "</a>" << std::endl;
2377 }
2378 }
2379 out<< "</div><br />" << std::endl;
2380 }
2381}
2382
2383////////////////////////////////////////////////////////////////////////////////
2384/// Write a search link or a search box, based on THtml::GetSearchStemURL()
2385/// and THtml::GetSearchEngine(). The first one is preferred.
2386
2387void TDocOutput::WriteSearch(std::ostream& out)
2388{
2389 // e.g. searchCmd = "http://www.google.com/search?q=%s+site%3A%u+-site%3A%u%2Fsrc%2F+-site%3A%u%2Fexamples%2F";
2390 const TString& searchCmd = GetHtml()->GetSearchStemURL();
2391 const TString& searchEngine = GetHtml()->GetSearchEngine();
2392
2393 if (!searchCmd.Length() && !searchEngine.Length())
2394 return;
2395
2396 if (searchCmd.Length()) {
2397 TUrl url(searchCmd);
2398 TString serverName(url.GetHost());
2399 if (serverName.Length()) {
2400 serverName.Prepend(" title=\"");
2401 serverName += "\" ";
2402 }
2403 // create search input
2404 out << "<script type=\"text/javascript\">" << std::endl
2405 << "function onSearch() {" << std::endl
2406 << "var s='" << searchCmd <<"';" << std::endl
2407 << "var ref=String(document.location.href).replace(/https?:\\/\\//,'').replace(/\\/[^\\/]*$/,'').replace(/\\//g,'%2F');" << std::endl
2408 << "window.location.href=s.replace(/%u/ig,ref).replace(/%s/ig,escape(document.searchform.t.value));" << std::endl
2409 << "return false;}" << std::endl
2410 << "</script>" << std::endl
2411 << "<form id=\"searchform\" name=\"searchform\" onsubmit=\"return onSearch()\" action=\"javascript:onSearch();\" method=\"post\">" << std::endl
2412 << "<input name=\"t\" size=\"30\" value=\"Search documentation...\" onfocus=\"if (document.searchform.t.value=='Search documentation...') document.searchform.t.value='';\"></input>" << std::endl
2413 << "<a id=\"searchlink\" " << serverName << " href=\"javascript:onSearch();\" onclick=\"return onSearch()\">Search</a></form>" << std::endl;
2414 } else if (searchEngine.Length())
2415 // create link to search engine page
2416 out << "<a class=\"descrheadentry\" href=\"" << searchEngine
2417 << "\">Search the Class Reference Guide</a>" << std::endl;
2418}
2419
2420
2421////////////////////////////////////////////////////////////////////////////////
2422/// make a link to the description
2423
2424void TDocOutput::WriteLocation(std::ostream& out, TModuleDocInfo* module, const char* classname)
2425{
2426 out << "<div class=\"location\">" << std::endl; // location
2427 const char *productName = fHtml->GetProductName();
2428 out << "<a class=\"locationlevel\" href=\"index.html\">" << productName << "</a>" << std::endl;
2429
2430 if (module) {
2431 TString modulename(module->GetName());
2432 modulename.ToUpper();
2433 TString modulePart;
2434 TString modulePath;
2435 Ssiz_t pos = 0;
2436 while (modulename.Tokenize(modulePart, pos, "/")) {
2437 if (pos == kNPOS && !classname)
2438 // we are documenting the module itself, no need to link it:
2439 break;
2440 if (modulePath.Length()) modulePath += "_";
2441 modulePath += modulePart;
2442 out << " &#187; <a class=\"locationlevel\" href=\"./" << modulePath << "_Index.html\">" << modulePart << "</a>" << std::endl;
2443 }
2444 }
2445
2446 TString entityName;
2447 if (classname) entityName = classname;
2448 else if (module) {
2449 entityName = module->GetName();
2450 Ssiz_t posSlash = entityName.Last('/');
2451 if (posSlash != kNPOS)
2452 entityName.Remove(0, posSlash + 1);
2453 entityName.ToUpper();
2454 }
2455 if (entityName.Length()) {
2456 out << " &#187; <a class=\"locationlevel\" href=\"#TopOfPage\">";
2457 ReplaceSpecialChars(out, entityName);
2458 out << "</a>" << std::endl;
2459 }
2460 out << "</div>" << std::endl; // location
2461}
2462
2463
2464////////////////////////////////////////////////////////////////////////////////
2465/// Write the first part of the links shown ontop of each doc page;
2466/// one <div> has to be closed by caller so additional items can still
2467/// be added.
2468
2469void TDocOutput::WriteTopLinks(std::ostream& out, TModuleDocInfo* module, const char* classname,
2470 Bool_t withLocation)
2471{
2472 out << "<div id=\"toplinks\">" << std::endl;
2473
2474 out << "<div class=\"descrhead\"><div class=\"descrheadcontent\">" << std::endl // descrhead line 1
2475 << "<span class=\"descrtitle\">Quick Links:</span>" << std::endl;
2476
2477 // link to the user home page (if exist)
2478 const char* userHomePage = GetHtml()->GetHomepage();
2479 const char* productName = fHtml->GetProductName();
2480 if (!productName) {
2481 productName = "";
2482 } else if (!strcmp(productName, "ROOT")) {
2483 userHomePage = "";
2484 }
2485 if (userHomePage && *userHomePage)
2486 out << "<a class=\"descrheadentry\" href=\"" << userHomePage << "\">" << productName << "</a>" << std::endl;
2487 out << "<a class=\"descrheadentry\" href=\"http://root.cern.ch\">ROOT Homepage</a>" << std::endl
2488 << "<a class=\"descrheadentry\" href=\"./ClassIndex.html\">Class Index</a>" << std::endl
2489 << "<a class=\"descrheadentry\" href=\"./ClassHierarchy.html\">Class Hierarchy</a></div>" << std::endl;
2490 WriteSearch(out);
2491 out << "</div>" << std::endl; // descrhead, line 1
2492
2493 if (withLocation) {
2494 out << "</div>" << std::endl; //toplinks
2495 WriteLocation(out, module, classname); // descrhead line 2
2496 }
2497 // else {
2498 // Closed by caller!
2499 // out << "</div>" << std::endl; // toplinks
2500 // }
2501
2502}
#define c(i)
Definition: RSha256.hxx:101
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:69
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
static int CaseInsensitiveSort(const void *name1, const void *name2)
Friend function for sorting strings, case insensitive.
Definition: TDocOutput.cxx:198
int type
Definition: TGX11.cxx:120
#define Printf
Definition: TGeoToOCC.h:18
#define gInterpreter
Definition: TInterpreter.h:538
#define gROOT
Definition: TROOT.h:410
char * Form(const char *fmt,...)
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2465
Bool_t R_ISREG(Int_t mode)
Definition: TSystem.h:119
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
#define R__LOCKGUARD(mutex)
Bool_t HaveSource() const
Definition: TDocInfo.h:71
virtual const char * GetName() const
Returns name of object.
Definition: TDocInfo.cxx:26
const char * GetHtmlFileName() const
Definition: TDocInfo.h:60
Bool_t IsSelected() const
Definition: TDocInfo.h:70
TList & GetListOfTypedefs()
Definition: TDocInfo.h:82
TDictionary * GetClass() const
Definition: TDocInfo.h:58
void CreateClassHierarchy(std::ostream &out, const char *docFileName)
Create the hierarchical class list part for the current class's base classes.
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition: TClass.cxx:3664
const char * GetSharedLibs()
Get the list of shared libraries containing the code for class cls.
Definition: TClass.cxx:3492
Short_t GetImplFileLine() const
Definition: TClass.h:427
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
virtual Bool_t IsEmpty() const
Definition: TCollection.h:186
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TClass * GetClass() const
Definition: TDataMember.h:73
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
Int_t GetType() const
Definition: TDataType.h:68
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TDataType.cxx:287
const char * GetFullTypeName() const
Get full type description of typedef, e,g.: "class TDirectory*".
Definition: TDataType.cxx:175
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
Int_t GetMonth() const
Definition: TDatime.h:66
Int_t GetDay() const
Definition: TDatime.h:67
Int_t GetHour() const
Definition: TDatime.h:69
Int_t GetYear() const
Definition: TDatime.h:65
Int_t GetMinute() const
Definition: TDatime.h:70
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:101
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:159
virtual Bool_t IsModified(TClass *classPtr, EFileType type)
Check if file is modified.
void Convert(std::istream &in, const char *infilename, const char *outfilename, const char *title, const char *relpath="../", Int_t includeOutput=0, const char *context="", TGClient *gclient=0)
Convert a text file into a html file.
Definition: TDocOutput.cxx:311
virtual void DecorateEntityBegin(TString &str, Ssiz_t &pos, TDocParser::EParseContext type)
Add some colors etc to a source entity, contained in str.
virtual void NameSpace2FileName(TString &name)
Replace "::" in name by "__" Replace "<", ">", " ", ",", "~", "=" in name by "_" Replace "A::X<A::Y>"...
void WriteTopLinks(std::ostream &out, TModuleDocInfo *module, const char *classname=0, Bool_t withLocation=kTRUE)
Write the first part of the links shown ontop of each doc page; one <div> has to be closed by caller ...
virtual void CreateProductIndex()
Fetch documentation from THtml::GetProductDocDir() and put it into the product index page.
virtual void CreateClassTypeDefs()
Create a forwarding page for each typedef pointing to a class.
void WriteLineNumbers(std::ostream &out, Long_t nLines, const TString &infileBase) const
Create a div containing the line numbers (for a source listing) 1 to nLines.
virtual void ReferenceEntity(TSubString &str, TClass *entity, const char *comment=0)
Create a reference to a class documentation page.
Bool_t CopyHtmlFile(const char *sourceName, const char *destName="")
Copy file to HTML directory.
Definition: TDocOutput.cxx:593
virtual void CreateHierarchy()
Create a hierarchical class list The algorithm descends from the base classes and branches into all d...
Definition: TDocOutput.cxx:640
void WriteHtmlFooter(std::ostream &out, const char *dir, const char *lastUpdate, const char *author, const char *copyright, const char *footer)
Write HTML footer.
virtual const char * ReplaceSpecialChars(char c)
Replace ampersand, less-than and greater-than character, writing to out.
virtual Bool_t ReferenceIsRelative(const char *reference) const
Check whether reference is a relative reference, and can (or should) be prependen by relative paths.
Bool_t RunDot(const char *filename, std::ostream *outMap=0, EGraphvizTool gvwhat=kDot)
Run filename".dot", creating filename".png", and - if outMap is !=0, filename".map",...
virtual void CreateClassIndex()
Create index of all classes.
Definition: TDocOutput.cxx:693
THtml * fHtml
Definition: TDocOutput.h:46
virtual void CreateTypeIndex()
Create index of all data types.
virtual void DecorateEntityEnd(TString &str, Ssiz_t &pos, TDocParser::EParseContext type)
Add some colors etc to a source entity, contained in str.
virtual void FixupAuthorSourceInfo(TString &authors)
Special author treatment; called when TDocParser::fSourceInfo[kInfoAuthor] is set.
virtual void CreateModuleIndex()
Create the class index for each module, picking up documentation from the module's TModuleDocInfo::Ge...
Definition: TDocOutput.cxx:801
virtual void AdjustSourcePath(TString &line, const char *relpath="../")
adjust the path of links for source files, which are in src/, but need to point to relpath (usually "...
Definition: TDocOutput.cxx:297
THtml * GetHtml()
Definition: TDocOutput.h:90
void ProcessDocInDir(std::ostream &out, const char *indir, const char *outdir, const char *linkdir)
Write links to files indir/*.txt, indir/*.html (non-recursive) to out.
virtual ~TDocOutput()
Definition: TDocOutput.cxx:261
void WriteModuleLinks(std::ostream &out)
Create a div containing links to all topmost modules.
void WriteHtmlHeader(std::ostream &out, const char *titleNoSpecial, const char *dir, TClass *cls, const char *header)
Write HTML header.
virtual void WriteSearch(std::ostream &out)
Write a search link or a search box, based on THtml::GetSearchStemURL() and THtml::GetSearchEngine().
TDocOutput(THtml &html)
Definition: TDocOutput.cxx:256
void WriteLocation(std::ostream &out, TModuleDocInfo *module, const char *classname=0)
make a link to the description
void AddLink(TSubString &str, TString &link, const char *comment)
Add a link around str, with title comment.
Definition: TDocOutput.cxx:268
static void AnchorFromLine(const TString &line, TString &anchor)
Create an anchor from the given line, by hashing it and convertig the hash into a custom base64 strin...
Definition: TDocParser.cxx:381
@ kNumSourceInfos
Definition: TDocParser.h:60
Long_t GetLineNumber() const
Definition: TDocParser.h:174
void Convert(std::ostream &out, std::istream &in, const char *relpath, Bool_t isCode, Bool_t interpretDirectives)
Parse text file "in", add links etc, and write output to "out".
Definition: TDocParser.cxx:402
virtual void DecorateKeywords(std::ostream &out, const char *text)
Expand keywords in text, writing to out.
Definition: TDocParser.cxx:450
virtual const char * GetPrototype() const
Returns the prototype of a function as defined by CINT, or 0 in case of error.
Definition: TFunction.cxx:245
virtual bool GetIncludeAs(TClass *cl, TString &out_include_as) const
Determine the path and filename used in an include statement for the header file of the given class.
Definition: THtml.cxx:571
virtual bool GetDocDir(const TString &module, TString &doc_dir) const
Determine the module's documentation directory.
Definition: THtml.cxx:541
Definition: THtml.h:40
const char * GetCounter() const
Definition: THtml.h:323
@ kForceOutput
Definition: THtml.h:237
@ kCompiledOutput
Definition: THtml.h:236
@ kSeparateProcessOutput
Definition: THtml.h:238
const TString & GetFooter() const
Definition: THtml.h:309
const TString & GetSearchStemURL() const
Definition: THtml.h:311
const TString & GetCharset() const
Definition: THtml.h:315
const char * ShortType(const char *name) const
Get short type name, i.e. with default templates removed.
Definition: THtml.cxx:2510
const TString & GetHomepage() const
Definition: THtml.h:310
const TString & GetProductName() const
Definition: THtml.h:294
void SortListOfModules()
Definition: THtml.h:339
const char * GetCounterFormat() const
Definition: THtml.h:303
TList * GetLibraryDependencies()
Definition: THtml.h:338
const TList * GetListOfModules() const
Definition: THtml.h:340
const TString & GetDotDir() const
Definition: THtml.h:299
const TString & GetSearchEngine() const
Definition: THtml.h:312
Bool_t HaveDot()
Check whether dot is available in $PATH or in the directory set by SetDotPath()
Definition: THtml.cxx:1403
virtual void CreateAuxiliaryFiles() const
copy CSS, javascript file, etc to the output dir
Definition: THtml.cxx:1291
virtual bool GetDeclFileName(TClass *cl, Bool_t filesys, TString &out_name) const
Return declaration file name; return the full path if filesys is true.
Definition: THtml.cxx:2095
const TString & GetHeader() const
Definition: THtml.h:308
void SetFoundDot(Bool_t found=kTRUE)
Set whether "dot" (a GraphViz utility) is available.
Definition: THtml.cxx:2400
virtual const char * GetEtcDir() const
Get the directory containing THtml's auxiliary files ($ROOTSYS/etc/html)
Definition: THtml.cxx:1344
virtual void GetHtmlFileName(TClass *classPtr, TString &filename) const
Return real HTML filename.
Definition: THtml.cxx:1991
virtual void GetModuleNameForClass(TString &module, TClass *cl) const
Return the module name for a given class.
Definition: THtml.cxx:1530
const TString & GetOutputDir(Bool_t createDir=kTRUE) const
Return the output directory as set by SetOutputDir().
Definition: THtml.cxx:2167
virtual bool GetImplFileName(TClass *cl, Bool_t filesys, TString &out_name) const
Return implementation file name.
Definition: THtml.cxx:2103
const TList * GetListOfClasses() const
Definition: THtml.h:341
const TPathDefinition & GetPathDefinition() const
Return the TModuleDefinition (or derived) object as set by SetModuleDefinition(); create and return a...
Definition: THtml.cxx:1331
const TString & GetXwho() const
Definition: THtml.h:301
void Reset()
Definition: TCollection.h:252
void AddDependency(const std::string &lib)
Definition: TDocInfo.h:148
std::set< std::string > & GetDependencies()
Definition: TDocInfo.h:146
std::set< std::string > & GetModules()
Definition: TDocInfo.h:147
void AddModule(const std::string &module)
Definition: TDocInfo.h:149
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual void Sort(Bool_t order=kSortAscending)
Sort linked list.
Definition: TList.cxx:933
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
TClass * GetClass() const
Definition: TMethod.h:55
THashList & GetSub()
Definition: TDocInfo.h:125
Bool_t IsSelected() const
Definition: TDocInfo.h:119
TList * GetClasses()
Definition: TDocInfo.h:122
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:97
Int_t Match(const TString &s, UInt_t start=0)
Runs a match on s against the regex 'this' was created with.
Definition: TPRegexp.cxx:708
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:644
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1896
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2152
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:487
const char * Data() const
Definition: TString.h:364
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
@ kBoth
Definition: TString.h:262
@ kIgnoreCase
Definition: TString.h:263
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:876
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1113
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2172
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
TString & Prepend(const char *cs)
Definition: TString.h:656
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
Definition: TString.cxx:464
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2286
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
A zero length substring is legal.
Definition: TString.h:77
TString & String()
Definition: TString.h:116
Ssiz_t Start() const
Definition: TString.h:115
Ssiz_t Length() const
Definition: TString.h:114
virtual TSeqCollection * GetListOfTimers() const
Definition: TSystem.h:375
Bool_t cd(const char *path)
Definition: TSystem.h:404
const char * pwd()
Definition: TSystem.h:405
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1013
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:852
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:843
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition: TSystem.cxx:1331
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:913
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:662
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1388
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1071
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1286
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:860
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:941
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:425
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition: TSystem.cxx:490
virtual int Unlink(const char *name)
Unlink, i.e.
Definition: TSystem.cxx:1371
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
This class represents a WWW compatible URL.
Definition: TUrl.h:35
const char * GetHost() const
Definition: TUrl.h:70
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:50
virtual void SaveAs(const char *filename="", Option_t *option="") const =0
Save this object in the file specified by filename.
virtual TVirtualViewer3D * GetViewer3D(Option_t *type="")=0
virtual Bool_t HasViewer3D() const =0
TText * text
TLine * line
Int_t fMode
Definition: TSystem.h:128
Long_t fMtime
Definition: TSystem.h:132
auto * l
Definition: textangle.C:4