40 typedef std::vector<std::string> Words_t;
41 typedef Words_t::const_iterator SectionStart_t;
45 TSectionInfo(SectionStart_t start,
size_t chars,
size_t size):
46 fStart(start), fChars(chars), fSize(size) {};
48 SectionStart_t fStart;
52 typedef std::list<TSectionInfo> SectionStarts_t;
54 static void Sections_BuildIndex(SectionStarts_t& sectionStarts,
55 SectionStart_t begin, SectionStart_t end,
61 SectionStart_t cursor = begin;
62 if (sectionStarts.empty() || sectionStarts.back().fStart != cursor)
63 sectionStarts.push_back(TSectionInfo(cursor, 1, 0));
65 SectionStarts_t::iterator prevSection = sectionStarts.end();
68 while (cursor != end) {
69 size_t numLeft = end - cursor;
70 size_t assumedNumSections = (numLeft + maxPerSection - 1 ) / maxPerSection;
71 size_t step = ((numLeft + assumedNumSections - 1) / assumedNumSections);
72 if (!step || step >= numLeft)
return;
74 if (cursor == end)
break;
76 SectionStart_t addWhichOne = prevSection->fStart;
78 size_t selectionChar=1;
79 for (; selectionChar <= cursor->length() && addWhichOne == prevSection->fStart;
81 SectionStart_t checkPrev = cursor;
82 while (--checkPrev != prevSection->fStart
83 && !strncasecmp(checkPrev->c_str(), cursor->c_str(), selectionChar)) { }
85 SectionStart_t checkNext = cursor;
86 while (++checkNext != end
87 && !strncasecmp(checkNext->c_str(), cursor->c_str(), selectionChar)) { }
90 if (checkPrev != prevSection->fStart) {
91 if ((cursor - checkPrev) <= (checkNext - cursor))
92 addWhichOne = ++checkPrev;
93 else if (checkNext != end
94 && (
size_t)(checkNext - cursor) < maxPerSection) {
95 addWhichOne = checkNext;
99 if (addWhichOne == prevSection->fStart)
100 addWhichOne = cursor;
103 while (selectionChar <= prevSection->fStart->length()
104 && selectionChar <= addWhichOne->length()
105 && !strncasecmp(prevSection->fStart->c_str(), addWhichOne->c_str(), selectionChar))
108 sectionStarts.push_back(TSectionInfo(addWhichOne, selectionChar, 0));
109 cursor = addWhichOne;
114 static void Sections_SetSize(SectionStarts_t& sectionStarts,
const Words_t &words)
117 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
118 iSectionStart != sectionStarts.end(); ++iSectionStart) {
119 SectionStarts_t::iterator next = iSectionStart;
121 if (next == sectionStarts.end()) {
122 iSectionStart->fSize = (words.end() - iSectionStart->fStart);
125 iSectionStart->fSize = (next->fStart - iSectionStart->fStart);
129 static void Sections_PostMerge(SectionStarts_t& sectionStarts,
const size_t maxPerSection)
132 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
133 iSectionStart != sectionStarts.end();) {
134 SectionStarts_t::iterator iNextSectionStart = iSectionStart;
136 if (iNextSectionStart == sectionStarts.end())
break;
137 if (iNextSectionStart->fSize + iSectionStart->fSize < maxPerSection) {
138 iSectionStart->fSize += iNextSectionStart->fSize;
139 sectionStarts.erase(iNextSectionStart);
140 }
else ++iSectionStart;
144 static void GetIndexChars(
const Words_t& words, UInt_t numSectionsIn,
145 std::vector<std::string> §ionMarkersOut)
152 const size_t maxPerSection = (words.size() + numSectionsIn - 1)/ numSectionsIn;
153 SectionStarts_t sectionStarts;
154 Sections_BuildIndex(sectionStarts, words.begin(), words.end(), maxPerSection);
155 Sections_SetSize(sectionStarts, words);
156 Sections_PostMerge(sectionStarts, maxPerSection);
159 sectionMarkersOut.clear();
160 sectionMarkersOut.resize(sectionStarts.size());
162 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
163 iSectionStart != sectionStarts.end(); ++iSectionStart)
164 sectionMarkersOut[idx++] =
165 iSectionStart->fStart->substr(0, iSectionStart->fChars);
168 static void GetIndexChars(
const std::list<std::string>& wordsIn, UInt_t numSectionsIn,
169 std::vector<std::string> §ionMarkersOut)
172 Words_t words(wordsIn.size());
174 for (std::list<std::string>::const_iterator iWord = wordsIn.begin(); iWord != wordsIn.end(); ++iWord)
175 words[idx++] = *iWord;
176 GetIndexChars(words, numSectionsIn, sectionMarkersOut);
197 static int CaseInsensitiveSort(
const void *name1,
const void *name2)
199 return (strcasecmp(*((
char **) name1), *((
char **) name2)));
206 static void sort_strlist_stricmp(std::vector<std::string>& l)
213 posList* carr =
new posList[l.size()];
215 for (
size_t iS = 0, iSE = l.size(); iS < iSE; ++iS) {
217 carr[idx++].str = l[iS].c_str();
219 qsort(&carr[0].str, idx,
sizeof(posList), CaseInsensitiveSort);
220 std::vector<std::string> lsort(l.size());
221 for (
size_t iS = 0, iSE = l.size(); iS < iSE; ++iS) {
222 lsort[iS].swap(l[carr[iS].pos]);
251 ClassImp(TDocOutput);
255 TDocOutput::TDocOutput(THtml& html): fHtml(&html)
260 TDocOutput::~TDocOutput()
267 void TDocOutput::AddLink(TSubString& str, TString& link,
const char* comment)
270 if (ReferenceIsRelative(link) && !link.BeginsWith(
"./"))
272 link.Prepend(
"<a href=\"");
274 if (comment && strlen(comment)) {
276 TString description(comment);
277 ReplaceSpecialChars(description);
278 description.ReplaceAll(
"\"",
""");
284 str.String().Insert(str.Start() + str.Length(),
"</a>");
285 str.String().Insert(str.Start(), link);
287 TString &strString = str.String();
288 TSubString update = strString(str.Start(), str.Length() + link.Length() + 4);
296 void TDocOutput::AdjustSourcePath(TString& line,
const char* relpath )
298 TString replWithRelPath(
"=\"@!@");
299 line.ReplaceAll(
"=\"../", replWithRelPath +
"../" + relpath);
300 line.ReplaceAll(
"=\"./", replWithRelPath + relpath);
301 line.ReplaceAll(
"=\"@!@",
"=\"");
310 void TDocOutput::Convert(std::istream& in,
const char* infilename,
311 const char* outfilename,
const char *title,
312 const char *relpath , Int_t includeOutput ,
313 const char* context ,
316 TString htmlFilename(outfilename);
317 htmlFilename +=
".html";
319 std::ofstream out(htmlFilename);
322 Error(
"Convert",
"Can't open file '%s' !", htmlFilename.Data());
327 WriteHtmlHeader(out, title, relpath);
329 if (context && context[0])
330 out << context << std::endl;
331 else if (title && title[0])
332 out <<
"<h1 class=\"convert\">" << title <<
"</h1>" << std::endl;
334 Int_t numReuseCanvases = 0;
335 if (includeOutput && !(includeOutput & THtml::kForceOutput)) {
336 void* dirHandle = gSystem->OpenDirectory(gSystem->DirName(htmlFilename));
338 FileStat_t infile_stat;
339 if (!gSystem->GetPathInfo(infilename, infile_stat)) {
341 const char* outfile = 0;
342 TString firstCanvasFileBase(gSystem->BaseName(outfilename));
343 firstCanvasFileBase +=
"_0.png";
345 Bool_t haveFirstCanvasFile =
false;
346 while ((outfile = gSystem->GetDirEntry(dirHandle))) {
347 if (firstCanvasFileBase == outfile) {
348 haveFirstCanvasFile =
true;
352 gSystem->FreeDirectory(dirHandle);
354 FileStat_t outfile_stat;
355 TString firstCanvasFile = outfilename;
356 firstCanvasFile +=
"_0.png";
358 if (haveFirstCanvasFile && !gSystem->GetPathInfo(firstCanvasFile, outfile_stat)
359 && outfile_stat.fMtime > infile_stat.fMtime) {
362 dirHandle = gSystem->OpenDirectory(gSystem->DirName(htmlFilename));
363 TString stem(gSystem->BaseName(outfilename));
365 TString dir(gSystem->DirName(htmlFilename));
366 while ((outfile = gSystem->GetDirEntry(dirHandle))) {
367 if (strncmp(outfile, stem, stem.Length()))
369 const char* posext = strrchr(outfile,
'.');
370 if (!posext || strcmp(posext,
".png"))
374 if (gSystem->GetPathInfo(dir +
"/" + outfile, outfile_stat))
378 if (outfile_stat.fMtime > infile_stat.fMtime) {
382 TString idxStr(outfile + stem.Length());
383 idxStr.Remove(idxStr.Length() - 4);
384 Int_t idx = idxStr.Atoi();
389 gSystem->FreeDirectory(dirHandle);
390 if (maxIdx + 1 != numReuseCanvases)
393 numReuseCanvases = 0;
399 if (numReuseCanvases)
400 Printf(
"Convert: %s (reusing %d saved canvas%s)", htmlFilename.Data(), numReuseCanvases, (numReuseCanvases > 1 ?
"es" :
""));
402 Printf(
"Convert: %s", htmlFilename.Data());
404 UInt_t nCanvases = numReuseCanvases;
406 if (!numReuseCanvases) {
408 if (includeOutput & THtml::kSeparateProcessOutput) {
409 TString baseInFileName = gSystem->BaseName(infilename);
410 TPMERegexp reOutFile(baseInFileName +
"_[[:digit:]]+\\.png");
413 void* outdirH = gSystem->OpenDirectory(gSystem->DirName(outfilename));
416 const char* outdirE = 0;
417 while ((outdirE = gSystem->GetDirEntry(outdirH))) {
418 if (reOutFile.Match(outdirE)) {
419 gSystem->Unlink(outdirE);
422 gSystem->FreeDirectory(outdirH);
425 gSystem->Exec(TString::Format(
"ROOT_HIST=0 root.exe -l -q %s $ROOTSYS/etc/html/saveScriptOutput.C\\(\\\"%s\\\",\\\"%s\\\",%d\\)",
426 gROOT->IsBatch() ?
"-b" :
"",
428 gSystem->DirName(outfilename),
429 includeOutput & THtml::kCompiledOutput));
432 outdirH = gSystem->OpenDirectory(gSystem->DirName(outfilename));
435 const char* outdirE = 0;
436 while ((outdirE = gSystem->GetDirEntry(outdirH))) {
437 if (reOutFile.Match(outdirE)) {
441 gSystem->FreeDirectory(outdirH);
445 TString pwd(gSystem->pwd());
446 gSystem->cd(gSystem->DirName(infilename));
448 TList* gClientGetListOfWindows = 0;
449 TObject* gClientGetDefaultRoot = 0;
450 std::set<TObject*> previousWindows;
452 gROOT->ProcessLine(TString::Format(
"*((TList**)0x%lx) = ((TGClient*)0x%lx)->GetListOfWindows();",
453 (ULong_t)&gClientGetListOfWindows, (ULong_t)gclient));
454 gROOT->ProcessLine(TString::Format(
"*((TObject**)0x%lx) = ((TGClient*)0x%lx)->GetDefaultRoot();",
455 (ULong_t)&gClientGetDefaultRoot, (ULong_t)gclient));
457 TIter iWin(gClientGetListOfWindows);
458 while((win = iWin())) {
459 TObject* winGetParent = 0;
460 gROOT->ProcessLine(TString::Format(
"*((TObject**)0x%lx) = ((TGWindow*)0x%lx)->GetParent();",
461 (ULong_t)&winGetParent, (ULong_t)win));
462 if (winGetParent == gClientGetDefaultRoot)
463 previousWindows.insert(win);
466 if (gROOT->GetListOfCanvases()->GetSize())
467 previousWindows.insert(gROOT->GetListOfCanvases()->Last());
469 TIter iTimer(gSystem->GetListOfTimers());
470 std::set<TObject*> timersBefore;
471 TObject* timerOld = 0;
472 while ((timerOld = iTimer()))
473 timersBefore.insert(timerOld);
476 cmd += gSystem->BaseName(infilename);
477 if (includeOutput & THtml::kCompiledOutput)
479 gInterpreter->SaveContext();
480 gInterpreter->SaveGlobalsContext();
482 gROOT->ProcessLine(cmd, &err);
483 gSystem->ProcessEvents();
486 if (err == TInterpreter::kNoError) {
488 TClass* clRootCanvas = TClass::GetClass(
"TRootCanvas");
489 TClass* clGMainFrame = TClass::GetClass(
"TGMainFrame");
491 TIter iWin(gClientGetListOfWindows);
492 while((win = iWin())) {
493 TObject* winGetParent = 0;
494 gROOT->ProcessLine(TString::Format(
"*((TObject**)0x%lx) = ((TGWindow*)0x%lx)->GetParent();",
495 (ULong_t)&winGetParent, (ULong_t)win));
496 Bool_t winIsMapped = kFALSE;
497 if (winGetParent == gClientGetDefaultRoot)
498 gROOT->ProcessLine(TString::Format(
"*((Bool_t*)0x%lx) = ((TGWindow*)0x%lx)->IsMapped();",
499 (ULong_t)&winIsMapped, (ULong_t)win));
500 if (winIsMapped && previousWindows.find(win) == previousWindows.end()
501 && win->InheritsFrom(clGMainFrame)) {
502 gROOT->ProcessLine(TString::Format(
"((TGWindow*)0x%lx)->MapRaised();", (ULong_t)win));
503 Bool_t isRootCanvas = win->InheritsFrom(clRootCanvas);
504 Bool_t hasEditor =
false;
506 gROOT->ProcessLine(TString::Format(
"*((Bool_t*)0x%lx) = ((TRootCanvas*)0x%lx)->HasEditor();",
507 (ULong_t)&hasEditor, (ULong_t)win));
509 if (isRootCanvas && !hasEditor) {
510 TVirtualPad* pad = 0;
511 gROOT->ProcessLine(TString::Format(
"*((TVirtualPad**)0x%lx) = ((TRootCanvas*)0x%lx)->Canvas();",
512 (ULong_t)&pad, (ULong_t)win));
513 if (!pad->HasViewer3D() || pad->GetViewer3D()->InheritsFrom(
"TViewer3DPad")) {
514 pad->SaveAs(TString::Format(
"%s_%d.png", outfilename, nCanvases++));
517 gROOT->ProcessLine(TString::Format(
"((TGWindow*)0x%lx)->SaveAs(\"%s_%d.png\");",
518 (ULong_t)win, outfilename, nCanvases++));
523 TVirtualPad* pad = 0;
524 TVirtualPad* last = 0;
525 if (!previousWindows.empty())
526 last = (TVirtualPad*) *previousWindows.begin();
527 TIter iCanvas(gROOT->GetListOfCanvases());
528 while ((pad = (TVirtualPad*) iCanvas())) {
530 if (last == pad) last = 0;
533 pad->SaveAs(TString::Format(
"%s_%d.png", outfilename, nCanvases++));
536 gInterpreter->Reset();
537 gInterpreter->ResetGlobals();
538 TIter iTimerRemove(gSystem->GetListOfTimers());
540 while ((timer = (TTimer*) iTimerRemove()))
541 if (timersBefore.find(timer) == timersBefore.end())
542 gSystem->RemoveTimer(timer);
546 out <<
"<table><tr><td style=\"vertical-align:top;padding-right:2em;\">" << std::endl;
548 out <<
"<div class=\"listing\"><pre class=\"listing\">" << std::endl;
550 TDocParser parser(*
this);
551 parser.Convert(out, in, relpath, (includeOutput) ,
554 out <<
"</pre></div>" << std::endl;
556 WriteLineNumbers(out, parser.GetLineNumber(), gSystem->BaseName(infilename));
559 out <<
"</td><td style=\"vertical-align:top;\">" << std::endl;
560 out <<
"<table>" << std::endl;
561 for (UInt_t i = 0; i < nCanvases; ++i) {
562 TString pngname = TString::Format(
"%s_%d.png", gSystem->BaseName(outfilename), i);
563 out <<
"<tr><td><a href=\"" << pngname <<
"\">" << std::endl
564 <<
"<img src=\"" << pngname <<
"\" id=\"canv" << i <<
"\" alt=\"thumb\" style=\"border:none;width:22em;\" "
565 "onmouseover=\"javascript:canv" << i <<
".style.width='auto';\" />" << std::endl
566 <<
"</a></td></tr>" << std::endl;
568 out <<
"</table>" << std::endl;
569 out <<
"</td></tr></table>" << std::endl;
573 WriteHtmlFooter(out, relpath);
592 Bool_t TDocOutput::CopyHtmlFile(
const char *sourceName,
const char *destName)
594 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
596 TString sourceFile(sourceName);
598 if (!sourceFile.Length()) {
599 Error(
"Copy",
"Can't copy file '%s' to '%s' directory - source file name invalid!", sourceName,
600 fHtml->GetOutputDir().Data());
606 if (!destName || !*destName)
607 destFile = gSystem->BaseName(sourceFile);
609 destFile = gSystem->BaseName(destName);
611 gSystem->PrependPathName(fHtml->GetOutputDir(), destFile);
615 Long_t id, flags, sModtime, dModtime;
618 if (gSystem->GetPathInfo(sourceFile, &
id, &size, &flags, &sModtime)
619 || gSystem->GetPathInfo(destFile, &
id, &size, &flags, &dModtime)
620 || sModtime > dModtime)
621 if (gSystem->CopyFile(sourceFile, destFile, kTRUE) < 0) {
622 Error(
"Copy",
"Can't copy file '%s' to '%s'!",
623 sourceFile.Data(), destFile.Data());
639 void TDocOutput::CreateHierarchy()
643 TString filename(
"ClassHierarchy.html");
644 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
647 std::ofstream out(filename);
650 Error(
"CreateHierarchy",
"Can't open file '%s' !", filename.Data());
654 Printf(fHtml->GetCounterFormat(),
"", fHtml->GetCounter(), filename.Data());
657 WriteHtmlHeader(out,
"Class Hierarchy");
659 WriteTopLinks(out, 0);
661 out <<
"<h1>Class Hierarchy</h1>" << std::endl;
665 TClassDocInfo* cdi = 0;
666 TIter iClass(fHtml->GetListOfClasses());
667 while ((cdi = (TClassDocInfo*)iClass())) {
668 if (!cdi->HaveSource())
672 TDictionary *dictPtr = cdi->GetClass();
673 TClass *basePtr =
dynamic_cast<TClass*
>(dictPtr);
676 Warning(
"THtml::CreateHierarchy",
"skipping class %s\n", cdi->GetName());
680 TClassDocOutput cdo(*fHtml, basePtr, 0);
681 cdo.CreateClassHierarchy(out, cdi->GetHtmlFileName());
685 WriteHtmlFooter(out);
692 void TDocOutput::CreateClassIndex()
695 fHtml->CreateAuxiliaryFiles();
697 TString filename(
"ClassIndex.html");
698 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
701 std::ofstream indexFile(filename.Data());
703 if (!indexFile.good()) {
704 Error(
"CreateClassIndex",
"Can't open file '%s' !", filename.Data());
708 Printf(fHtml->GetCounterFormat(),
"", fHtml->GetCounter(), filename.Data());
711 WriteHtmlHeader(indexFile,
"Class Index");
713 WriteTopLinks(indexFile, 0);
715 indexFile <<
"<h1>Class Index</h1>" << std::endl;
717 WriteModuleLinks(indexFile);
719 std::vector<std::string> indexChars;
720 if (fHtml->GetListOfClasses()->GetSize() > 10) {
721 std::vector<std::string> classNames;
723 TIter iClass(fHtml->GetListOfClasses());
724 TClassDocInfo* cdi = 0;
725 while ((cdi = (TClassDocInfo*)iClass()))
726 if (cdi->IsSelected() && cdi->HaveSource())
727 classNames.push_back(cdi->GetName());
730 if (classNames.size() > 10) {
731 indexFile <<
"<div id=\"indxShortX\"><h4>Jump to</h4>" << std::endl;
733 GetIndexChars(classNames, 50 , indexChars);
734 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
735 indexFile <<
"<a href=\"#idx" << iIdxEntry <<
"\">";
736 ReplaceSpecialChars(indexFile, indexChars[iIdxEntry].c_str());
737 indexFile <<
"</a>" << std::endl;
739 indexFile <<
"</div><br />" << std::endl;
743 indexFile <<
"<ul id=\"indx\">" << std::endl;
746 UInt_t currentIndexEntry = 0;
747 TIter iClass(fHtml->GetListOfClasses());
748 TClassDocInfo* cdi = 0;
750 while ((cdi = (TClassDocInfo*)iClass())) {
751 if (!cdi->IsSelected() || !cdi->HaveSource())
755 TDictionary *currentDict = cdi->GetClass();
756 TClass* currentClass =
dynamic_cast<TClass*
>(currentDict);
759 Warning(
"THtml::CreateClassIndex",
"skipping class %s\n", cdi->GetName());
763 indexFile <<
"<li class=\"idxl" << (i++)%2 <<
"\">";
764 if (currentIndexEntry < indexChars.size()
765 && !strncmp(indexChars[currentIndexEntry].c_str(), cdi->GetName(),
766 indexChars[currentIndexEntry].length()))
767 indexFile <<
"<a name=\"idx" << currentIndexEntry++ <<
"\"></a>";
769 TString htmlFile(cdi->GetHtmlFileName());
770 if (htmlFile.Length()) {
771 indexFile <<
"<a href=\"";
772 indexFile << htmlFile;
773 indexFile <<
"\"><span class=\"typename\">";
774 ReplaceSpecialChars(indexFile, cdi->GetName());
775 indexFile <<
"</span></a> ";
777 indexFile <<
"<span class=\"typename\">";
778 ReplaceSpecialChars(indexFile, cdi->GetName());
779 indexFile <<
"</span> ";
783 ReplaceSpecialChars(indexFile, currentClass->GetTitle());
784 indexFile <<
"</li>" << std::endl;
787 indexFile <<
"</ul>" << std::endl;
790 WriteHtmlFooter(indexFile);
800 void TDocOutput::CreateModuleIndex()
802 const char* title =
"LibraryDependencies";
803 TString dotfilename(title);
804 gSystem->PrependPathName(fHtml->GetOutputDir(), dotfilename);
806 std::ofstream libDepDotFile(dotfilename +
".dot");
807 libDepDotFile <<
"digraph G {" << std::endl
808 <<
"ratio=compress;" << std::endl
809 <<
"node [fontsize=22,labeldistance=0.1];" << std::endl
810 <<
"edge [len=0.01];" << std::endl
811 <<
"fontsize=22;" << std::endl
812 <<
"size=\"16,16\";" << std::endl
813 <<
"overlap=false;" << std::endl
814 <<
"splines=true;" << std::endl
815 <<
"K=0.1;" << std::endl;
817 TModuleDocInfo* module = 0;
818 TIter iterModule(fHtml->GetListOfModules());
820 std::stringstream sstrCluster;
821 std::stringstream sstrDeps;
822 while ((module = (TModuleDocInfo*)iterModule())) {
823 if (!module->IsSelected())
826 std::vector<std::string> indexChars;
827 TString filename(module->GetName());
829 filename.ReplaceAll(
"/",
"_");
830 filename +=
"_Index.html";
831 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
832 std::ofstream outputFile(filename.Data());
833 if (!outputFile.good()) {
834 Error(
"CreateModuleIndex",
"Can't open file '%s' !", filename.Data());
837 Printf(fHtml->GetCounterFormat(),
"", fHtml->GetCounter(), filename.Data());
839 TString htmltitle(
"Index of ");
840 TString moduletitle(module->GetName());
841 moduletitle.ToUpper();
842 htmltitle += moduletitle;
843 WriteHtmlHeader(outputFile, htmltitle);
845 WriteTopLinks(outputFile, module);
847 outputFile <<
"<h2>" << htmltitle <<
"</h2>" << std::endl;
850 if (GetHtml()->GetModuleDocPath().Length()) {
851 TString outdir(module->GetName());
852 gSystem->PrependPathName(GetHtml()->GetOutputDir(), outdir);
854 TString moduleDocDir;
855 GetHtml()->GetPathDefinition().GetDocDir(module->GetName(), moduleDocDir);
856 ProcessDocInDir(outputFile, moduleDocDir, outdir, module->GetName());
859 WriteModuleLinks(outputFile, module);
861 std::list<std::string> classNames;
863 TIter iClass(module->GetClasses());
864 TClassDocInfo* cdi = 0;
865 while ((cdi = (TClassDocInfo*) iClass())) {
866 if (!cdi->IsSelected() || !cdi->HaveSource())
868 classNames.push_back(cdi->GetName());
870 if (classNames.size() > 1)
continue;
872 TClass* cdiClass =
dynamic_cast<TClass*
>(cdi->GetClass());
876 TString libs(cdiClass->GetSharedLibs());
877 Ssiz_t posDepLibs = libs.Index(
' ');
878 TString thisLib(libs);
879 if (posDepLibs != kNPOS)
880 thisLib.Remove(posDepLibs, thisLib.Length());
883 Ssiz_t posExt = thisLib.First(
'.');
885 thisLib.Remove(posExt, thisLib.Length());
888 if (!thisLib.Length())
892 TLibraryDocInfo *libdeps =
893 (TLibraryDocInfo*)fHtml->GetLibraryDependencies()->FindObject(thisLib);
895 libdeps =
new TLibraryDocInfo(thisLib);
896 fHtml->GetLibraryDependencies()->Add(libdeps);
898 libdeps->AddModule(module->GetName());
899 if (posDepLibs != kNPOS) {
901 for(Ssiz_t pos = posDepLibs + 1; libs[pos]; ++pos) {
902 if (libs[pos] ==
' ') {
903 if (thisLib.Length() && lib.length()) {
904 size_t posExt = lib.find(
'.');
905 if (posExt != std::string::npos)
907 libdeps->AddDependency(lib);
913 if (lib.length() && thisLib.Length()) {
914 size_t posExt = lib.find(
'.');
915 if (posExt != std::string::npos)
917 libdeps->AddDependency(lib);
923 TIter iClass(module->GetClasses());
924 TClassDocInfo* cdi = 0;
926 UInt_t currentIndexEntry = 0;
927 while ((cdi = (TClassDocInfo*) iClass())) {
928 if (!cdi->IsSelected() || !cdi->HaveSource())
931 TDictionary *classPtr = cdi->GetClass();
933 Error(
"CreateModuleIndex",
"Unknown class '%s' !", cdi->GetName());
938 outputFile <<
"<h2>Class Index</h2>" << std::endl;
940 if (classNames.size() > 10) {
941 outputFile <<
"<div id=\"indxShortX\"><h4>Jump to</h4>" << std::endl;
942 UInt_t numSections = classNames.size() / 10;
943 if (numSections < 10) numSections = 10;
944 if (numSections > 50) numSections = 50;
946 GetIndexChars(classNames, numSections, indexChars);
947 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
948 outputFile <<
"<a href=\"#idx" << iIdxEntry <<
"\">";
949 ReplaceSpecialChars(outputFile, indexChars[iIdxEntry].c_str());
950 outputFile <<
"</a>" << std::endl;
952 outputFile <<
"</div><br />" << std::endl;
955 outputFile <<
"<ul id=\"indx\">" << std::endl;
959 outputFile <<
"<li class=\"idxl" << (count++)%2 <<
"\">";
960 if (currentIndexEntry < indexChars.size()
961 && !strncmp(indexChars[currentIndexEntry].c_str(), cdi->GetName(),
962 indexChars[currentIndexEntry].length()))
963 outputFile <<
"<a name=\"idx" << currentIndexEntry++ <<
"\"></a>";
965 TString htmlFile(cdi->GetHtmlFileName());
966 if (htmlFile.Length()) {
967 outputFile <<
"<a href=\"";
968 outputFile << htmlFile;
969 outputFile <<
"\"><span class=\"typename\">";
970 ReplaceSpecialChars(outputFile, classPtr->GetName());
971 outputFile <<
"</span></a> ";
973 outputFile <<
"<span class=\"typename\">";
974 ReplaceSpecialChars(outputFile, classPtr->GetName());
975 outputFile <<
"</span> ";
979 ReplaceSpecialChars(outputFile, classPtr->GetTitle());
980 outputFile <<
"</li>" << std::endl;
985 outputFile <<
"</ul>" << std::endl;
988 WriteHtmlFooter(outputFile);
1006 TIter iLib(fHtml->GetLibraryDependencies());
1007 TLibraryDocInfo* libinfo = 0;
1008 while ((libinfo = (TLibraryDocInfo*)iLib())) {
1009 if (!libinfo->GetName() || !libinfo->GetName()[0])
continue;
1011 std::set<std::string>& deps = libinfo->GetDependencies();
1012 for (std::set<std::string>::iterator iDep = deps.begin();
1013 iDep != deps.end(); ) {
1014 Bool_t already_indirect = kFALSE;
1015 for (std::set<std::string>::const_iterator iDep2 = deps.begin();
1016 !already_indirect && iDep2 != deps.end(); ++iDep2) {
1017 if (iDep == iDep2)
continue;
1018 TLibraryDocInfo* libinfo2 = (TLibraryDocInfo*)
1019 fHtml->GetLibraryDependencies()->FindObject(iDep2->c_str());
1020 if (!libinfo2)
continue;
1021 const std::set<std::string>& deps2 = libinfo2->GetDependencies();
1022 already_indirect |= deps2.find(*iDep) != deps2.end();
1024 if (already_indirect) {
1025 std::set<std::string>::iterator iRemove = iDep;
1028 deps.erase(iRemove);
1036 while ((libinfo = (TLibraryDocInfo*)iLib())) {
1037 if (!libinfo->GetName() || !libinfo->GetName()[0])
continue;
1039 const std::set<std::string>& modules = libinfo->GetModules();
1040 if (modules.size() > 1) {
1041 sstrCluster <<
"subgraph cluster" << libinfo->GetName() <<
" {" << std::endl
1042 <<
"style=filled;" << std::endl
1043 <<
"color=lightgray;" << std::endl
1045 if (!strcmp(libinfo->GetName(),
"libCore"))
1046 sstrCluster <<
"Everything depends on ";
1047 sstrCluster << libinfo->GetName() <<
"\";" << std::endl;
1049 for (std::set<std::string>::const_iterator iModule = modules.begin();
1050 iModule != modules.end(); ++iModule) {
1051 TString modURL(*iModule);
1052 modURL.ReplaceAll(
"/",
"_");
1054 sstrCluster <<
"\"" << *iModule <<
"\" [style=filled,color=white,URL=\""
1055 << modURL <<
"_Index.html\"];" << std::endl;
1057 sstrCluster << std::endl
1058 <<
"}" << std::endl;
1061 TString modURL(*modules.begin());
1062 modURL.ReplaceAll(
"/",
"_");
1064 sstrCluster <<
"\"" << *modules.begin()
1065 <<
"\" [label=\"" << libinfo->GetName()
1066 <<
"\",style=filled,color=lightgray,shape=box,URL=\""
1067 << modURL <<
"_Index.html\"];" << std::endl;
1077 const std::string& mod = *(modules.begin());
1078 const std::set<std::string>& deps = libinfo->GetDependencies();
1079 for (std::set<std::string>::const_iterator iDep = deps.begin();
1080 iDep != deps.end(); ++iDep) {
1082 TLibraryDocInfo* depLibInfo = (TLibraryDocInfo*)
1083 fHtml->GetLibraryDependencies()->FindObject(iDep->c_str());
1084 if (!depLibInfo || depLibInfo->GetModules().empty())
1087 const std::string& moddep = *(depLibInfo->GetModules().begin());
1088 sstrDeps <<
"\"" << mod <<
"\" -> \"" << moddep <<
"\";" << std::endl;
1091 sstrDeps <<
"\"" << mod <<
"\" -> \"CONT\" [style=invis];" << std::endl;
1094 libDepDotFile << sstrCluster.str() << std::endl
1096 libDepDotFile <<
"}" << std::endl;
1097 libDepDotFile.close();
1099 std::ofstream out(dotfilename +
".html");
1101 Error(
"CreateModuleIndex",
"Can't open file '%s.html' !",
1102 dotfilename.Data());
1106 Printf(fHtml->GetCounterFormat(),
"", fHtml->GetCounter(), (dotfilename +
".html").Data());
1108 WriteHtmlHeader(out,
"Library Dependencies");
1110 WriteTopLinks(out, 0);
1112 out <<
"<h1>Library Dependencies</h1>" << std::endl;
1114 RunDot(dotfilename, &out, kFdp);
1116 out <<
"<img alt=\"Library Dependencies\" class=\"classcharts\" usemap=\"#Map" << title <<
"\" src=\"" << title <<
".png\"/>" << std::endl;
1119 WriteHtmlFooter(out);
1126 void TDocOutput::CreateProductIndex()
1130 TString outFile(
"index.html");
1131 gSystem->PrependPathName(GetHtml()->GetOutputDir(), outFile);
1132 std::ofstream out(outFile);
1135 Error(
"CreateProductIndex",
"Can't open file '%s' !", outFile.Data());
1139 Printf(fHtml->GetCounterFormat(),
"",
"", outFile.Data());
1141 WriteHtmlHeader(out, GetHtml()->GetProductName() +
" Reference Guide");
1143 WriteTopLinks(out, 0);
1145 out <<
"<h1>" << GetHtml()->GetProductName() +
" Reference Guide</h1>" << std::endl;
1148 if (GetHtml()->GetPathDefinition().GetDocDir(
"", prodDoc))
1149 ProcessDocInDir(out, prodDoc, GetHtml()->GetOutputDir(),
"./");
1151 WriteModuleLinks(out);
1153 out <<
"<h2>Chapters</h2>" << std::endl
1154 <<
"<h3><a href=\"./ClassIndex.html\">Class Index</a></h3>" << std::endl
1155 <<
"<p>A complete list of all classes defined in " << GetHtml()->GetProductName() <<
"</p>" << std::endl
1156 <<
"<h3><a href=\"./ClassHierarchy.html\">Class Hierarchy</a></h3>" << std::endl
1157 <<
"<p>A hierarchy graph of all classes, showing each class's base and derived classes</p>" << std::endl
1158 <<
"<h3><a href=\"./ListOfTypes.html\">Type Index</a></h3>" << std::endl
1159 <<
"<p>A complete list of all types</p>" << std::endl
1160 <<
"<h3><a href=\"./LibraryDependencies.html\">Library Dependency</a></h3>" << std::endl
1161 <<
"<p>A diagram showing all of " << GetHtml()->GetProductName() <<
"'s libraries and their dependencies</p>" << std::endl;
1163 WriteHtmlFooter(out);
1169 void TDocOutput::CreateClassTypeDefs()
1171 TDocParser parser(*
this);
1173 TIter iClass(GetHtml()->GetListOfClasses());
1174 TClassDocInfo* cdi = 0;
1175 while ((cdi = (TClassDocInfo*) iClass())) {
1176 if (cdi->GetListOfTypedefs().IsEmpty())
1178 TIter iTypedefs(&cdi->GetListOfTypedefs());
1180 while ((dt = (TDataType*) iTypedefs())) {
1182 Info(
"CreateClassTypeDefs",
"Creating typedef %s to class %s",
1183 dt->GetName(), cdi->GetName());
1185 TString filename(dt->GetName());
1186 NameSpace2FileName(filename);
1188 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
1190 filename +=
".html";
1193 std::ofstream outfile(filename);
1195 if (!outfile.good()) {
1196 Error(
"CreateClassTypeDefs",
"Can't open file '%s' !", filename.Data());
1200 WriteHtmlHeader(outfile, dt->GetName());
1202 outfile <<
"<a name=\"TopOfPage\"></a>" << std::endl;
1204 TString dtName(dt->GetName());
1205 ReplaceSpecialChars(dtName);
1206 TString sTitle(
"typedef ");
1209 TClass* cls =
dynamic_cast<TClass*
>(cdi->GetClass());
1215 const char* lib=cls->GetSharedLibs();
1216 GetHtml()->GetPathDefinition().GetIncludeAs(cls, sInclude);
1218 char* libDup=StrDup(lib);
1219 char* libDupSpace=strchr(libDup,
' ');
1220 if (libDupSpace) *libDupSpace = 0;
1221 char* libDupEnd=libDup+strlen(libDup);
1222 while (libDupEnd!=libDup)
1223 if (*(--libDupEnd)==
'.') {
1230 outfile <<
"<script type=\"text/javascript\">WriteFollowPageBox('"
1231 << sTitle <<
"','" << sLib <<
"','" << sInclude <<
"');</script>" << std::endl;
1235 fHtml->GetModuleNameForClass(modulename, cls);
1236 TModuleDocInfo* module = (TModuleDocInfo*) fHtml->GetListOfModules()->FindObject(modulename);
1237 WriteTopLinks(outfile, module, dt->GetName());
1239 outfile <<
"<div class=\"dropshadow\"><div class=\"withshadow\">";
1240 outfile <<
"<h1>" << sTitle <<
"</h1>" << std::endl
1241 <<
"<div class=\"classdescr\">" << std::endl;
1243 outfile << dtName <<
" is a typedef to ";
1244 std::string shortClsName(fHtml->ShortType(cdi->GetName()));
1245 parser.DecorateKeywords(outfile, shortClsName.c_str());
1246 outfile << std::endl
1247 <<
"</div>" << std::endl
1248 <<
"</div></div><div style=\"clear:both;\"></div>" << std::endl;
1251 outfile << std::endl <<
"<div id=\"datamembers\">" << std::endl
1252 <<
"<table class=\"data\" cellspacing=\"0\">" << std::endl;
1253 outfile <<
"<tr class=\"data";
1254 outfile <<
"\"><td class=\"datatype\">typedef ";
1255 parser.DecorateKeywords(outfile, dt->GetFullTypeName());
1256 outfile <<
"</td><td class=\"dataname\">";
1257 ReplaceSpecialChars(outfile, dt->GetName());
1258 if (dt->GetTitle() && dt->GetTitle()[0]) {
1259 outfile <<
"</td><td class=\"datadesc\">";
1260 ReplaceSpecialChars(outfile, dt->GetTitle());
1261 }
else outfile <<
"</td><td>";
1262 outfile <<
"</td></tr>" << std::endl
1263 <<
"</table></div>" << std::endl;
1266 WriteHtmlFooter(outfile);
1275 void TDocOutput::CreateTypeIndex()
1278 TString outFile(
"ListOfTypes.html");
1279 gSystem->PrependPathName(fHtml->GetOutputDir(), outFile);
1280 std::ofstream typesList(outFile);
1282 if (!typesList.good()) {
1283 Error(
"CreateTypeIndex",
"Can't open file '%s' !", outFile.Data());
1287 Printf(fHtml->GetCounterFormat(),
"",
"", outFile.Data());
1290 WriteHtmlHeader(typesList,
"List of data types");
1291 typesList <<
"<h2> List of data types </h2>" << std::endl;
1293 typesList <<
"<dl><dd>" << std::endl;
1296 std::vector<std::string> typeNames(gROOT->GetListOfTypes()->GetSize());
1300 TIter nextType(gROOT->GetListOfTypes());
1303 while ((type = (TDataType *) nextType()))
1305 if (*type->GetTitle() && !strchr(type->GetName(),
'(')
1306 && !( strchr(type->GetName(),
'<') && strchr(type->GetName(),
'>'))
1308 typeNames[tnIdx++] = type->GetName();
1309 typeNames.resize(tnIdx);
1312 sort_strlist_stricmp(typeNames);
1314 std::vector<std::string> indexChars;
1315 if (typeNames.size() > 10) {
1316 typesList <<
"<div id=\"indxShortX\"><h4>Jump to</h4>" << std::endl;
1318 GetIndexChars(typeNames, 10 , indexChars);
1319 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
1320 typesList <<
"<a href=\"#idx" << iIdxEntry <<
"\">";
1321 ReplaceSpecialChars(typesList, indexChars[iIdxEntry].c_str());
1322 typesList <<
"</a>" << std::endl;
1324 typesList <<
"</div><br />" << std::endl;
1327 typesList <<
"<ul id=\"indx\">" << std::endl;
1330 UInt_t currentIndexEntry = 0;
1332 for (std::vector<std::string>::iterator iTypeName = typeNames.begin();
1333 iTypeName != typeNames.end(); ++iTypeName) {
1334 TDataType* type = gROOT->GetType(iTypeName->c_str(), kFALSE);
1335 typesList <<
"<li class=\"idxl" << idx%2 <<
"\">";
1336 if (currentIndexEntry < indexChars.size()
1337 && !strncmp(indexChars[currentIndexEntry].c_str(), iTypeName->c_str(),
1338 indexChars[currentIndexEntry].length()))
1339 typesList <<
"<a name=\"idx" << currentIndexEntry++ <<
"\"></a>" << std::endl;
1340 typesList <<
"<a name=\"";
1341 ReplaceSpecialChars(typesList, iTypeName->c_str());
1342 typesList <<
"\"><span class=\"typename\">";
1343 ReplaceSpecialChars(typesList, iTypeName->c_str());
1344 typesList <<
"</span></a> ";
1345 ReplaceSpecialChars(typesList, type->GetTitle());
1346 typesList <<
"</li>" << std::endl;
1349 typesList <<
"</ul>" << std::endl;
1352 WriteHtmlFooter(typesList);
1367 void TDocOutput::DecorateEntityBegin(TString& str, Ssiz_t& pos, TDocParser::EParseContext type)
1369 Ssiz_t originalLen = str.Length();
1372 case TDocParser::kCode:
break;
1373 case TDocParser::kComment:
1374 str.Insert(pos,
"<span class=\"comment\">");
1376 case TDocParser::kDirective:
1378 case TDocParser::kString:
1379 str.Insert(pos,
"<span class=\"string\">");
1381 case TDocParser::kKeyword:
1382 str.Insert(pos,
"<span class=\"keyword\">");
1384 case TDocParser::kCPP:
1385 str.Insert(pos,
"<span class=\"cpp\">");
1387 case TDocParser::kVerbatim:
1388 str.Insert(pos,
"<pre>");
1391 Error(
"DecorateEntityBegin",
"Unhandled / invalid entity type %d!", (Int_t)type);
1395 Ssiz_t addedLen = str.Length() - originalLen;
1407 void TDocOutput::DecorateEntityEnd(TString& str, Ssiz_t& pos, TDocParser::EParseContext type)
1409 Ssiz_t originalLen = str.Length();
1412 case TDocParser::kCode:
break;
1413 case TDocParser::kComment:
1414 str.Insert(pos,
"</span>");
1416 case TDocParser::kDirective:
1418 case TDocParser::kString:
1419 str.Insert(pos,
"</span>");
1421 case TDocParser::kKeyword:
1422 str.Insert(pos,
"</span>");
1424 case TDocParser::kCPP:
1425 str.Insert(pos,
"</span>");
1427 case TDocParser::kVerbatim:
1428 str.Insert(pos,
"</pre>");
1431 Error(
"DecorateEntityBegin",
"Unhandled / invalid entity type %d!", (Int_t)type);
1434 Ssiz_t addedLen = str.Length() - originalLen;
1448 void TDocOutput::FixupAuthorSourceInfo(TString& authors)
1450 TString original(authors);
1455 Bool_t firstAuthor = kTRUE;
1456 while (original.Tokenize(author, pos,
",")) {
1457 author.Strip(TString::kBoth);
1461 firstAuthor = kFALSE;
1464 Ssiz_t cLink = author.First(
'<');
1465 if (cLink != kNPOS) {
1468 Ssiz_t endLink = author.Index(
">", cLink + 1);
1469 if(endLink == kNPOS)
1470 endLink = author.Length();
1471 authors +=
"<a href=\"";
1472 authors += author(cLink + 1, endLink - (cLink + 1));
1474 authors += author(0, cLink);
1476 if (endLink != author.Length())
1477 authors += author(endLink + 1, author.Length());
1479 authors +=
"<a href=\"";
1480 authors += fHtml->GetXwho();
1484 Ssiz_t posNamePart = 0;
1485 Bool_t firstNamePart = kTRUE;
1486 while (author.Tokenize(namePart, posNamePart,
" ")) {
1487 namePart.Strip(TString::kBoth);
1488 if (!namePart.Length())
1490 if (isdigit(namePart[0]))
continue;
1493 firstNamePart = kFALSE;
1494 authors += namePart;
1515 Bool_t TDocOutput::IsModified(TClass * classPtr, EFileType type)
1518 TString classname(classPtr->GetName());
1526 if (classPtr->GetImplFileLine()) {
1527 fHtml->GetImplFileName(classPtr, kTRUE, sourceFile);
1529 fHtml->GetDeclFileName(classPtr, kTRUE, declFile);
1531 Long_t id, flags, iModtime, dModtime;
1532 if (!(gSystem->GetPathInfo(sourceFile, &
id, &size, &flags, &iModtime))) {
1533 if (!(gSystem->GetPathInfo(declFile, &
id, &size, &flags, &dModtime))) {
1534 if (iModtime < dModtime) {
1536 sourceFile = declFile;
1541 gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
1542 filename = classname;
1543 NameSpace2FileName(filename);
1544 gSystem->PrependPathName(dir, filename);
1545 if (classPtr->GetImplFileLine())
1546 filename +=
".cxx.html";
1548 filename +=
".h.html";
1553 fHtml->GetDeclFileName(classPtr, kFALSE, filename);
1554 filename = gSystem->BaseName(filename);
1555 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
1556 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
1560 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
1561 NameSpace2FileName(classname);
1562 gSystem->PrependPathName(fHtml->GetOutputDir(), classname);
1563 filename = classname;
1564 filename +=
"_Tree.pdf";
1570 if (classPtr->GetImplFileLine()) {
1571 fHtml->GetImplFileName(classPtr, kTRUE, sourceFile);
1573 fHtml->GetDeclFileName(classPtr, kTRUE, declFile);
1575 Long_t id, flags, iModtime, dModtime;
1576 if (!(gSystem->GetPathInfo(sourceFile, &
id, &size, &flags, &iModtime))) {
1577 if (!(gSystem->GetPathInfo(declFile, &
id, &size, &flags, &dModtime))) {
1578 if (iModtime < dModtime) {
1580 sourceFile = declFile;
1584 filename = classname;
1585 NameSpace2FileName(filename);
1586 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
1587 filename +=
".html";
1592 Error(
"IsModified",
"Unknown file type !");
1595 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1599 Long_t id, flags, sModtime, dModtime;
1601 if (!(gSystem->GetPathInfo(sourceFile, &
id, &size, &flags, &sModtime))) {
1602 if (!(gSystem->GetPathInfo(filename, &
id, &size, &flags, &dModtime))) {
1603 return (sModtime > dModtime);
1617 void TDocOutput::NameSpace2FileName(TString& name)
1619 TString encScope(name);
1620 Ssiz_t posTemplate = encScope.Index(
'<');
1621 if (posTemplate != kNPOS) {
1623 name = fHtml->ShortType(name);
1624 TString templateArgs = encScope(posTemplate, encScope.Length());
1625 encScope.Remove(posTemplate, encScope.Length());
1631 Ssiz_t posName = encScope.Last(
':');
1632 if (posName != kNPOS) {
1633 Int_t numDblColumn = encScope.CountChar(
':');
1634 while (numDblColumn > 1) {
1635 encScope.Remove(posName + 1, encScope.Length());
1637 templateArgs.ReplaceAll(encScope, TString::Format(
"-p%d", numDblColumn / 2));
1638 encScope.Remove(encScope.Length() - 2, 2);
1639 posName = encScope.Last(
':');
1640 if (posName == kNPOS)
1643 name.Replace(posTemplate, name.Length(), templateArgs);
1647 if (name.Length() > 240) {
1653 TDocParser::AnchorFromLine(name, hash);
1655 Ssiz_t posDot = name.Last(
'.');
1657 if (posDot != kNPOS)
1658 ext = name(posDot, name.Length());
1659 Ssiz_t namelen = 240 - hash.Length() - ext.Length();
1660 name = name(0, namelen) + hash + ext;
1663 const char* replaceWhat =
":<> ,~=";
1664 for (Ssiz_t i=0; i < name.Length(); ++i)
1665 if (strchr(replaceWhat, name[i]))
1676 void TDocOutput::ProcessDocInDir(std::ostream& out,
const char* indir,
1677 const char* outdir,
const char* linkdir)
1679 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
1681 void * dirHandle = gSystem->OpenDirectory(indir);
1682 if (!dirHandle)
return;
1684 const char* entry = 0;
1685 std::list<std::string> files;
1686 while ((entry = gSystem->GetDirEntry(dirHandle))) {
1688 TString filename(entry);
1689 gSystem->PrependPathName(indir, filename);
1690 if (gSystem->GetPathInfo(filename, stat))
1692 if (!R_ISREG(stat.fMode))
continue;
1694 if (TString(entry).BeginsWith(
"index.", TString::kIgnoreCase)) {
1697 if (filename.EndsWith(
".txt", TString::kIgnoreCase)) {
1698 std::ifstream in(filename);
1701 TDocParser parser(*
this);
1702 parser.Convert(out, in,
"./", kFALSE , kTRUE );
1705 }
else if (filename.EndsWith(
".html", TString::kIgnoreCase)) {
1706 std::ifstream in(filename);
1709 if (!line.ReadLine(in))
break;
1710 out << line << std::endl;
1713 files.push_back(filename.Data());
1715 files.push_back(filename.Data());
1718 std::stringstream furtherReading;
1720 for (std::list<std::string>::const_iterator iFile = files.begin();
1721 iFile != files.end(); ++iFile) {
1722 TString filename(iFile->c_str());
1723 if (gSystem->AccessPathName(outdir))
1724 if (gSystem->mkdir(outdir, kTRUE) == -1)
1726 Error(
"CreateModuleIndex",
"Cannot create output directory %s", outdir);
1728 TString outfile(gSystem->BaseName(filename));
1729 gSystem->PrependPathName(outdir, outfile);
1731 if (!filename.EndsWith(
".txt", TString::kIgnoreCase)
1732 && !filename.EndsWith(
".html", TString::kIgnoreCase)) {
1734 if (gSystem->CopyFile(filename, outfile, kTRUE) == -1) {
1735 Error(
"CreateModuleIndex",
"Cannot copy file %s to %s",
1736 filename.Data(), outfile.Data());
1743 if (outfile.EndsWith(
".txt", TString::kIgnoreCase)) {
1745 outfile.Remove(outfile.Length()-3, 3);
1747 std::ifstream inFurther(filename);
1748 std::ofstream outFurther(outfile);
1749 if (inFurther && outFurther) {
1750 outFurther <<
"<pre>";
1751 TDocParser parser(*
this);
1752 parser.Convert(outFurther, inFurther,
"../", kFALSE , kTRUE );
1753 outFurther <<
"</pre>";
1756 if (gSystem->CopyFile(filename, outfile, kTRUE) == -1)
1759 TString showname(gSystem->BaseName(outfile));
1760 furtherReading <<
"<a class=\"linkeddoc\" href=\"" << linkdir <<
"/" << showname <<
"\">";
1761 showname.Remove(showname.Length() - 5, 5);
1762 showname.ReplaceAll(
"_",
" ");
1763 ReplaceSpecialChars(furtherReading, showname);
1764 furtherReading <<
"</a> " << std::endl;
1767 gSystem->FreeDirectory(dirHandle);
1768 if (furtherReading.str().length())
1769 out <<
"<h3>Further Reading</h3><div id=\"furtherreading\">" << std::endl
1770 << furtherReading.str() <<
"</div><h3>List of Classes</h3>" << std::endl;
1788 void TDocOutput::ReferenceEntity(TSubString& str, TClass* entity,
const char* comment )
1791 fHtml->GetHtmlFileName(entity, link);
1793 if (comment && !strcmp(comment, entity->GetName()))
1796 AddLink(str, link, comment);
1814 void TDocOutput::ReferenceEntity(TSubString& str, TDataMember* entity,
const char* comment )
1817 TClass* scope = entity->GetClass();
1818 fHtml->GetHtmlFileName(scope, link);
1821 TString mangledName;
1823 mangledName = scope->GetName();
1824 NameSpace2FileName(mangledName);
1825 link += mangledName;
1829 mangledName = entity->GetName();
1830 NameSpace2FileName(mangledName);
1831 link += mangledName;
1833 TString description;
1835 description = entity->GetFullTypeName();
1838 description += scope->GetName();
1839 description +=
"::";
1841 description += entity->GetName();
1842 comment = description.Data();
1845 if (comment && !strcmp(comment, entity->GetName()))
1848 AddLink(str, link, comment);
1866 void TDocOutput::ReferenceEntity(TSubString& str, TDataType* entity,
const char* comment )
1868 TString mangledEntity(entity->GetName());
1869 NameSpace2FileName(mangledEntity);
1872 TClassDocInfo* cdi = 0;
1873 bool isClassTypedef = entity->GetType() == -1;
1876 isClassTypedef = isClassTypedef && (entity->Property() & 7);
1877 if (isClassTypedef) {
1878 std::string shortTypeName(fHtml->ShortType(entity->GetFullTypeName()));
1879 cdi = (TClassDocInfo*) GetHtml()->GetListOfClasses()->FindObject(shortTypeName.c_str());
1882 link = mangledEntity +
".html";
1884 link =
"ListOfTypes.html#";
1885 link += mangledEntity;
1888 if (comment && !strcmp(comment, entity->GetName()))
1891 AddLink(str, link, comment);
1909 void TDocOutput::ReferenceEntity(TSubString& str, TMethod* entity,
const char* comment )
1912 TClass* scope = entity->GetClass();
1913 fHtml->GetHtmlFileName(scope, link);
1916 TString mangledName(scope->GetName());
1917 NameSpace2FileName(mangledName);
1918 link += mangledName;
1921 mangledName = entity->GetName();
1922 NameSpace2FileName(mangledName);
1923 link += mangledName;
1925 TString description;
1926 if (!comment && entity->GetClass()) {
1927 TIter iMeth(scope->GetListOfMethods());
1929 while ((mCand = (TMethod*)iMeth()))
1930 if (!strcmp(mCand->GetName(), entity->GetName())) {
1931 if (description.Length()) {
1932 description +=
" or overloads";
1935 description = mCand->GetPrototype();
1937 comment = description.Data();
1940 if (comment && !strcmp(comment, entity->GetName()))
1943 AddLink(str, link, comment);
1951 Bool_t TDocOutput::ReferenceIsRelative(
const char* reference)
const
1953 return !reference ||
1954 strncmp(reference,
"http", 4) ||
1955 (strncmp(reference + 4,
"://", 3) && strncmp(reference + 4,
"s://", 4));
1962 const char* TDocOutput::ReplaceSpecialChars(
char c)
1976 case '<':
return "<";
1977 case '&':
return "&";
1978 case '>':
return ">";
1992 void TDocOutput::ReplaceSpecialChars(TString& text, Ssiz_t &pos)
1994 const char c = text[pos];
1995 const char* replaced = ReplaceSpecialChars(c);
1997 text.Replace(pos, 1, replaced);
1998 pos += strlen(replaced) - 1;
2010 void TDocOutput::ReplaceSpecialChars(TString& text) {
2012 while (pos < text.Length())
2013 ReplaceSpecialChars(text, pos);
2024 void TDocOutput::ReplaceSpecialChars(std::ostream& out,
const char *
string)
2026 while (
string && *
string) {
2027 const char* replaced = ReplaceSpecialChars(*
string);
2040 Bool_t TDocOutput::RunDot(
const char* filename, std::ostream* outMap ,
2041 EGraphvizTool gvwhat ) {
2042 if (!fHtml->HaveDot())
2047 case kNeato: runDot =
"neato";
break;
2048 case kFdp: runDot =
"fdp";
break;
2049 case kCirco: runDot =
"circo";
break;
2050 default: runDot =
"dot";
2052 if (fHtml->GetDotDir() && *fHtml->GetDotDir())
2053 gSystem->PrependPathName(fHtml->GetDotDir(), runDot);
2054 runDot +=
" -q1 -Tpng -o";
2058 runDot +=
"-Tcmap -o";
2066 Info(
"RunDot",
"Running: %s", runDot.Data());
2067 Int_t retDot = gSystem->Exec(runDot);
2068 if (gDebug < 4 && !retDot)
2069 gSystem->Unlink(Form(
"%s.dot", filename));
2071 if (!retDot && outMap) {
2072 std::ifstream inmap(Form(
"%s.map", filename));
2074 std::getline(inmap, line);
2075 if (inmap && !inmap.eof()) {
2076 *outMap <<
"<map name=\"Map" << gSystem->BaseName(filename)
2077 <<
"\" id=\"Map" << gSystem->BaseName(filename) <<
"\">" << std::endl;
2078 while (inmap && !inmap.eof()) {
2079 if (line.compare(0, 6,
"<area ") == 0) {
2080 size_t posEndTag = line.find(
'>');
2081 if (posEndTag != std::string::npos)
2082 line.replace(posEndTag, 1,
"/>");
2084 *outMap << line << std::endl;
2085 std::getline(inmap, line);
2087 *outMap <<
"</map>" << std::endl;
2091 gSystem->Unlink(Form(
"%s.map", filename));
2095 Error(
"RunDot",
"Error running %s!", runDot.Data());
2096 fHtml->SetFoundDot(kFALSE);
2109 void TDocOutput::WriteHtmlHeader(std::ostream& out,
const char *titleNoSpecial,
2110 const char* dir , TClass *cls ,
2113 std::ifstream addHeaderFile(header);
2115 if (!addHeaderFile.good()) {
2116 Warning(
"THtml::WriteHtmlHeader",
2117 "Can't open html header file %s\n", header);
2121 TString declFileName;
2122 if (cls) fHtml->GetDeclFileName(cls, kFALSE, declFileName);
2123 TString implFileName;
2124 if (cls) fHtml->GetImplFileName(cls, kFALSE, implFileName);
2126 const TString& charset = GetHtml()->GetCharset();
2128 TString strDate(date.AsString());
2131 while (!addHeaderFile.eof()) {
2133 line.ReadLine(addHeaderFile, kFALSE);
2134 if (addHeaderFile.eof())
2140 line.Index(
"%CLASS%") != kNPOS ||
2141 line.Index(
"%INCFILE%") != kNPOS ||
2142 line.Index(
"%SRCFILE%") != kNPOS))
2147 txt.ReplaceAll(
"%TITLE%", titleNoSpecial);
2148 txt.ReplaceAll(
"%DATE%", strDate);
2149 txt.ReplaceAll(
"%RELDIR%", dir);
2150 txt.ReplaceAll(
"%CHARSET%", charset);
2153 txt.ReplaceAll(
"%CLASS%", cls->GetName());
2154 txt.ReplaceAll(
"%INCFILE%", declFileName);
2155 txt.ReplaceAll(
"%SRCFILE%", implFileName);
2158 out << txt << std::endl;
2189 void TDocOutput::WriteHtmlHeader(std::ostream& out,
const char *title,
2190 const char* dir , TClass *cls)
2192 TString userHeader = GetHtml()->GetHeader();
2193 TString noSpecialCharTitle(title);
2194 ReplaceSpecialChars(noSpecialCharTitle);
2196 Ssiz_t lenUserHeader = userHeader.Length();
2198 Bool_t bothHeaders = lenUserHeader > 0 && userHeader[lenUserHeader - 1] ==
'+';
2199 if (lenUserHeader == 0 || bothHeaders) {
2200 TString header(
"header.html");
2201 gSystem->PrependPathName(fHtml->GetEtcDir(), header);
2202 WriteHtmlHeader(out, noSpecialCharTitle, dir, cls, header);
2205 if (lenUserHeader != 0) {
2207 userHeader.Remove(lenUserHeader - 1);
2208 WriteHtmlHeader(out, noSpecialCharTitle, dir, cls, userHeader);
2217 void TDocOutput::WriteHtmlFooter(std::ostream& out,
const char* ,
2218 const char* lastUpdate,
const char* author,
2219 const char* copyright,
const char* footer)
2221 static const char* templateSITags[TDocParser::kNumSourceInfos] = {
"%UPDATE%",
"%AUTHOR%",
"%COPYRIGHT%",
"%CHANGED%",
"%GENERATED%"};
2225 today.Form(
"%d-%02d-%02d %02d:%02d", dtToday.GetYear(), dtToday.GetMonth(), dtToday.GetDay(), dtToday.GetHour(), dtToday.GetMinute());
2227 TString datimeString;
2228 if (!lastUpdate || !lastUpdate[0]) {
2231 const char* siValues[TDocParser::kNumSourceInfos] = { lastUpdate, author, copyright, lastUpdate, today };
2233 std::ifstream addFooterFile(footer);
2235 if (!addFooterFile.good()) {
2236 Warning(
"THtml::WriteHtmlFooter",
2237 "Can't open html footer file %s\n", footer);
2242 while (!addFooterFile.eof()) {
2244 line.ReadLine(addFooterFile, kFALSE);
2245 if (addFooterFile.eof())
2251 for (Int_t siTag = 0; siTag < (Int_t) TDocParser::kNumSourceInfos; ++siTag) {
2252 Ssiz_t siPos = line.Index(templateSITags[siTag]);
2253 if (siPos != kNPOS) {
2254 if (siValues[siTag] && siValues[siTag][0])
2255 line.Replace(siPos, strlen(templateSITags[siTag]), siValues[siTag]);
2261 out << line << std::endl;
2287 void TDocOutput::WriteHtmlFooter(std::ostream& out,
const char *dir,
2288 const char *lastUpdate,
const char *author,
2289 const char *copyright)
2293 TString userFooter = GetHtml()->GetFooter();
2295 if (userFooter.Length() != 0) {
2296 TString footer(userFooter);
2297 if (footer.EndsWith(
"+"))
2298 footer.Remove(footer.Length() - 1);
2299 WriteHtmlFooter(out, dir, lastUpdate, author, copyright, footer);
2302 if (userFooter.Length() == 0 || userFooter.EndsWith(
"+")) {
2303 TString footer(
"footer.html");
2304 gSystem->PrependPathName(fHtml->GetEtcDir(), footer);
2305 WriteHtmlFooter(out, dir, lastUpdate, author, copyright, footer);
2312 void TDocOutput::WriteModuleLinks(std::ostream& out)
2314 if (fHtml->GetListOfModules()->GetSize()) {
2315 out <<
"<div id=\"indxModules\"><h4>Modules</h4>" << std::endl;
2317 fHtml->SortListOfModules();
2318 TIter iModule(fHtml->GetListOfModules());
2319 TModuleDocInfo* module = 0;
2320 while ((module = (TModuleDocInfo*) iModule())) {
2321 if (!module->GetName() || strchr(module->GetName(),
'/'))
2323 if (module->IsSelected()) {
2324 TString name(module->GetName());
2326 out <<
"<a href=\"" << name <<
"_Index.html\">"
2327 << name <<
"</a>" << std::endl;
2330 out<<
"</div><br />" << std::endl;
2340 void TDocOutput::WriteLineNumbers(std::ostream& out, Long_t nLines,
const TString& infileBase)
const
2342 out <<
"<div id=\"linenums\">";
2343 for (Long_t i = 0; i < nLines; ++i) {
2345 out <<
"<div class=\"ln\"> <span class=\"lnfile\">" << infileBase
2346 <<
":</span><a name=\"" << i + 1 <<
"\" href=\"#" << i + 1
2347 <<
"\" class=\"ln\">" << i + 1 <<
"</a></div>";
2349 out <<
"</div>" << std::endl;
2356 void TDocOutput::WriteModuleLinks(std::ostream& out, TModuleDocInfo* super)
2358 if (super->GetSub().GetSize()) {
2359 TString superName(super->GetName());
2360 superName.ToUpper();
2361 out <<
"<div id=\"indxModules\"><h4>" << superName <<
" Modules</h4>" << std::endl;
2363 super->GetSub().Sort();
2364 TIter iModule(&super->GetSub());
2365 TModuleDocInfo* module = 0;
2366 while ((module = (TModuleDocInfo*) iModule())) {
2367 if (module->IsSelected()) {
2368 TString name(module->GetName());
2371 link.ReplaceAll(
"/",
"_");
2372 Ssiz_t posSlash = name.Last(
'/');
2373 if (posSlash != kNPOS)
2374 name.Remove(0, posSlash + 1);
2375 out <<
"<a href=\"" << link <<
"_Index.html\">" << name <<
"</a>" << std::endl;
2378 out<<
"</div><br />" << std::endl;
2386 void TDocOutput::WriteSearch(std::ostream& out)
2389 const TString& searchCmd = GetHtml()->GetSearchStemURL();
2390 const TString& searchEngine = GetHtml()->GetSearchEngine();
2392 if (!searchCmd.Length() && !searchEngine.Length())
2395 if (searchCmd.Length()) {
2396 TUrl url(searchCmd);
2397 TString serverName(url.GetHost());
2398 if (serverName.Length()) {
2399 serverName.Prepend(
" title=\"");
2400 serverName +=
"\" ";
2403 out <<
"<script type=\"text/javascript\">" << std::endl
2404 <<
"function onSearch() {" << std::endl
2405 <<
"var s='" << searchCmd <<
"';" << std::endl
2406 <<
"var ref=String(document.location.href).replace(/https?:\\/\\//,'').replace(/\\/[^\\/]*$/,'').replace(/\\//g,'%2F');" << std::endl
2407 <<
"window.location.href=s.replace(/%u/ig,ref).replace(/%s/ig,escape(document.searchform.t.value));" << std::endl
2408 <<
"return false;}" << std::endl
2409 <<
"</script>" << std::endl
2410 <<
"<form id=\"searchform\" name=\"searchform\" onsubmit=\"return onSearch()\" action=\"javascript:onSearch();\" method=\"post\">" << std::endl
2411 <<
"<input name=\"t\" size=\"30\" value=\"Search documentation...\" onfocus=\"if (document.searchform.t.value=='Search documentation...') document.searchform.t.value='';\"></input>" << std::endl
2412 <<
"<a id=\"searchlink\" " << serverName <<
" href=\"javascript:onSearch();\" onclick=\"return onSearch()\">Search</a></form>" << std::endl;
2413 }
else if (searchEngine.Length())
2415 out <<
"<a class=\"descrheadentry\" href=\"" << searchEngine
2416 <<
"\">Search the Class Reference Guide</a>" << std::endl;
2423 void TDocOutput::WriteLocation(std::ostream& out, TModuleDocInfo* module,
const char* classname)
2425 out <<
"<div class=\"location\">" << std::endl;
2426 const char *productName = fHtml->GetProductName();
2427 out <<
"<a class=\"locationlevel\" href=\"index.html\">" << productName <<
"</a>" << std::endl;
2430 TString modulename(module->GetName());
2431 modulename.ToUpper();
2435 while (modulename.Tokenize(modulePart, pos,
"/")) {
2436 if (pos == kNPOS && !classname)
2439 if (modulePath.Length()) modulePath +=
"_";
2440 modulePath += modulePart;
2441 out <<
" » <a class=\"locationlevel\" href=\"./" << modulePath <<
"_Index.html\">" << modulePart <<
"</a>" << std::endl;
2446 if (classname) entityName = classname;
2448 entityName = module->GetName();
2449 Ssiz_t posSlash = entityName.Last(
'/');
2450 if (posSlash != kNPOS)
2451 entityName.Remove(0, posSlash + 1);
2452 entityName.ToUpper();
2454 if (entityName.Length()) {
2455 out <<
" » <a class=\"locationlevel\" href=\"#TopOfPage\">";
2456 ReplaceSpecialChars(out, entityName);
2457 out <<
"</a>" << std::endl;
2459 out <<
"</div>" << std::endl;
2468 void TDocOutput::WriteTopLinks(std::ostream& out, TModuleDocInfo* module,
const char* classname,
2469 Bool_t withLocation)
2471 out <<
"<div id=\"toplinks\">" << std::endl;
2473 out <<
"<div class=\"descrhead\"><div class=\"descrheadcontent\">" << std::endl
2474 <<
"<span class=\"descrtitle\">Quick Links:</span>" << std::endl;
2477 const char* userHomePage = GetHtml()->GetHomepage();
2478 const char* productName = fHtml->GetProductName();
2481 }
else if (!strcmp(productName,
"ROOT")) {
2484 if (userHomePage && *userHomePage)
2485 out <<
"<a class=\"descrheadentry\" href=\"" << userHomePage <<
"\">" << productName <<
"</a>" << std::endl;
2486 out <<
"<a class=\"descrheadentry\" href=\"http://root.cern.ch\">ROOT Homepage</a>" << std::endl
2487 <<
"<a class=\"descrheadentry\" href=\"./ClassIndex.html\">Class Index</a>" << std::endl
2488 <<
"<a class=\"descrheadentry\" href=\"./ClassHierarchy.html\">Class Hierarchy</a></div>" << std::endl;
2490 out <<
"</div>" << std::endl;
2493 out <<
"</div>" << std::endl;
2494 WriteLocation(out, module, classname);