Logo ROOT   6.12/07
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 
39 namespace {
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 
182 extern "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 
204 namespace {
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 
256 TDocOutput::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 
268 void 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 
297 void 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 
311 void 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 
593 Bool_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 
612  gSystem->PrependPathName(fHtml->GetOutputDir(), destFile);
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");
645  gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
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");
699  gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
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";
832  gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
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 
1189  gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
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");
1280  gSystem->PrependPathName(fHtml->GetOutputDir(), outFile);
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;
1374  case TDocParser::kComment:
1375  str.Insert(pos, "<span class=\"comment\">");
1376  break;
1378  break;
1379  case TDocParser::kString:
1380  str.Insert(pos, "<span class=\"string\">");
1381  break;
1382  case TDocParser::kKeyword:
1383  str.Insert(pos, "<span class=\"keyword\">");
1384  break;
1385  case TDocParser::kCPP:
1386  str.Insert(pos, "<span class=\"cpp\">");
1387  break;
1388  case TDocParser::kVerbatim:
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;
1414  case TDocParser::kComment:
1415  str.Insert(pos, "</span>");
1416  break;
1418  break;
1419  case TDocParser::kString:
1420  str.Insert(pos, "</span>");
1421  break;
1422  case TDocParser::kKeyword:
1423  str.Insert(pos, "</span>");
1424  break;
1425  case TDocParser::kCPP:
1426  str.Insert(pos, "</span>");
1427  break;
1428  case TDocParser::kVerbatim:
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);
1557  gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
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);
1587  gSystem->PrependPathName(fHtml->GetOutputDir(), 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
1624  name = fHtml->ShortType(name);
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;
1654  TDocParser::AnchorFromLine(name, 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 
1677 void 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 
1789 void 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 
1815 void 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 
1867 void 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 
1910 void 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 
1952 Bool_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())
2014  ReplaceSpecialChars(text, pos);
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 
2025 void 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 
2041 Bool_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())
2054  gSystem->PrependPathName(fHtml->GetDotDir(), runDot);
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 
2110 void 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 
2190 void 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");
2202  gSystem->PrependPathName(fHtml->GetEtcDir(), header);
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 
2218 void 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 
2288 void 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");
2305  gSystem->PrependPathName(fHtml->GetEtcDir(), footer);
2306  WriteHtmlFooter(out, dir, lastUpdate, author, copyright, footer);
2307  }
2308 }
2309 
2310 ////////////////////////////////////////////////////////////////////////////////
2311 /// Create a div containing links to all topmost modules
2312 
2313 void 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 
2341 void 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 
2357 void 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 
2387 void 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 
2424 void 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 
2469 void 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 }
A zero length substring is legal.
Definition: TString.h:71
Short_t GetImplFileLine() const
Definition: TClass.h:422
const TString & GetCharset() const
Definition: THtml.h:315
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:932
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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:1276
virtual bool GetDocDir(const TString &module, TString &doc_dir) const
Determine the module&#39;s documentation directory.
Definition: THtml.cxx:541
TDocOutput(THtml &html)
Definition: TDocOutput.cxx:256
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:424
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
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 bool GetImplFileName(TClass *cl, Bool_t filesys, TString &out_name) const
Return implementation file name.
Definition: THtml.cxx:2105
virtual void CreateProductIndex()
Fetch documentation from THtml::GetProductDocDir() and put it into the product index page...
Bool_t HaveDot()
Check whether dot is available in $PATH or in the directory set by SetDotPath()
Definition: THtml.cxx:1403
long long Long64_t
Definition: RtypesCore.h:69
virtual void CreateTypeIndex()
Create index of all data types.
void CreateClassHierarchy(std::ostream &out, const char *docFileName)
Create the hierarchical class list part for the current class&#39;s base classes.
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
TLine * line
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
This class represents a WWW compatible URL.
Definition: TUrl.h:35
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:638
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:1374
std::istream & ReadLine(std::istream &str, Bool_t skipWhite=kTRUE)
Read a line from stream upto newline skipping any whitespace.
Definition: Stringio.cxx:65
void AddDependency(const std::string &lib)
Definition: TDocInfo.h:148
const TString & GetDotDir() const
Definition: THtml.h:299
Bool_t IsSelected() const
Definition: TDocInfo.h:119
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1112
#define gROOT
Definition: TROOT.h:402
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
const TString & GetProductName() const
Definition: THtml.h:294
const char * GetSharedLibs()
Get the list of shared libraries containing the code for class cls.
Definition: TClass.cxx:3494
Bool_t cd(const char *path)
Definition: TSystem.h:404
Ssiz_t Start() const
Definition: TString.h:109
Basic string class.
Definition: TString.h:125
virtual void CreateModuleIndex()
Create the class index for each module, picking up documentation from the module&#39;s TModuleDocInfo::Ge...
Definition: TDocOutput.cxx:801
virtual Bool_t ReferenceIsRelative(const char *reference) const
Check whether reference is a relative reference, and can (or should) be prependen by relative paths...
int Int_t
Definition: RtypesCore.h:41
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1004
bool Bool_t
Definition: RtypesCore.h:59
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition: TSystem.cxx:489
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.
Ssiz_t Length() const
Definition: TString.h:108
Bool_t CopyHtmlFile(const char *sourceName, const char *destName="")
Copy file to HTML directory.
Definition: TDocOutput.cxx:593
#define gInterpreter
Definition: TInterpreter.h:526
Long_t fMtime
Definition: TSystem.h:132
std::set< std::string > & GetDependencies()
Definition: TDocInfo.h:146
TString & Prepend(const char *cs)
Definition: TString.h:607
virtual TSeqCollection * GetListOfTimers() const
Definition: TSystem.h:375
void WriteModuleLinks(std::ostream &out)
Create a div containing links to all topmost modules.
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:595
const char * GetCounter() const
Definition: THtml.h:323
virtual void DecorateEntityBegin(TString &str, Ssiz_t &pos, TDocParser::EParseContext type)
Add some colors etc to a source entity, contained in str.
Bool_t R_ISREG(Int_t mode)
Definition: TSystem.h:119
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:904
const TList * GetListOfClasses() const
Definition: THtml.h:341
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:628
Int_t fMode
Definition: TSystem.h:128
virtual void Sort(Bool_t order=kSortAscending)
Sort linked list.
Definition: TList.cxx:933
virtual void SaveAs(const char *filename="", Option_t *option="") const =0
Save this object in the file specified by filename.
virtual void DecorateEntityEnd(TString &str, Ssiz_t &pos, TDocParser::EParseContext type)
Add some colors etc to a source entity, contained in str.
const char * GetHost() const
Definition: TUrl.h:70
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:851
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1357
Int_t GetDay() const
Definition: TDatime.h:67
Bool_t HaveSource() const
Definition: TDocInfo.h:71
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:2365
virtual const char * GetEtcDir() const
Get the directory containing THtml&#39;s auxiliary files ($ROOTSYS/etc/html)
Definition: THtml.cxx:1344
std::set< std::string > & GetModules()
Definition: TDocInfo.h:147
virtual void CreateAuxiliaryFiles() const
copy CSS, javascript file, etc to the output dir
Definition: THtml.cxx:1291
TList * GetLibraryDependencies()
Definition: THtml.h:338
virtual void CreateHierarchy()
Create a hierarchical class list The algorithm descends from the base classes and branches into all d...
Definition: TDocOutput.cxx:640
static int CaseInsensitiveSort(const void *name1, const void *name2)
Friend function for sorting strings, case insensitive.
Definition: TDocOutput.cxx:198
Long_t GetLineNumber() const
Definition: TDocParser.h:174
Int_t GetMonth() const
Definition: TDatime.h:66
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
const TString & GetFooter() const
Definition: THtml.h:309
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1062
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2231
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:477
void WriteHtmlFooter(std::ostream &out, const char *dir, const char *lastUpdate, const char *author, const char *copyright, const char *footer)
Write HTML footer.
XFontStruct * id
Definition: TGX11.cxx:108
const TString & GetHeader() const
Definition: THtml.h:308
void WriteLocation(std::ostream &out, TModuleDocInfo *module, const char *classname=0)
make a link to the description
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:49
virtual void GetModuleNameForClass(TString &module, TClass *cl) const
Return the module name for a given class.
Definition: THtml.cxx:1530
TDictionary * GetClass() const
Definition: TDocInfo.h:58
A doubly linked list.
Definition: TList.h:44
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
const char * pwd()
Definition: TSystem.h:405
Int_t GetType() const
Definition: TDataType.h:68
const TString & GetSearchEngine() const
Definition: THtml.h:312
TList & GetListOfTypedefs()
Definition: TDocInfo.h:82
Int_t GetMinute() const
Definition: TDatime.h:70
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 void ReferenceEntity(TSubString &str, TClass *entity, const char *comment=0)
Create a reference to a class documentation page.
virtual const char * GetName() const
Returns name of object.
Definition: TDocInfo.cxx:26
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
Int_t GetHour() const
Definition: TDatime.h:69
Basic data type descriptor (datatype information is obtained from CINT).
Definition: TDataType.h:44
virtual const char * ReplaceSpecialChars(char c)
Replace ampersand, less-than and greater-than character, writing to out.
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:158
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
virtual void NameSpace2FileName(TString &name)
Replace "::" in name by "__" Replace "<", ">", " ", ",", "~", "=" in name by "_" Replace "A::X<A::Y>"...
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:561
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2343
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TDataType.cxx:287
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void CreateClassTypeDefs()
Create a forwarding page for each typedef pointing to a class.
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:386
const char * ShortType(const char *name) const
Get short type name, i.e. with default templates removed.
Definition: THtml.cxx:2512
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1080
Handles synchronous and a-synchronous timer events.
Definition: TTimer.h:51
const TString & GetOutputDir(Bool_t createDir=kTRUE) const
Return the output directory as set by SetOutputDir().
Definition: THtml.cxx:2169
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
THtml * fHtml
Definition: TDocOutput.h:46
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:661
THashList & GetSub()
Definition: TDocInfo.h:125
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:2097
virtual void WriteSearch(std::ostream &out)
Write a search link or a search box, based on THtml::GetSearchStemURL() and THtml::GetSearchEngine()...
virtual ~TDocOutput()
Definition: TDocOutput.cxx:261
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:843
void WriteHtmlHeader(std::ostream &out, const char *titleNoSpecial, const char *dir, TClass *cls, const char *header)
Write HTML header.
#define Printf
Definition: TGeoToOCC.h:18
virtual Bool_t IsModified(TClass *classPtr, EFileType type)
Check if file is modified.
const char * GetHtmlFileName() const
Definition: TDocInfo.h:60
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2544
const Bool_t kFALSE
Definition: RtypesCore.h:88
virtual void FixupAuthorSourceInfo(TString &authors)
Special author treatment; called when TDocParser::fSourceInfo[kInfoAuthor] is set.
TString & Remove(Ssiz_t pos)
Definition: TString.h:619
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
const char * GetCounterFormat() const
Definition: THtml.h:303
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2251
virtual Bool_t IsEmpty() const
Definition: TCollection.h:184
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
void AddLink(TSubString &str, TString &link, const char *comment)
Add a link around str, with title comment.
Definition: TDocOutput.cxx:268
#define ClassImp(name)
Definition: Rtypes.h:359
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:875
TText * text
virtual void DecorateKeywords(std::ostream &out, const char *text)
Expand keywords in text, writing to out.
Definition: TDocParser.cxx:450
int type
Definition: TGX11.cxx:120
unsigned long ULong_t
Definition: RtypesCore.h:51
TList * GetClasses()
Definition: TDocInfo.h:122
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:101
#define R__LOCKGUARD(mutex)
void AddModule(const std::string &module)
Definition: TDocInfo.h:149
virtual void CreateClassIndex()
Create index of all classes.
Definition: TDocOutput.cxx:693
virtual void GetHtmlFileName(TClass *classPtr, TString &filename) const
Return real HTML filename.
Definition: THtml.cxx:1991
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:2887
const TString & GetHomepage() const
Definition: THtml.h:310
void SetFoundDot(Bool_t found=kTRUE)
Set whether "dot" (a GraphViz utility) is available.
Definition: THtml.cxx:2402
Int_t Match(const TString &s, UInt_t start=0)
Runs a match on s against the regex &#39;this&#39; was created with.
Definition: TPRegexp.cxx:708
Mother of all ROOT objects.
Definition: TObject.h:37
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 ...
const char * GetFullTypeName() const
Get full type description of typedef, e,g.: "class TDirectory*".
Definition: TDataType.cxx:175
void SortListOfModules()
Definition: THtml.h:339
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
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", which gets then included literally into outMap.
Wrapper for PCRE library (Perl Compatible Regular Expressions).
Definition: TPRegexp.h:97
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
const TString & GetSearchStemURL() const
Definition: THtml.h:311
TClass * GetClass() const
Definition: TMethod.h:55
THtml * GetHtml()
Definition: TDocOutput.h:90
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
Copy a file.
Definition: TSystem.cxx:1321
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:834
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
Definition: TString.cxx:454
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1975
const TList * GetListOfModules() const
Definition: THtml.h:340
virtual Int_t GetSize() const
Definition: TCollection.h:180
const TPathDefinition & GetPathDefinition() const
Return the TModuleDefinition (or derived) object as set by SetModuleDefinition(); create and return a...
Definition: THtml.cxx:1331
Int_t GetYear() const
Definition: TDatime.h:65
TClass * GetClass() const
Definition: TDataMember.h:73
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition: TClass.cxx:3666
const Bool_t kTRUE
Definition: RtypesCore.h:87
const TString & GetXwho() const
Definition: THtml.h:301
TString & String()
Definition: TString.h:110
Definition: THtml.h:40
char name[80]
Definition: TGX11.cxx:109
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
const char * Data() const
Definition: TString.h:345