00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TDocOutput.h"
00013
00014 #include "Riostream.h"
00015 #include "TClassDocOutput.h"
00016 #include "TClassEdit.h"
00017 #include "TDataMember.h"
00018 #include "TDataType.h"
00019 #include "TDocInfo.h"
00020 #include "TDocParser.h"
00021 #include "TEnv.h"
00022 #include "TGlobal.h"
00023 #include "THtml.h"
00024 #include "TInterpreter.h"
00025 #include "TMethod.h"
00026 #include "TPRegexp.h"
00027 #include "TROOT.h"
00028 #include "TSystem.h"
00029 #include "TUrl.h"
00030 #include "TVirtualMutex.h"
00031 #include "TVirtualPad.h"
00032 #include "TVirtualViewer3D.h"
00033 #include <vector>
00034 #include <list>
00035 #include <set>
00036 #include <sstream>
00037 #include <stdlib.h>
00038
00039 namespace {
00040
00041 typedef std::vector<std::string> Words_t;
00042 typedef Words_t::const_iterator SectionStart_t;
00043
00044 class TSectionInfo {
00045 public:
00046 TSectionInfo(SectionStart_t start, size_t chars, size_t size):
00047 fStart(start), fChars(chars), fSize(size) {};
00048
00049 SectionStart_t fStart;
00050 size_t fChars;
00051 size_t fSize;
00052 };
00053 typedef std::list<TSectionInfo> SectionStarts_t;
00054
00055 static void Sections_BuildIndex(SectionStarts_t& sectionStarts,
00056 SectionStart_t begin, SectionStart_t end,
00057 size_t maxPerSection)
00058 {
00059
00060
00061
00062 SectionStart_t cursor = begin;
00063 if (sectionStarts.empty() || sectionStarts.back().fStart != cursor)
00064 sectionStarts.push_back(TSectionInfo(cursor, 1, 0));
00065
00066 SectionStarts_t::iterator prevSection = sectionStarts.end();
00067 --prevSection;
00068
00069 while (cursor != end) {
00070 size_t numLeft = end - cursor;
00071 size_t assumedNumSections = (numLeft + maxPerSection - 1 ) / maxPerSection;
00072 size_t step = ((numLeft + assumedNumSections - 1) / assumedNumSections);
00073 if (!step || step >= numLeft) return;
00074 cursor += step;
00075 if (cursor == end) break;
00076
00077 SectionStart_t addWhichOne = prevSection->fStart;
00078
00079 size_t selectionChar=1;
00080 for (; selectionChar <= cursor->length() && addWhichOne == prevSection->fStart;
00081 ++selectionChar) {
00082 SectionStart_t checkPrev = cursor;
00083 while (--checkPrev != prevSection->fStart
00084 && !strncasecmp(checkPrev->c_str(), cursor->c_str(), selectionChar)) { }
00085
00086 SectionStart_t checkNext = cursor;
00087 while (++checkNext != end
00088 && !strncasecmp(checkNext->c_str(), cursor->c_str(), selectionChar)) { }
00089
00090
00091 if (checkPrev != prevSection->fStart) {
00092 if ((cursor - checkPrev) <= (checkNext - cursor))
00093 addWhichOne = ++checkPrev;
00094 else if (checkNext != end
00095 && (size_t)(checkNext - cursor) < maxPerSection) {
00096 addWhichOne = checkNext;
00097 }
00098 }
00099 }
00100 if (addWhichOne == prevSection->fStart)
00101 addWhichOne = cursor;
00102
00103 selectionChar = 1;
00104 while (selectionChar <= prevSection->fStart->length()
00105 && selectionChar <= addWhichOne->length()
00106 && !strncasecmp(prevSection->fStart->c_str(), addWhichOne->c_str(), selectionChar))
00107 ++selectionChar;
00108
00109 sectionStarts.push_back(TSectionInfo(addWhichOne, selectionChar, 0));
00110 cursor = addWhichOne;
00111 ++prevSection;
00112 }
00113 }
00114
00115 static void Sections_SetSize(SectionStarts_t& sectionStarts, const Words_t &words)
00116 {
00117
00118 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
00119 iSectionStart != sectionStarts.end(); ++iSectionStart) {
00120 SectionStarts_t::iterator next = iSectionStart;
00121 ++next;
00122 if (next == sectionStarts.end()) {
00123 iSectionStart->fSize = (words.end() - iSectionStart->fStart);
00124 break;
00125 }
00126 iSectionStart->fSize = (next->fStart - iSectionStart->fStart);
00127 }
00128 }
00129
00130 static void Sections_PostMerge(SectionStarts_t& sectionStarts, const size_t maxPerSection)
00131 {
00132
00133 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
00134 iSectionStart != sectionStarts.end();) {
00135 SectionStarts_t::iterator iNextSectionStart = iSectionStart;
00136 ++iNextSectionStart;
00137 if (iNextSectionStart == sectionStarts.end()) break;
00138 if (iNextSectionStart->fSize + iSectionStart->fSize < maxPerSection) {
00139 iSectionStart->fSize += iNextSectionStart->fSize;
00140 sectionStarts.erase(iNextSectionStart);
00141 } else ++iSectionStart;
00142 }
00143 }
00144
00145 static void GetIndexChars(const Words_t& words, UInt_t numSectionsIn,
00146 std::vector<std::string> §ionMarkersOut)
00147 {
00148
00149
00150
00151
00152
00153 const size_t maxPerSection = (words.size() + numSectionsIn - 1)/ numSectionsIn;
00154 SectionStarts_t sectionStarts;
00155 Sections_BuildIndex(sectionStarts, words.begin(), words.end(), maxPerSection);
00156 Sections_SetSize(sectionStarts, words);
00157 Sections_PostMerge(sectionStarts, maxPerSection);
00158
00159
00160 sectionMarkersOut.clear();
00161 sectionMarkersOut.resize(sectionStarts.size());
00162 size_t idx = 0;
00163 for (SectionStarts_t::iterator iSectionStart = sectionStarts.begin();
00164 iSectionStart != sectionStarts.end(); ++iSectionStart)
00165 sectionMarkersOut[idx++] =
00166 iSectionStart->fStart->substr(0, iSectionStart->fChars);
00167 }
00168
00169 static void GetIndexChars(const std::list<std::string>& wordsIn, UInt_t numSectionsIn,
00170 std::vector<std::string> §ionMarkersOut)
00171 {
00172
00173 Words_t words(wordsIn.size());
00174 size_t idx = 0;
00175 for (std::list<std::string>::const_iterator iWord = wordsIn.begin(); iWord != wordsIn.end(); ++iWord)
00176 words[idx++] = *iWord;
00177 GetIndexChars(words, numSectionsIn, sectionMarkersOut);
00178 }
00179
00180 }
00181
00182 extern "C" {
00183
00184
00185 static int CaseInsensitiveSort(const void *name1, const void *name2)
00186 {
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 return (strcasecmp(*((char **) name1), *((char **) name2)));
00201 }
00202 }
00203
00204 namespace {
00205
00206
00207 static void sort_strlist_stricmp(std::vector<std::string>& l)
00208 {
00209
00210 struct posList {
00211 const char* str;
00212 size_t pos;
00213 };
00214 posList* carr = new posList[l.size()];
00215 size_t idx = 0;
00216 for (size_t iS = 0, iSE = l.size(); iS < iSE; ++iS) {
00217 carr[idx].pos = iS;
00218 carr[idx++].str = l[iS].c_str();
00219 }
00220 qsort(&carr[0].str, idx, sizeof(posList), CaseInsensitiveSort);
00221 std::vector<std::string> lsort(l.size());
00222 for (size_t iS = 0, iSE = l.size(); iS < iSE; ++iS) {
00223 lsort[iS].swap(l[carr[iS].pos]);
00224 }
00225 delete [] carr;
00226 l.swap(lsort);
00227 }
00228
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 ClassImp(TDocOutput);
00253
00254
00255 TDocOutput::TDocOutput(THtml& html): fHtml(&html)
00256 {}
00257
00258
00259 TDocOutput::~TDocOutput()
00260 {}
00261
00262
00263 void TDocOutput::AddLink(TSubString& str, TString& link, const char* comment)
00264 {
00265
00266
00267
00268
00269 if (ReferenceIsRelative(link) && !link.BeginsWith("./"))
00270 link.Prepend("./");
00271 link.Prepend("<a href=\"");
00272 link += "\"";
00273 if (comment && strlen(comment)) {
00274 link += " title=\"";
00275 TString description(comment);
00276 ReplaceSpecialChars(description);
00277 description.ReplaceAll("\"", """);
00278 link += description;
00279 link += "\"";
00280 }
00281 link += ">";
00282
00283 str.String().Insert(str.Start() + str.Length(), "</a>");
00284 str.String().Insert(str.Start(), link);
00285
00286 TString &strString = str.String();
00287 TSubString update = strString(str.Start(), str.Length() + link.Length() + 4);
00288 str = update;
00289 }
00290
00291
00292 void TDocOutput::AdjustSourcePath(TString& line, const char* relpath )
00293 {
00294
00295
00296
00297 TString replWithRelPath("=\"@!@");
00298 line.ReplaceAll("=\"../", replWithRelPath + "../" + relpath);
00299 line.ReplaceAll("=\"./", replWithRelPath + relpath);
00300 line.ReplaceAll("=\"@!@","=\"");
00301 }
00302
00303
00304 void TDocOutput::Convert(std::istream& in, const char* infilename,
00305 const char* outfilename, const char *title,
00306 const char *relpath , Int_t includeOutput ,
00307 const char* context ,
00308 TGClient* gclient )
00309 {
00310
00311
00312
00313
00314
00315 TString htmlFilename(outfilename);
00316 htmlFilename += ".html";
00317
00318 std::ofstream out(htmlFilename);
00319
00320 if (!out.good()) {
00321 Error("Convert", "Can't open file '%s' !", htmlFilename.Data());
00322 return;
00323 }
00324
00325
00326 WriteHtmlHeader(out, title, relpath);
00327
00328 if (context && context[0])
00329 out << context << endl;
00330 else if (title && title[0])
00331 out << "<h1 class=\"convert\">" << title << "</h1>" << endl;
00332
00333 Int_t numReuseCanvases = 0;
00334 if (includeOutput && !(includeOutput & THtml::kForceOutput)) {
00335 void* dirHandle = gSystem->OpenDirectory(gSystem->DirName(htmlFilename));
00336 if (dirHandle) {
00337 FileStat_t infile_stat;
00338 if (!gSystem->GetPathInfo(infilename, infile_stat)) {
00339
00340 const char* outfile = 0;
00341 TString firstCanvasFileBase(gSystem->BaseName(outfilename));
00342 firstCanvasFileBase += "_0.png";
00343
00344 Bool_t haveFirstCanvasFile = false;
00345 while ((outfile = gSystem->GetDirEntry(dirHandle))) {
00346 if (firstCanvasFileBase == outfile) {
00347 haveFirstCanvasFile = true;
00348 break;
00349 }
00350 }
00351 gSystem->FreeDirectory(dirHandle);
00352
00353 FileStat_t outfile_stat;
00354 TString firstCanvasFile = outfilename;
00355 firstCanvasFile += "_0.png";
00356 Int_t maxIdx = -1;
00357 if (haveFirstCanvasFile && !gSystem->GetPathInfo(firstCanvasFile, outfile_stat)
00358 && outfile_stat.fMtime > infile_stat.fMtime) {
00359
00360
00361 dirHandle = gSystem->OpenDirectory(gSystem->DirName(htmlFilename));
00362 TString stem(gSystem->BaseName(outfilename));
00363 stem += "_";
00364 TString dir(gSystem->DirName(htmlFilename));
00365 while ((outfile = gSystem->GetDirEntry(dirHandle))) {
00366 if (strncmp(outfile, stem, stem.Length()))
00367 continue;
00368 const char* posext = strrchr(outfile, '.');
00369 if (!posext || strcmp(posext, ".png"))
00370 continue;
00371
00372
00373 if (gSystem->GetPathInfo(dir + "/" + outfile, outfile_stat))
00374
00375 continue;
00376
00377 if (outfile_stat.fMtime > infile_stat.fMtime) {
00378 ++numReuseCanvases;
00379
00380
00381 TString idxStr(outfile + stem.Length());
00382 idxStr.Remove(idxStr.Length() - 4);
00383 Int_t idx = idxStr.Atoi();
00384 if (maxIdx < idx)
00385 maxIdx = idx;
00386 }
00387 }
00388 gSystem->FreeDirectory(dirHandle);
00389 if (maxIdx + 1 != numReuseCanvases)
00390
00391
00392 numReuseCanvases = 0;
00393 }
00394 }
00395 }
00396 }
00397
00398 if (numReuseCanvases)
00399 Printf("Convert: %s (reusing %d saved canvas%s)", htmlFilename.Data(), numReuseCanvases, (numReuseCanvases > 1 ? "es" : ""));
00400 else
00401 Printf("Convert: %s", htmlFilename.Data());
00402
00403 UInt_t nCanvases = numReuseCanvases;
00404 if (includeOutput) {
00405 if (!numReuseCanvases) {
00406
00407 if (includeOutput & THtml::kSeparateProcessOutput) {
00408 TString baseInFileName = gSystem->BaseName(infilename);
00409 TPMERegexp reOutFile(baseInFileName + "_[[:digit:]]+\\.png");
00410
00411
00412 void* outdirH = gSystem->OpenDirectory(gSystem->DirName(outfilename));
00413 if (outdirH) {
00414
00415 const char* outdirE = 0;
00416 while ((outdirE = gSystem->GetDirEntry(outdirH))) {
00417 if (reOutFile.Match(outdirE)) {
00418 gSystem->Unlink(outdirE);
00419 }
00420 }
00421 gSystem->FreeDirectory(outdirH);
00422 }
00423
00424 gSystem->Exec(TString::Format("ROOT_HIST=0 root.exe -l -q %s $ROOTSYS/etc/html/saveScriptOutput.C\\(\\\"%s\\\",\\\"%s\\\",%d\\)",
00425 gROOT->IsBatch() ? "-b" : "",
00426 infilename,
00427 gSystem->DirName(outfilename),
00428 includeOutput & THtml::kCompiledOutput));
00429
00430
00431 outdirH = gSystem->OpenDirectory(gSystem->DirName(outfilename));
00432 if (outdirH) {
00433
00434 const char* outdirE = 0;
00435 while ((outdirE = gSystem->GetDirEntry(outdirH))) {
00436 if (reOutFile.Match(outdirE)) {
00437 ++nCanvases;
00438 }
00439 }
00440 gSystem->FreeDirectory(outdirH);
00441 }
00442 } else {
00443
00444 TString pwd(gSystem->pwd());
00445 gSystem->cd(gSystem->DirName(infilename));
00446
00447 TList* gClientGetListOfWindows = 0;
00448 TObject* gClientGetDefaultRoot = 0;
00449 std::set<TObject*> previousWindows;
00450 if (gclient) {
00451 gROOT->ProcessLine(TString::Format("*((TList**)0x%lx) = ((TGClient*)0x%lx)->GetListOfWindows();",
00452 (ULong_t)&gClientGetListOfWindows, (ULong_t)gclient));
00453 gROOT->ProcessLine(TString::Format("*((TObject**)0x%lx) = ((TGClient*)0x%lx)->GetDefaultRoot();",
00454 (ULong_t)&gClientGetDefaultRoot, (ULong_t)gclient));
00455 TObject* win = 0;
00456 TIter iWin(gClientGetListOfWindows);
00457 while((win = iWin())) {
00458 TObject* winGetParent = 0;
00459 gROOT->ProcessLine(TString::Format("*((TObject**)0x%lx) = ((TGWindow*)0x%lx)->GetParent();",
00460 (ULong_t)&winGetParent, (ULong_t)win));
00461 if (winGetParent == gClientGetDefaultRoot)
00462 previousWindows.insert(win);
00463 }
00464 } else {
00465 if (gROOT->GetListOfCanvases()->GetSize())
00466 previousWindows.insert(gROOT->GetListOfCanvases()->Last());
00467 }
00468 TIter iTimer(gSystem->GetListOfTimers());
00469 std::set<TObject*> timersBefore;
00470 TObject* timerOld = 0;
00471 while ((timerOld = iTimer()))
00472 timersBefore.insert(timerOld);
00473
00474 TString cmd(".x ");
00475 cmd += gSystem->BaseName(infilename);
00476 if (includeOutput & THtml::kCompiledOutput)
00477 cmd += "+";
00478 gInterpreter->SaveContext();
00479 gInterpreter->SaveGlobalsContext();
00480 Int_t err;
00481 gROOT->ProcessLine(cmd, &err);
00482 gSystem->ProcessEvents();
00483 gSystem->cd(pwd);
00484
00485 if (err == TInterpreter::kNoError) {
00486 if (gclient) {
00487 TClass* clRootCanvas = TClass::GetClass("TRootCanvas");
00488 TClass* clGMainFrame = TClass::GetClass("TGMainFrame");
00489 TObject* win = 0;
00490 TIter iWin(gClientGetListOfWindows);
00491 while((win = iWin())) {
00492 TObject* winGetParent = 0;
00493 gROOT->ProcessLine(TString::Format("*((TObject**)0x%lx) = ((TGWindow*)0x%lx)->GetParent();",
00494 (ULong_t)&winGetParent, (ULong_t)win));
00495 Bool_t winIsMapped = kFALSE;
00496 if (winGetParent == gClientGetDefaultRoot)
00497 gROOT->ProcessLine(TString::Format("*((Bool_t*)0x%lx) = ((TGWindow*)0x%lx)->IsMapped();",
00498 (ULong_t)&winIsMapped, (ULong_t)win));
00499 if (winIsMapped && previousWindows.find(win) == previousWindows.end()
00500 && win->InheritsFrom(clGMainFrame)) {
00501 gROOT->ProcessLine(TString::Format("((TGWindow*)0x%lx)->MapRaised();", (ULong_t)win));
00502 Bool_t isRootCanvas = win->InheritsFrom(clRootCanvas);
00503 Bool_t hasEditor = false;
00504 if (isRootCanvas) {
00505 gROOT->ProcessLine(TString::Format("*((Bool_t*)0x%lx) = ((TRootCanvas*)0x%lx)->HasEditor();",
00506 (ULong_t)&hasEditor, (ULong_t)win));
00507 }
00508 if (isRootCanvas && !hasEditor) {
00509 TVirtualPad* pad = 0;
00510 gROOT->ProcessLine(TString::Format("*((TVirtualPad**)0x%lx) = ((TRootCanvas*)0x%lx)->Canvas();",
00511 (ULong_t)&pad, (ULong_t)win));
00512 if (!pad->HasViewer3D() || pad->GetViewer3D()->InheritsFrom("TViewer3DPad")) {
00513 pad->SaveAs(TString::Format("%s_%d.png", outfilename, nCanvases++));
00514 }
00515 } else
00516 gROOT->ProcessLine(TString::Format("((TGWindow*)0x%lx)->SaveAs(\"%s_%d.png\");",
00517 (ULong_t)win, outfilename, nCanvases++));
00518 }
00519 }
00520 } else {
00521
00522 TVirtualPad* pad = 0;
00523 TVirtualPad* last = 0;
00524 if (!previousWindows.empty())
00525 last = (TVirtualPad*) *previousWindows.begin();
00526 TIter iCanvas(gROOT->GetListOfCanvases());
00527 while ((pad = (TVirtualPad*) iCanvas())) {
00528 if (last) {
00529 if (last == pad) last = 0;
00530 continue;
00531 }
00532 pad->SaveAs(TString::Format("%s_%d.png", outfilename, nCanvases++));
00533 }
00534 }
00535 gInterpreter->Reset();
00536 gInterpreter->ResetGlobals();
00537 TIter iTimerRemove(gSystem->GetListOfTimers());
00538 TTimer* timer = 0;
00539 while ((timer = (TTimer*) iTimerRemove()))
00540 if (timersBefore.find(timer) == timersBefore.end())
00541 gSystem->RemoveTimer(timer);
00542 }
00543 }
00544 }
00545 out << "<table><tr><td style=\"vertical-align:top;padding-right:2em;\">" << endl;
00546 }
00547 out << "<div class=\"listing\"><pre class=\"listing\">" << endl;
00548
00549 TDocParser parser(*this);
00550 parser.Convert(out, in, relpath, (includeOutput) ,
00551 kFALSE );
00552
00553 out << "</pre></div>" << endl;
00554
00555 WriteLineNumbers(out, parser.GetLineNumber(), gSystem->BaseName(infilename));
00556
00557 if (includeOutput) {
00558 out << "</td><td style=\"vertical-align:top;\">" << endl;
00559 out << "<table>" << endl;
00560 for (UInt_t i = 0; i < nCanvases; ++i) {
00561 TString pngname = TString::Format("%s_%d.png", gSystem->BaseName(outfilename), i);
00562 out << "<tr><td><a href=\"" << pngname << "\">" << endl
00563 << "<img src=\"" << pngname << "\" id=\"canv" << i << "\" alt=\"thumb\" style=\"border:none;width:22em;\" "
00564 "onmouseover=\"javascript:canv" << i << ".style.width='auto';\" />" << endl
00565 << "</a></td></tr>" << endl;
00566 }
00567 out << "</table>" << endl;
00568 out << "</td></tr></table>" << endl;
00569 }
00570
00571
00572 WriteHtmlFooter(out, relpath);
00573 }
00574
00575
00576 Bool_t TDocOutput::CopyHtmlFile(const char *sourceName, const char *destName)
00577 {
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
00594
00595 TString sourceFile(sourceName);
00596
00597 if (!sourceFile.Length()) {
00598 Error("Copy", "Can't copy file '%s' to '%s' directory - source file name invalid!", sourceName,
00599 fHtml->GetOutputDir().Data());
00600 return kFALSE;
00601 }
00602
00603
00604 TString destFile;
00605 if (!destName || !*destName)
00606 destFile = gSystem->BaseName(sourceFile);
00607 else
00608 destFile = gSystem->BaseName(destName);
00609
00610 gSystem->PrependPathName(fHtml->GetOutputDir(), destFile);
00611
00612
00613 Long64_t size;
00614 Long_t id, flags, sModtime, dModtime;
00615 sModtime = 0;
00616 dModtime = 0;
00617 if (gSystem->GetPathInfo(sourceFile, &id, &size, &flags, &sModtime)
00618 || gSystem->GetPathInfo(destFile, &id, &size, &flags, &dModtime)
00619 || sModtime > dModtime)
00620 gSystem->CopyFile(sourceFile, destFile, kTRUE);
00621
00622 return kTRUE;
00623 }
00624
00625
00626
00627
00628 void TDocOutput::CreateHierarchy()
00629 {
00630
00631
00632
00633
00634
00635
00636
00637
00638 TString filename("ClassHierarchy.html");
00639 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
00640
00641
00642 std::ofstream out(filename);
00643
00644 if (!out.good()) {
00645 Error("CreateHierarchy", "Can't open file '%s' !", filename.Data());
00646 return;
00647 }
00648
00649 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
00650
00651
00652 WriteHtmlHeader(out, "Class Hierarchy");
00653
00654 WriteTopLinks(out, 0);
00655
00656 out << "<h1>Class Hierarchy</h1>" << endl;
00657
00658
00659
00660 TClassDocInfo* cdi = 0;
00661 TIter iClass(fHtml->GetListOfClasses());
00662 while ((cdi = (TClassDocInfo*)iClass())) {
00663 if (!cdi->HaveSource())
00664 continue;
00665
00666
00667 TDictionary *dictPtr = cdi->GetClass();
00668 TClass *basePtr = dynamic_cast<TClass*>(dictPtr);
00669 if (basePtr == 0) {
00670 if (!dictPtr)
00671 Warning("THtml::CreateHierarchy", "skipping class %s\n", cdi->GetName());
00672 continue;
00673 }
00674
00675 TClassDocOutput cdo(*fHtml, basePtr, 0);
00676 cdo.CreateClassHierarchy(out, cdi->GetHtmlFileName());
00677 }
00678
00679
00680 WriteHtmlFooter(out);
00681 }
00682
00683
00684 void TDocOutput::CreateClassIndex()
00685 {
00686
00687
00688
00689
00690 fHtml->CreateAuxiliaryFiles();
00691
00692 TString filename("ClassIndex.html");
00693 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
00694
00695
00696 std::ofstream indexFile(filename.Data());
00697
00698 if (!indexFile.good()) {
00699 Error("CreateClassIndex", "Can't open file '%s' !", filename.Data());
00700 return;
00701 }
00702
00703 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
00704
00705
00706 WriteHtmlHeader(indexFile, "Class Index");
00707
00708 WriteTopLinks(indexFile, 0);
00709
00710 indexFile << "<h1>Class Index</h1>" << endl;
00711
00712 WriteModuleLinks(indexFile);
00713
00714 std::vector<std::string> indexChars;
00715 if (fHtml->GetListOfClasses()->GetSize() > 10) {
00716 std::vector<std::string> classNames;
00717 {
00718 TIter iClass(fHtml->GetListOfClasses());
00719 TClassDocInfo* cdi = 0;
00720 while ((cdi = (TClassDocInfo*)iClass()))
00721 if (cdi->IsSelected() && cdi->HaveSource())
00722 classNames.push_back(cdi->GetName());
00723 }
00724
00725 if (classNames.size() > 10) {
00726 indexFile << "<div id=\"indxShortX\"><h4>Jump to</h4>" << endl;
00727
00728 GetIndexChars(classNames, 50 , indexChars);
00729 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
00730 indexFile << "<a href=\"#idx" << iIdxEntry << "\">";
00731 ReplaceSpecialChars(indexFile, indexChars[iIdxEntry].c_str());
00732 indexFile << "</a>" << endl;
00733 }
00734 indexFile << "</div><br />" << endl;
00735 }
00736 }
00737
00738 indexFile << "<ul id=\"indx\">" << endl;
00739
00740
00741 UInt_t currentIndexEntry = 0;
00742 TIter iClass(fHtml->GetListOfClasses());
00743 TClassDocInfo* cdi = 0;
00744 Int_t i = 0;
00745 while ((cdi = (TClassDocInfo*)iClass())) {
00746 if (!cdi->IsSelected() || !cdi->HaveSource())
00747 continue;
00748
00749
00750 TDictionary *currentDict = cdi->GetClass();
00751 TClass* currentClass = dynamic_cast<TClass*>(currentDict);
00752 if (!currentClass) {
00753 if (!currentDict)
00754 Warning("THtml::CreateClassIndex", "skipping class %s\n", cdi->GetName());
00755 continue;
00756 }
00757
00758 indexFile << "<li class=\"idxl" << (i++)%2 << "\">";
00759 if (currentIndexEntry < indexChars.size()
00760 && !strncmp(indexChars[currentIndexEntry].c_str(), cdi->GetName(),
00761 indexChars[currentIndexEntry].length()))
00762 indexFile << "<a name=\"idx" << currentIndexEntry++ << "\"></a>";
00763
00764 TString htmlFile(cdi->GetHtmlFileName());
00765 if (htmlFile.Length()) {
00766 indexFile << "<a href=\"";
00767 indexFile << htmlFile;
00768 indexFile << "\"><span class=\"typename\">";
00769 ReplaceSpecialChars(indexFile, cdi->GetName());
00770 indexFile << "</span></a> ";
00771 } else {
00772 indexFile << "<span class=\"typename\">";
00773 ReplaceSpecialChars(indexFile, cdi->GetName());
00774 indexFile << "</span> ";
00775 }
00776
00777
00778 ReplaceSpecialChars(indexFile, currentClass->GetTitle());
00779 indexFile << "</li>" << endl;
00780 }
00781
00782 indexFile << "</ul>" << endl;
00783
00784
00785 WriteHtmlFooter(indexFile);
00786 }
00787
00788
00789
00790 void TDocOutput::CreateModuleIndex()
00791 {
00792
00793
00794
00795
00796
00797 const char* title = "LibraryDependencies";
00798 TString dotfilename(title);
00799 gSystem->PrependPathName(fHtml->GetOutputDir(), dotfilename);
00800
00801 std::ofstream libDepDotFile(dotfilename + ".dot");
00802 libDepDotFile << "digraph G {" << endl
00803 << "ratio=compress;" << endl
00804 << "node [fontsize=22,labeldistance=0.1];" << endl
00805 << "edge [len=0.01];" << endl
00806 << "fontsize=22;" << endl
00807 << "size=\"16,16\";" << endl
00808 << "overlap=false;" << endl
00809 << "splines=true;" << endl
00810 << "K=0.1;" << endl;
00811
00812 TModuleDocInfo* module = 0;
00813 TIter iterModule(fHtml->GetListOfModules());
00814
00815 std::stringstream sstrCluster;
00816 std::stringstream sstrDeps;
00817 while ((module = (TModuleDocInfo*)iterModule())) {
00818 if (!module->IsSelected())
00819 continue;
00820
00821 std::vector<std::string> indexChars;
00822 TString filename(module->GetName());
00823 filename.ToUpper();
00824 filename.ReplaceAll("/","_");
00825 filename += "_Index.html";
00826 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
00827 std::ofstream outputFile(filename.Data());
00828 if (!outputFile.good()) {
00829 Error("CreateModuleIndex", "Can't open file '%s' !", filename.Data());
00830 continue;
00831 }
00832 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), filename.Data());
00833
00834 TString htmltitle("Index of ");
00835 TString moduletitle(module->GetName());
00836 moduletitle.ToUpper();
00837 htmltitle += moduletitle;
00838 WriteHtmlHeader(outputFile, htmltitle);
00839
00840 WriteTopLinks(outputFile, module);
00841
00842 outputFile << "<h2>" << htmltitle << "</h2>" << endl;
00843
00844
00845 if (GetHtml()->GetModuleDocPath().Length()) {
00846 TString outdir(module->GetName());
00847 gSystem->PrependPathName(GetHtml()->GetOutputDir(), outdir);
00848
00849 TString moduleDocDir;
00850 GetHtml()->GetPathDefinition().GetDocDir(module->GetName(), moduleDocDir);
00851 ProcessDocInDir(outputFile, moduleDocDir, outdir, module->GetName());
00852 }
00853
00854 WriteModuleLinks(outputFile, module);
00855
00856 std::list<std::string> classNames;
00857 {
00858 TIter iClass(module->GetClasses());
00859 TClassDocInfo* cdi = 0;
00860 while ((cdi = (TClassDocInfo*) iClass())) {
00861 if (!cdi->IsSelected() || !cdi->HaveSource())
00862 continue;
00863 classNames.push_back(cdi->GetName());
00864
00865 if (classNames.size() > 1) continue;
00866
00867 TClass* cdiClass = dynamic_cast<TClass*>(cdi->GetClass());
00868 if (!cdiClass)
00869 continue;
00870
00871 TString libs(cdiClass->GetSharedLibs());
00872 Ssiz_t posDepLibs = libs.Index(' ');
00873 TString thisLib(libs);
00874 if (posDepLibs != kNPOS)
00875 thisLib.Remove(posDepLibs, thisLib.Length());
00876
00877 {
00878 Ssiz_t posExt = thisLib.First('.');
00879 if (posExt != kNPOS)
00880 thisLib.Remove(posExt, thisLib.Length());
00881 }
00882
00883 if (!thisLib.Length())
00884 continue;
00885
00886
00887 TLibraryDocInfo *libdeps =
00888 (TLibraryDocInfo*)fHtml->GetLibraryDependencies()->FindObject(thisLib);
00889 if (!libdeps) {
00890 libdeps = new TLibraryDocInfo(thisLib);
00891 fHtml->GetLibraryDependencies()->Add(libdeps);
00892 }
00893 libdeps->AddModule(module->GetName());
00894 if (posDepLibs != kNPOS) {
00895 std::string lib;
00896 for(Ssiz_t pos = posDepLibs + 1; libs[pos]; ++pos) {
00897 if (libs[pos] == ' ') {
00898 if (thisLib.Length() && lib.length()) {
00899 size_t posExt = lib.find('.');
00900 if (posExt != std::string::npos)
00901 lib.erase(posExt);
00902 libdeps->AddDependency(lib);
00903 }
00904 lib.erase();
00905 } else
00906 lib += libs[pos];
00907 }
00908 if (lib.length() && thisLib.Length()) {
00909 size_t posExt = lib.find('.');
00910 if (posExt != std::string::npos)
00911 lib.erase(posExt);
00912 libdeps->AddDependency(lib);
00913 }
00914 }
00915 }
00916 }
00917
00918 TIter iClass(module->GetClasses());
00919 TClassDocInfo* cdi = 0;
00920 UInt_t count = 0;
00921 UInt_t currentIndexEntry = 0;
00922 while ((cdi = (TClassDocInfo*) iClass())) {
00923 if (!cdi->IsSelected() || !cdi->HaveSource())
00924 continue;
00925
00926 TDictionary *classPtr = cdi->GetClass();
00927 if (!classPtr) {
00928 Error("CreateModuleIndex", "Unknown class '%s' !", cdi->GetName());
00929 continue;
00930 }
00931
00932 if (!count) {
00933 outputFile << "<h2>Class Index</h2>" << endl;
00934
00935 if (classNames.size() > 10) {
00936 outputFile << "<div id=\"indxShortX\"><h4>Jump to</h4>" << endl;
00937 UInt_t numSections = classNames.size() / 10;
00938 if (numSections < 10) numSections = 10;
00939 if (numSections > 50) numSections = 50;
00940
00941 GetIndexChars(classNames, numSections, indexChars);
00942 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
00943 outputFile << "<a href=\"#idx" << iIdxEntry << "\">";
00944 ReplaceSpecialChars(outputFile, indexChars[iIdxEntry].c_str());
00945 outputFile << "</a>" << endl;
00946 }
00947 outputFile << "</div><br />" << endl;
00948 }
00949
00950 outputFile << "<ul id=\"indx\">" << endl;
00951 }
00952
00953
00954 outputFile << "<li class=\"idxl" << (count++)%2 << "\">";
00955 if (currentIndexEntry < indexChars.size()
00956 && !strncmp(indexChars[currentIndexEntry].c_str(), cdi->GetName(),
00957 indexChars[currentIndexEntry].length()))
00958 outputFile << "<a name=\"idx" << currentIndexEntry++ << "\"></a>";
00959
00960 TString htmlFile(cdi->GetHtmlFileName());
00961 if (htmlFile.Length()) {
00962 outputFile << "<a href=\"";
00963 outputFile << htmlFile;
00964 outputFile << "\"><span class=\"typename\">";
00965 ReplaceSpecialChars(outputFile, classPtr->GetName());
00966 outputFile << "</span></a> ";
00967 } else {
00968 outputFile << "<span class=\"typename\">";
00969 ReplaceSpecialChars(outputFile, classPtr->GetName());
00970 outputFile << "</span> ";
00971 }
00972
00973
00974 ReplaceSpecialChars(outputFile, classPtr->GetTitle());
00975 outputFile << "</li>" << endl;
00976 }
00977
00978
00979 if (count)
00980 outputFile << "</ul>" << endl;
00981
00982
00983 WriteHtmlFooter(outputFile);
00984 }
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001 TIter iLib(fHtml->GetLibraryDependencies());
01002 TLibraryDocInfo* libinfo = 0;
01003 while ((libinfo = (TLibraryDocInfo*)iLib())) {
01004 if (!libinfo->GetName() || !libinfo->GetName()[0]) continue;
01005
01006 std::set<std::string>& deps = libinfo->GetDependencies();
01007 for (std::set<std::string>::iterator iDep = deps.begin();
01008 iDep != deps.end(); ++iDep) {
01009 Bool_t already_indirect = kFALSE;
01010 for (std::set<std::string>::const_iterator iDep2 = deps.begin();
01011 !already_indirect && iDep2 != deps.end(); ++iDep2) {
01012 if (iDep == iDep2) continue;
01013 TLibraryDocInfo* libinfo2 = (TLibraryDocInfo*)
01014 fHtml->GetLibraryDependencies()->FindObject(iDep2->c_str());
01015 if (!libinfo2) continue;
01016 const std::set<std::string>& deps2 = libinfo2->GetDependencies();
01017 already_indirect |= deps2.find(*iDep) != deps2.end();
01018 }
01019 if (already_indirect) {
01020 std::set<std::string>::iterator iRemove = iDep;
01021 --iDep;
01022 deps.erase(*iRemove);
01023 }
01024 }
01025 }
01026
01027 iLib.Reset();
01028 while ((libinfo = (TLibraryDocInfo*)iLib())) {
01029 if (!libinfo->GetName() || !libinfo->GetName()[0]) continue;
01030
01031 const std::set<std::string>& modules = libinfo->GetModules();
01032 if (modules.size() > 1) {
01033 sstrCluster << "subgraph cluster" << libinfo->GetName() << " {" << endl
01034 << "style=filled;" << endl
01035 << "color=lightgray;" << endl
01036 << "label=\"";
01037 if (!strcmp(libinfo->GetName(), "libCore"))
01038 sstrCluster << "Everything depends on ";
01039 sstrCluster << libinfo->GetName() << "\";" << endl;
01040
01041 for (std::set<std::string>::const_iterator iModule = modules.begin();
01042 iModule != modules.end(); ++iModule) {
01043 sstrCluster << "\"" << *iModule << "\" [style=filled,color=white,URL=\""
01044 << *iModule << "_Index.html\"];" << endl;
01045 }
01046 sstrCluster << endl
01047 << "}" << endl;
01048 } else {
01049
01050 sstrCluster << "\"" << *modules.begin()
01051 << "\" [label=\"" << libinfo->GetName()
01052 << "\",style=filled,color=lightgray,shape=box,URL=\""
01053 << *modules.begin() << "_Index.html\"];" << endl;
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063 const std::string& mod = *(modules.begin());
01064 const std::set<std::string>& deps = libinfo->GetDependencies();
01065 for (std::set<std::string>::const_iterator iDep = deps.begin();
01066 iDep != deps.end(); ++iDep) {
01067
01068 TLibraryDocInfo* depLibInfo = (TLibraryDocInfo*)
01069 fHtml->GetLibraryDependencies()->FindObject(iDep->c_str());
01070 if (!depLibInfo || depLibInfo->GetModules().empty())
01071 continue;
01072
01073 const std::string& moddep = *(depLibInfo->GetModules().begin());
01074 sstrDeps << "\"" << mod << "\" -> \"" << moddep << "\";" << endl;
01075 }
01076
01077 sstrDeps << "\"" << mod << "\" -> \"CONT\" [style=invis];" << endl;
01078 }
01079
01080 libDepDotFile << sstrCluster.str() << endl
01081 << sstrDeps.str();
01082 libDepDotFile << "}" << endl;
01083 libDepDotFile.close();
01084
01085 std::ofstream out(dotfilename + ".html");
01086 if (!out.good()) {
01087 Error("CreateModuleIndex", "Can't open file '%s.html' !",
01088 dotfilename.Data());
01089 return;
01090 }
01091
01092 Printf(fHtml->GetCounterFormat(), "", fHtml->GetCounter(), (dotfilename + ".html").Data());
01093
01094 WriteHtmlHeader(out, "Library Dependencies");
01095
01096 WriteTopLinks(out, 0);
01097
01098 out << "<h1>Library Dependencies</h1>" << endl;
01099
01100 RunDot(dotfilename, &out, kFdp);
01101
01102 out << "<img alt=\"Library Dependencies\" class=\"classcharts\" usemap=\"#Map" << title << "\" src=\"" << title << ".png\"/>" << endl;
01103
01104
01105 WriteHtmlFooter(out);
01106 }
01107
01108
01109 void TDocOutput::CreateProductIndex()
01110 {
01111
01112
01113
01114
01115
01116 TString outFile("index.html");
01117 gSystem->PrependPathName(GetHtml()->GetOutputDir(), outFile);
01118 std::ofstream out(outFile);
01119
01120 if (!out.good()) {
01121 Error("CreateProductIndex", "Can't open file '%s' !", outFile.Data());
01122 return;
01123 }
01124
01125 Printf(fHtml->GetCounterFormat(), "", "", outFile.Data());
01126
01127 WriteHtmlHeader(out, GetHtml()->GetProductName() + " Reference Guide");
01128
01129 WriteTopLinks(out, 0);
01130
01131 out << "<h1>" << GetHtml()->GetProductName() + " Reference Guide</h1>" << std::endl;
01132
01133 TString prodDoc;
01134 if (GetHtml()->GetPathDefinition().GetDocDir("", prodDoc))
01135 ProcessDocInDir(out, prodDoc, GetHtml()->GetOutputDir(), "./");
01136
01137 WriteModuleLinks(out);
01138
01139 out << "<h2>Chapters</h2>" << std::endl
01140 << "<h3><a href=\"./ClassIndex.html\">Class Index</a></h3>" << std::endl
01141 << "<p>A complete list of all classes defined in " << GetHtml()->GetProductName() << "</p>" << std::endl
01142 << "<h3><a href=\"./ClassHierarchy.html\">Class Hierarchy</a></h3>" << std::endl
01143 << "<p>A hierarchy graph of all classes, showing each class's base and derived classes</p>" << std::endl
01144 << "<h3><a href=\"./ListOfTypes.html\">Type Index</a></h3>" << std::endl
01145 << "<p>A complete list of all types</p>" << std::endl
01146 << "<h3><a href=\"./LibraryDependencies.html\">Library Dependency</a></h3>" << std::endl
01147 << "<p>A diagram showing all of " << GetHtml()->GetProductName() << "'s libraries and their dependencies</p>" << std::endl;
01148
01149 WriteHtmlFooter(out);
01150 }
01151
01152
01153 void TDocOutput::CreateClassTypeDefs()
01154 {
01155
01156 TDocParser parser(*this);
01157
01158 TIter iClass(GetHtml()->GetListOfClasses());
01159 TClassDocInfo* cdi = 0;
01160 while ((cdi = (TClassDocInfo*) iClass())) {
01161 if (cdi->GetListOfTypedefs().IsEmpty())
01162 continue;
01163 TIter iTypedefs(&cdi->GetListOfTypedefs());
01164 TDataType* dt = 0;
01165 while ((dt = (TDataType*) iTypedefs())) {
01166 if (gDebug > 0)
01167 Info("CreateClassTypeDefs", "Creating typedef %s to class %s",
01168 dt->GetName(), cdi->GetName());
01169
01170 TString filename(dt->GetName());
01171 NameSpace2FileName(filename);
01172
01173 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
01174
01175 filename += ".html";
01176
01177
01178 std::ofstream outfile(filename);
01179
01180 if (!outfile.good()) {
01181 Error("CreateClassTypeDefs", "Can't open file '%s' !", filename.Data());
01182 continue;
01183 }
01184
01185 WriteHtmlHeader(outfile, dt->GetName());
01186
01187 outfile << "<a name=\"TopOfPage\"></a>" << endl;
01188
01189 TString dtName(dt->GetName());
01190 ReplaceSpecialChars(dtName);
01191 TString sTitle("typedef ");
01192 sTitle += dtName;
01193
01194 TClass* cls = dynamic_cast<TClass*>(cdi->GetClass());
01195 if (cls) {
01196
01197
01198 TString sInclude;
01199 TString sLib;
01200 const char* lib=cls->GetSharedLibs();
01201 GetHtml()->GetPathDefinition().GetIncludeAs(cls, sInclude);
01202 if (lib) {
01203 char* libDup=StrDup(lib);
01204 char* libDupSpace=strchr(libDup,' ');
01205 if (libDupSpace) *libDupSpace = 0;
01206 char* libDupEnd=libDup+strlen(libDup);
01207 while (libDupEnd!=libDup)
01208 if (*(--libDupEnd)=='.') {
01209 *libDupEnd=0;
01210 break;
01211 }
01212 sLib = libDup;
01213 delete[] libDup;
01214 }
01215 outfile << "<script type=\"text/javascript\">WriteFollowPageBox('"
01216 << sTitle << "','" << sLib << "','" << sInclude << "');</script>" << endl;
01217 }
01218
01219 TString modulename;
01220 fHtml->GetModuleNameForClass(modulename, cls);
01221 TModuleDocInfo* module = (TModuleDocInfo*) fHtml->GetListOfModules()->FindObject(modulename);
01222 WriteTopLinks(outfile, module, dt->GetName());
01223
01224 outfile << "<div class=\"dropshadow\"><div class=\"withshadow\">";
01225 outfile << "<h1>" << sTitle << "</h1>" << endl
01226 << "<div class=\"classdescr\">" << endl;
01227
01228 outfile << dtName << " is a typedef to ";
01229 std::string shortClsName(fHtml->ShortType(cdi->GetName()));
01230 parser.DecorateKeywords(outfile, shortClsName.c_str());
01231 outfile << endl
01232 << "</div>" << std::endl
01233 << "</div></div><div style=\"clear:both;\"></div>" << std::endl;
01234
01235
01236 outfile << endl << "<div id=\"datamembers\">" << endl
01237 << "<table class=\"data\" cellspacing=\"0\">" << endl;
01238 outfile << "<tr class=\"data";
01239 outfile << "\"><td class=\"datatype\">typedef ";
01240 parser.DecorateKeywords(outfile, dt->GetFullTypeName());
01241 outfile << "</td><td class=\"dataname\">";
01242 ReplaceSpecialChars(outfile, dt->GetName());
01243 if (dt->GetTitle() && dt->GetTitle()[0]) {
01244 outfile << "</td><td class=\"datadesc\">";
01245 ReplaceSpecialChars(outfile, dt->GetTitle());
01246 } else outfile << "</td><td>";
01247 outfile << "</td></tr>" << endl
01248 << "</table></div>" << endl;
01249
01250
01251 WriteHtmlFooter(outfile);
01252
01253 }
01254 }
01255 }
01256
01257
01258 void TDocOutput::CreateTypeIndex()
01259 {
01260
01261
01262
01263 TString outFile("ListOfTypes.html");
01264 gSystem->PrependPathName(fHtml->GetOutputDir(), outFile);
01265 std::ofstream typesList(outFile);
01266
01267 if (!typesList.good()) {
01268 Error("CreateTypeIndex", "Can't open file '%s' !", outFile.Data());
01269 return;
01270 }
01271
01272 Printf(fHtml->GetCounterFormat(), "", "", outFile.Data());
01273
01274
01275 WriteHtmlHeader(typesList, "List of data types");
01276 typesList << "<h2> List of data types </h2>" << endl;
01277
01278 typesList << "<dl><dd>" << endl;
01279
01280
01281 std::vector<std::string> typeNames(gROOT->GetListOfTypes()->GetSize());
01282
01283 {
01284 TDataType *type;
01285 TIter nextType(gROOT->GetListOfTypes());
01286 size_t tnIdx = 0;
01287
01288 while ((type = (TDataType *) nextType()))
01289
01290 if (*type->GetTitle() && !strchr(type->GetName(), '(')
01291 && !( strchr(type->GetName(), '<') && strchr(type->GetName(),'>'))
01292 && type->GetName())
01293 typeNames[tnIdx++] = type->GetName();
01294 typeNames.resize(tnIdx);
01295 }
01296
01297 sort_strlist_stricmp(typeNames);
01298
01299 std::vector<std::string> indexChars;
01300 if (typeNames.size() > 10) {
01301 typesList << "<div id=\"indxShortX\"><h4>Jump to</h4>" << endl;
01302
01303 GetIndexChars(typeNames, 10 , indexChars);
01304 for (UInt_t iIdxEntry = 0; iIdxEntry < indexChars.size(); ++iIdxEntry) {
01305 typesList << "<a href=\"#idx" << iIdxEntry << "\">";
01306 ReplaceSpecialChars(typesList, indexChars[iIdxEntry].c_str());
01307 typesList << "</a>" << endl;
01308 }
01309 typesList << "</div><br />" << endl;
01310 }
01311
01312 typesList << "<ul id=\"indx\">" << endl;
01313
01314 int idx = 0;
01315 UInt_t currentIndexEntry = 0;
01316
01317 for (std::vector<std::string>::iterator iTypeName = typeNames.begin();
01318 iTypeName != typeNames.end(); ++iTypeName) {
01319 TDataType* type = gROOT->GetType(iTypeName->c_str(), kFALSE);
01320 typesList << "<li class=\"idxl" << idx%2 << "\">";
01321 if (currentIndexEntry < indexChars.size()
01322 && !strncmp(indexChars[currentIndexEntry].c_str(), iTypeName->c_str(),
01323 indexChars[currentIndexEntry].length()))
01324 typesList << "<a name=\"idx" << currentIndexEntry++ << "\"></a>" << endl;
01325 typesList << "<a name=\"";
01326 ReplaceSpecialChars(typesList, iTypeName->c_str());
01327 typesList << "\"><span class=\"typename\">";
01328 ReplaceSpecialChars(typesList, iTypeName->c_str());
01329 typesList << "</span></a> ";
01330 ReplaceSpecialChars(typesList, type->GetTitle());
01331 typesList << "</li>" << endl;
01332 ++idx;
01333 }
01334 typesList << "</ul>" << endl;
01335
01336
01337 WriteHtmlFooter(typesList);
01338
01339
01340 typesList.close();
01341
01342 }
01343
01344
01345
01346 void TDocOutput::DecorateEntityBegin(TString& str, Ssiz_t& pos, TDocParser::EParseContext type)
01347 {
01348
01349
01350
01351
01352
01353
01354 Ssiz_t originalLen = str.Length();
01355
01356 switch (type) {
01357 case TDocParser::kCode: break;
01358 case TDocParser::kComment:
01359 str.Insert(pos, "<span class=\"comment\">");
01360 break;
01361 case TDocParser::kDirective:
01362 break;
01363 case TDocParser::kString:
01364 str.Insert(pos, "<span class=\"string\">");
01365 break;
01366 case TDocParser::kKeyword:
01367 str.Insert(pos, "<span class=\"keyword\">");
01368 break;
01369 case TDocParser::kCPP:
01370 str.Insert(pos, "<span class=\"cpp\">");
01371 break;
01372 case TDocParser::kVerbatim:
01373 str.Insert(pos, "<pre>");
01374 break;
01375 default:
01376 Error("DecorateEntityBegin", "Unhandled / invalid entity type %d!", (Int_t)type);
01377 return;
01378 }
01379
01380 Ssiz_t addedLen = str.Length() - originalLen;
01381 pos += addedLen;
01382 }
01383
01384
01385 void TDocOutput::DecorateEntityEnd(TString& str, Ssiz_t& pos, TDocParser::EParseContext type)
01386 {
01387
01388
01389
01390
01391
01392
01393
01394 Ssiz_t originalLen = str.Length();
01395
01396 switch (type) {
01397 case TDocParser::kCode: break;
01398 case TDocParser::kComment:
01399 str.Insert(pos, "</span>");
01400 break;
01401 case TDocParser::kDirective:
01402 break;
01403 case TDocParser::kString:
01404 str.Insert(pos, "</span>");
01405 break;
01406 case TDocParser::kKeyword:
01407 str.Insert(pos, "</span>");
01408 break;
01409 case TDocParser::kCPP:
01410 str.Insert(pos, "</span>");
01411 break;
01412 case TDocParser::kVerbatim:
01413 str.Insert(pos, "</pre>");
01414 break;
01415 default:
01416 Error("DecorateEntityBegin", "Unhandled / invalid entity type %d!", (Int_t)type);
01417 return;
01418 }
01419 Ssiz_t addedLen = str.Length() - originalLen;
01420 pos += addedLen;
01421 }
01422
01423
01424 void TDocOutput::FixupAuthorSourceInfo(TString& authors)
01425 {
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435 TString original(authors);
01436 authors = "";
01437
01438 TString author;
01439 Ssiz_t pos = 0;
01440 Bool_t firstAuthor = kTRUE;
01441 while (original.Tokenize(author, pos, ",")) {
01442 author.Strip(TString::kBoth);
01443
01444 if (!firstAuthor)
01445 authors += ", ";
01446 firstAuthor = kFALSE;
01447
01448
01449 Ssiz_t cLink = author.First('<');
01450 if (cLink != kNPOS) {
01451
01452
01453 Ssiz_t endLink = author.Index(">", cLink + 1);
01454 if(endLink == kNPOS)
01455 endLink = author.Length();
01456 authors += "<a href=\"";
01457 authors += author(cLink + 1, endLink - (cLink + 1));
01458 authors += "\">";
01459 authors += author(0, cLink);
01460 authors += "</a>";
01461 if (endLink != author.Length())
01462 authors += author(endLink + 1, author.Length());
01463 } else {
01464 authors += "<a href=\"";
01465 authors += fHtml->GetXwho();
01466
01467
01468 TString namePart;
01469 Ssiz_t posNamePart = 0;
01470 Bool_t firstNamePart = kTRUE;
01471 while (author.Tokenize(namePart, posNamePart, " ")) {
01472 namePart.Strip(TString::kBoth);
01473 if (!namePart.Length())
01474 continue;
01475 if (isdigit(namePart[0])) continue;
01476 if (!firstNamePart)
01477 authors += '+';
01478 firstNamePart = kFALSE;
01479 authors += namePart;
01480 }
01481 authors += "\">";
01482 authors += author;
01483 authors += "</a>";
01484 }
01485 }
01486 }
01487
01488
01489 Bool_t TDocOutput::IsModified(TClass * classPtr, EFileType type)
01490 {
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 TString sourceFile;
01503 TString classname(classPtr->GetName());
01504 TString filename;
01505 TString dir;
01506
01507 switch (type) {
01508 case kSource:
01509 if (classPtr->GetImplFileLine()) {
01510 fHtml->GetImplFileName(classPtr, kTRUE, sourceFile);
01511 } else {
01512 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
01513 }
01514 dir = "src";
01515 gSystem->PrependPathName(fHtml->GetOutputDir(), dir);
01516 filename = classname;
01517 NameSpace2FileName(filename);
01518 gSystem->PrependPathName(dir, filename);
01519 if (classPtr->GetImplFileLine())
01520 filename += ".cxx.html";
01521 else
01522 filename += ".h.html";
01523 break;
01524
01525 case kInclude:
01526 fHtml->GetDeclFileName(classPtr, kFALSE, filename);
01527 filename = gSystem->BaseName(filename);
01528 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
01529 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
01530 break;
01531
01532 case kTree:
01533 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
01534 NameSpace2FileName(classname);
01535 gSystem->PrependPathName(fHtml->GetOutputDir(), classname);
01536 filename = classname;
01537 filename += "_Tree.pdf";
01538 break;
01539
01540 case kDoc:
01541 if (classPtr->GetImplFileLine()) {
01542 fHtml->GetImplFileName(classPtr, kTRUE, sourceFile);
01543 } else {
01544 fHtml->GetDeclFileName(classPtr, kTRUE, sourceFile);
01545 }
01546 filename = classname;
01547 NameSpace2FileName(filename);
01548 gSystem->PrependPathName(fHtml->GetOutputDir(), filename);
01549 filename += ".html";
01550 break;
01551
01552 default:
01553 Error("IsModified", "Unknown file type !");
01554 }
01555
01556 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
01557
01558
01559 Long64_t size;
01560 Long_t id, flags, sModtime, dModtime;
01561
01562 if (!(gSystem->GetPathInfo(sourceFile, &id, &size, &flags, &sModtime)))
01563 if (!(gSystem->GetPathInfo(filename, &id, &size, &flags, &dModtime)))
01564 return (sModtime > dModtime);
01565
01566 return kTRUE;
01567 }
01568
01569
01570
01571 void TDocOutput::NameSpace2FileName(TString& name)
01572 {
01573
01574
01575
01576
01577
01578 TString encScope(name);
01579 Ssiz_t posTemplate = encScope.Index('<');
01580 if (posTemplate != kNPOS) {
01581
01582 name = fHtml->ShortType(name);
01583 TString templateArgs = encScope(posTemplate, encScope.Length());
01584 encScope.Remove(posTemplate, encScope.Length());
01585
01586
01587
01588
01589
01590 Ssiz_t posName = encScope.Last(':');
01591 if (posName != kNPOS) {
01592 Int_t numDblColumn = encScope.CountChar(':');
01593 while (numDblColumn > 1) {
01594 encScope.Remove(posName + 1, encScope.Length());
01595 numDblColumn -= 2;
01596 templateArgs.ReplaceAll(encScope, TString::Format("-p%d", numDblColumn / 2));
01597 encScope.Remove(encScope.Length() - 2, 2);
01598 posName = encScope.Last(':');
01599 if (posName == kNPOS)
01600 break;
01601 }
01602 name.Replace(posTemplate, name.Length(), templateArgs);
01603 }
01604 }
01605
01606 if (name.Length() > 240) {
01607
01608
01609
01610
01611 TString hash;
01612 TDocParser::AnchorFromLine(name, hash);
01613 hash.Prepend("-h");
01614 Ssiz_t posDot = name.Last('.');
01615 TString ext;
01616 if (posDot != kNPOS)
01617 ext = name(posDot, name.Length());
01618 Ssiz_t namelen = 240 - hash.Length() - ext.Length();
01619 name = name(0, namelen) + hash + ext;
01620 }
01621
01622 const char* replaceWhat = ":<> ,~=";
01623 for (Ssiz_t i=0; i < name.Length(); ++i)
01624 if (strchr(replaceWhat, name[i]))
01625 name[i] = '_';
01626 }
01627
01628
01629 void TDocOutput::ProcessDocInDir(std::ostream& out, const char* indir,
01630 const char* outdir, const char* linkdir)
01631 {
01632
01633
01634
01635
01636
01637
01638 R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
01639
01640 void * dirHandle = gSystem->OpenDirectory(indir);
01641 if (!dirHandle) return;
01642
01643 const char* entry = 0;
01644 std::list<std::string> files;
01645 while ((entry = gSystem->GetDirEntry(dirHandle))) {
01646 FileStat_t stat;
01647 TString filename(entry);
01648 gSystem->PrependPathName(indir, filename);
01649 if (gSystem->GetPathInfo(filename, stat))
01650 continue;
01651 if (!R_ISREG(stat.fMode)) continue;
01652
01653 if (TString(entry).BeginsWith("index.", TString::kIgnoreCase)) {
01654
01655
01656 if (filename.EndsWith(".txt", TString::kIgnoreCase)) {
01657 std::ifstream in(filename);
01658 if (in) {
01659 out << "<pre>";
01660 TDocParser parser(*this);
01661 parser.Convert(out, in, "./", kFALSE , kTRUE );
01662 out << "</pre>";
01663 }
01664 } else if (filename.EndsWith(".html", TString::kIgnoreCase)) {
01665 std::ifstream in(filename);
01666 TString line;
01667 while (in) {
01668 if (!line.ReadLine(in)) break;
01669 out << line << endl;
01670 }
01671 } else
01672 files.push_back(filename.Data());
01673 } else
01674 files.push_back(filename.Data());
01675 }
01676
01677 std::stringstream furtherReading;
01678 files.sort();
01679 for (std::list<std::string>::const_iterator iFile = files.begin();
01680 iFile != files.end(); ++iFile) {
01681 TString filename(iFile->c_str());
01682 if (gSystem->AccessPathName(outdir))
01683 if (gSystem->mkdir(outdir, kTRUE) == -1)
01684
01685 Error("CreateModuleIndex", "Cannot create output directory %s", outdir);
01686
01687 TString outfile(gSystem->BaseName(filename));
01688 gSystem->PrependPathName(outdir, outfile);
01689
01690 if (!filename.EndsWith(".txt", TString::kIgnoreCase)
01691 && !filename.EndsWith(".html", TString::kIgnoreCase)) {
01692
01693 if (gSystem->CopyFile(filename, outfile, kTRUE) == -1)
01694 continue;
01695 continue;
01696 }
01697
01698
01699 if (outfile.EndsWith(".txt", TString::kIgnoreCase)) {
01700
01701 outfile.Remove(outfile.Length()-3, 3);
01702 outfile += "html";
01703 std::ifstream inFurther(filename);
01704 std::ofstream outFurther(outfile);
01705 if (inFurther && outFurther) {
01706 outFurther << "<pre>";
01707 TDocParser parser(*this);
01708 parser.Convert(outFurther, inFurther, "../", kFALSE , kTRUE );
01709 outFurther << "</pre>";
01710 }
01711 } else {
01712 if (gSystem->CopyFile(filename, outfile, kTRUE) == -1)
01713 continue;
01714 }
01715 TString showname(gSystem->BaseName(outfile));
01716 furtherReading << "<a class=\"linkeddoc\" href=\"" << linkdir << "/" << showname << "\">";
01717 showname.Remove(showname.Length() - 5, 5);
01718 showname.ReplaceAll("_", " ");
01719 ReplaceSpecialChars(furtherReading, showname);
01720 furtherReading << "</a> " << endl;
01721 }
01722
01723 gSystem->FreeDirectory(dirHandle);
01724 if (furtherReading.str().length())
01725 out << "<h3>Further Reading</h3><div id=\"furtherreading\">" << endl
01726 << furtherReading.str() << "</div><h3>List of Classes</h3>" << endl;
01727 }
01728
01729
01730 void TDocOutput::ReferenceEntity(TSubString& str, TClass* entity, const char* comment )
01731 {
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746 TString link;
01747 fHtml->GetHtmlFileName(entity, link);
01748
01749 if (comment && !strcmp(comment, entity->GetName()))
01750 comment = "";
01751
01752 AddLink(str, link, comment);
01753 }
01754
01755
01756 void TDocOutput::ReferenceEntity(TSubString& str, TDataMember* entity, const char* comment )
01757 {
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771 TString link;
01772 TClass* scope = entity->GetClass();
01773 fHtml->GetHtmlFileName(scope, link);
01774 link += "#";
01775
01776 TString mangledName;
01777 if (scope) {
01778 mangledName = scope->GetName();
01779 NameSpace2FileName(mangledName);
01780 link += mangledName;
01781 link += ":";
01782 }
01783
01784 mangledName = entity->GetName();
01785 NameSpace2FileName(mangledName);
01786 link += mangledName;
01787
01788 TString description;
01789 if (!comment) {
01790 description = entity->GetFullTypeName();
01791 description += " ";
01792 if (scope) {
01793 description += scope->GetName();
01794 description += "::";
01795 }
01796 description += entity->GetName();
01797 comment = description.Data();
01798 }
01799
01800 if (comment && !strcmp(comment, entity->GetName()))
01801 comment = "";
01802
01803 AddLink(str, link, comment);
01804 }
01805
01806
01807 void TDocOutput::ReferenceEntity(TSubString& str, TDataType* entity, const char* comment )
01808 {
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823 TString mangledEntity(entity->GetName());
01824 NameSpace2FileName(mangledEntity);
01825
01826 TString link;
01827 TClassDocInfo* cdi = 0;
01828 bool isClassTypedef = entity->GetType() == -1;
01829 if (isClassTypedef)
01830
01831 isClassTypedef = isClassTypedef && (entity->Property() & 7);
01832 if (isClassTypedef) {
01833 std::string shortTypeName(fHtml->ShortType(entity->GetFullTypeName()));
01834 cdi = (TClassDocInfo*) GetHtml()->GetListOfClasses()->FindObject(shortTypeName.c_str());
01835 }
01836 if (cdi) {
01837 link = mangledEntity + ".html";
01838 } else {
01839 link = "ListOfTypes.html#";
01840 link += mangledEntity;
01841 }
01842
01843 if (comment && !strcmp(comment, entity->GetName()))
01844 comment = "";
01845
01846 AddLink(str, link, comment);
01847 }
01848
01849
01850 void TDocOutput::ReferenceEntity(TSubString& str, TMethod* entity, const char* comment )
01851 {
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866 TString link;
01867 TClass* scope = entity->GetClass();
01868 fHtml->GetHtmlFileName(scope, link);
01869 link += "#";
01870
01871 TString mangledName(scope->GetName());
01872 NameSpace2FileName(mangledName);
01873 link += mangledName;
01874 link += ":";
01875
01876 mangledName = entity->GetName();
01877 NameSpace2FileName(mangledName);
01878 link += mangledName;
01879
01880 TString description;
01881 if (!comment && entity->GetClass()) {
01882 TIter iMeth(scope->GetListOfMethods());
01883 TMethod* mCand = 0;
01884 while ((mCand = (TMethod*)iMeth()))
01885 if (!strcmp(mCand->GetName(), entity->GetName())) {
01886 if (description.Length()) {
01887 description += " or overloads";
01888 break;
01889 }
01890 description = mCand->GetPrototype();
01891 }
01892 comment = description.Data();
01893 }
01894
01895 if (comment && !strcmp(comment, entity->GetName()))
01896 comment = "";
01897
01898 AddLink(str, link, comment);
01899 }
01900
01901
01902 Bool_t TDocOutput::ReferenceIsRelative(const char* reference) const
01903 {
01904
01905
01906
01907
01908 return !reference ||
01909 strncmp(reference, "http", 4) ||
01910 (strncmp(reference + 4, "://", 3) && strncmp(reference + 4, "s://", 4));
01911 }
01912
01913
01914 const char* TDocOutput::ReplaceSpecialChars(char c)
01915 {
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930 switch (c) {
01931 case '<': return "<";
01932 case '&': return "&";
01933 case '>': return ">";
01934 };
01935 return 0;
01936 }
01937
01938
01939 void TDocOutput::ReplaceSpecialChars(TString& text, Ssiz_t &pos)
01940 {
01941
01942
01943
01944
01945
01946
01947
01948
01949 const char c = text[pos];
01950 const char* replaced = ReplaceSpecialChars(c);
01951 if (replaced) {
01952 text.Replace(pos, 1, replaced);
01953 pos += strlen(replaced) - 1;
01954 }
01955 ++pos;
01956 }
01957
01958
01959 void TDocOutput::ReplaceSpecialChars(TString& text) {
01960
01961
01962
01963
01964
01965 Ssiz_t pos = 0;
01966 while (pos < text.Length())
01967 ReplaceSpecialChars(text, pos);
01968 }
01969
01970
01971 void TDocOutput::ReplaceSpecialChars(std::ostream& out, const char *string)
01972 {
01973
01974
01975
01976
01977
01978
01979
01980 while (string && *string) {
01981 const char* replaced = ReplaceSpecialChars(*string);
01982 if (replaced)
01983 out << replaced;
01984 else
01985 out << *string;
01986 string++;
01987 }
01988 }
01989
01990
01991 Bool_t TDocOutput::RunDot(const char* filename, std::ostream* outMap ,
01992 EGraphvizTool gvwhat ) {
01993
01994
01995
01996 if (!fHtml->HaveDot())
01997 return kFALSE;
01998
01999 TString runDot;
02000 switch (gvwhat) {
02001 case kNeato: runDot = "neato"; break;
02002 case kFdp: runDot = "fdp"; break;
02003 case kCirco: runDot = "circo"; break;
02004 default: runDot = "dot";
02005 };
02006 if (fHtml->GetDotDir() && *fHtml->GetDotDir())
02007 gSystem->PrependPathName(fHtml->GetDotDir(), runDot);
02008 runDot += " -q1 -Tpng -o";
02009 runDot += filename;
02010 runDot += ".png ";
02011 if (outMap) {
02012 runDot += "-Tcmap -o";
02013 runDot += filename;
02014 runDot += ".map ";
02015 }
02016 runDot += filename;
02017 runDot += ".dot";
02018
02019 if (gDebug > 3)
02020 Info("RunDot", "Running: %s", runDot.Data());
02021 Int_t retDot = gSystem->Exec(runDot);
02022 if (gDebug < 4 && !retDot)
02023 gSystem->Unlink(Form("%s.dot", filename));
02024
02025 if (!retDot && outMap) {
02026 ifstream inmap(Form("%s.map", filename));
02027 std::string line;
02028 std::getline(inmap, line);
02029 if (inmap && !inmap.eof()) {
02030 *outMap << "<map name=\"Map" << gSystem->BaseName(filename)
02031 << "\" id=\"Map" << gSystem->BaseName(filename) << "\">" << endl;
02032 while (inmap && !inmap.eof()) {
02033 if (line.compare(0, 6, "<area ") == 0) {
02034 size_t posEndTag = line.find('>');
02035 if (posEndTag != std::string::npos)
02036 line.replace(posEndTag, 1, "/>");
02037 }
02038 *outMap << line << endl;
02039 std::getline(inmap, line);
02040 }
02041 *outMap << "</map>" << endl;
02042 }
02043 inmap.close();
02044 if (gDebug < 7)
02045 gSystem->Unlink(Form("%s.map", filename));
02046 }
02047
02048 if (retDot) {
02049 Error("RunDot", "Error running %s!", runDot.Data());
02050 fHtml->SetFoundDot(kFALSE);
02051 return kFALSE;
02052 }
02053
02054 return kTRUE;
02055 }
02056
02057
02058
02059 void TDocOutput::WriteHtmlHeader(std::ostream& out, const char *titleNoSpecial,
02060 const char* dir , TClass *cls ,
02061 const char* header)
02062 {
02063
02064
02065
02066
02067 ifstream addHeaderFile(header);
02068
02069 if (!addHeaderFile.good()) {
02070 Warning("THtml::WriteHtmlHeader",
02071 "Can't open html header file %s\n", header);
02072 return;
02073 }
02074
02075 TString declFileName;
02076 if (cls) fHtml->GetDeclFileName(cls, kFALSE, declFileName);
02077 TString implFileName;
02078 if (cls) fHtml->GetImplFileName(cls, kFALSE, implFileName);
02079
02080 const TString& charset = GetHtml()->GetCharset();
02081 TDatime date;
02082 TString strDate(date.AsString());
02083 TString line;
02084
02085 while (!addHeaderFile.eof()) {
02086
02087 line.ReadLine(addHeaderFile, kFALSE);
02088 if (addHeaderFile.eof())
02089 break;
02090
02091 if (line) {
02092
02093 if (!cls && (
02094 line.Index("%CLASS%") != kNPOS ||
02095 line.Index("%INCFILE%") != kNPOS ||
02096 line.Index("%SRCFILE%") != kNPOS))
02097 continue;
02098
02099 TString txt(line);
02100
02101 txt.ReplaceAll("%TITLE%", titleNoSpecial);
02102 txt.ReplaceAll("%DATE%", strDate);
02103 txt.ReplaceAll("%RELDIR%", dir);
02104 txt.ReplaceAll("%CHARSET%", charset);
02105
02106 if (cls) {
02107 txt.ReplaceAll("%CLASS%", cls->GetName());
02108 txt.ReplaceAll("%INCFILE%", declFileName);
02109 txt.ReplaceAll("%SRCFILE%", implFileName);
02110 }
02111
02112 out << txt << endl;
02113 }
02114 }
02115 }
02116
02117
02118 void TDocOutput::WriteHtmlHeader(std::ostream& out, const char *title,
02119 const char* dir , TClass *cls)
02120 {
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146 TString userHeader = GetHtml()->GetHeader();
02147 TString noSpecialCharTitle(title);
02148 ReplaceSpecialChars(noSpecialCharTitle);
02149
02150 Ssiz_t lenUserHeader = userHeader.Length();
02151
02152 Bool_t bothHeaders = lenUserHeader > 0 && userHeader[lenUserHeader - 1] == '+';
02153 if (lenUserHeader == 0 || bothHeaders) {
02154 TString header("header.html");
02155 gSystem->PrependPathName(fHtml->GetEtcDir(), header);
02156 WriteHtmlHeader(out, noSpecialCharTitle, dir, cls, header);
02157 }
02158
02159 if (lenUserHeader != 0) {
02160 if (bothHeaders)
02161 userHeader.Remove(lenUserHeader - 1);
02162 WriteHtmlHeader(out, noSpecialCharTitle, dir, cls, userHeader);
02163 };
02164 }
02165
02166
02167 void TDocOutput::WriteHtmlFooter(std::ostream& out, const char* ,
02168 const char* lastUpdate, const char* author,
02169 const char* copyright, const char* footer)
02170 {
02171
02172
02173
02174
02175 static const char* templateSITags[TDocParser::kNumSourceInfos] = { "%UPDATE%", "%AUTHOR%", "%COPYRIGHT%", "%CHANGED%", "%GENERATED%"};
02176
02177 TString today;
02178 TDatime dtToday;
02179 today.Form("%d-%02d-%02d %02d:%02d", dtToday.GetYear(), dtToday.GetMonth(), dtToday.GetDay(), dtToday.GetHour(), dtToday.GetMinute());
02180
02181 TString datimeString;
02182 if (!lastUpdate || !strlen(lastUpdate)) {
02183 lastUpdate = today;
02184 }
02185 const char* siValues[TDocParser::kNumSourceInfos] = { lastUpdate, author, copyright, lastUpdate, today };
02186
02187 ifstream addFooterFile(footer);
02188
02189 if (!addFooterFile.good()) {
02190 Warning("THtml::WriteHtmlFooter",
02191 "Can't open html footer file %s\n", footer);
02192 return;
02193 }
02194
02195 TString line;
02196 while (!addFooterFile.eof()) {
02197
02198 line.ReadLine(addFooterFile, kFALSE);
02199 if (addFooterFile.eof())
02200 break;
02201
02202 if (!line)
02203 continue;
02204
02205 for (Int_t siTag = 0; siTag < (Int_t) TDocParser::kNumSourceInfos; ++siTag) {
02206 Ssiz_t siPos = line.Index(templateSITags[siTag]);
02207 if (siPos != kNPOS) {
02208 if (siValues[siTag] && siValues[siTag][0])
02209 line.Replace(siPos, strlen(templateSITags[siTag]), siValues[siTag]);
02210 else
02211 line = "";
02212 }
02213 }
02214
02215 out << line << std::endl;
02216 }
02217
02218 }
02219
02220
02221 void TDocOutput::WriteHtmlFooter(std::ostream& out, const char *dir,
02222 const char *lastUpdate, const char *author,
02223 const char *copyright)
02224 {
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245 out << endl;
02246
02247 TString userFooter = GetHtml()->GetFooter();
02248
02249 if (userFooter.Length() != 0) {
02250 TString footer(userFooter);
02251 if (footer.EndsWith("+"))
02252 footer.Remove(footer.Length() - 1);
02253 WriteHtmlFooter(out, dir, lastUpdate, author, copyright, footer);
02254 };
02255
02256 if (userFooter.Length() == 0 || userFooter.EndsWith("+")) {
02257 TString footer("footer.html");
02258 gSystem->PrependPathName(fHtml->GetEtcDir(), footer);
02259 WriteHtmlFooter(out, dir, lastUpdate, author, copyright, footer);
02260 }
02261 }
02262
02263
02264 void TDocOutput::WriteModuleLinks(std::ostream& out)
02265 {
02266
02267
02268 if (fHtml->GetListOfModules()->GetSize()) {
02269 out << "<div id=\"indxModules\"><h4>Modules</h4>" << endl;
02270
02271 fHtml->SortListOfModules();
02272 TIter iModule(fHtml->GetListOfModules());
02273 TModuleDocInfo* module = 0;
02274 while ((module = (TModuleDocInfo*) iModule())) {
02275 if (!module->GetName() || strchr(module->GetName(), '/'))
02276 continue;
02277 if (module->IsSelected()) {
02278 TString name(module->GetName());
02279 name.ToUpper();
02280 out << "<a href=\"" << name << "_Index.html\">"
02281 << name << "</a>" << endl;
02282 }
02283 }
02284 out<< "</div><br />" << endl;
02285 }
02286 }
02287
02288
02289 void TDocOutput::WriteLineNumbers(std::ostream& out, Long_t nLines, const TString& infileBase) const
02290 {
02291
02292
02293
02294
02295
02296 out << "<div id=\"linenums\">";
02297 for (Long_t i = 0; i < nLines; ++i) {
02298
02299 out << "<div class=\"ln\"> <span class=\"lnfile\">" << infileBase
02300 << ":</span><a name=\"" << i + 1 << "\" href=\"#" << i + 1
02301 << "\" class=\"ln\">" << i + 1 << "</a></div>";
02302 }
02303 out << "</div>" << std::endl;
02304
02305 }
02306
02307
02308 void TDocOutput::WriteModuleLinks(std::ostream& out, TModuleDocInfo* super)
02309 {
02310
02311
02312 if (super->GetSub().GetSize()) {
02313 TString superName(super->GetName());
02314 superName.ToUpper();
02315 out << "<div id=\"indxModules\"><h4>" << superName << " Modules</h4>" << endl;
02316
02317 super->GetSub().Sort();
02318 TIter iModule(&super->GetSub());
02319 TModuleDocInfo* module = 0;
02320 while ((module = (TModuleDocInfo*) iModule())) {
02321 if (module->IsSelected()) {
02322 TString name(module->GetName());
02323 name.ToUpper();
02324 TString link(name);
02325 link.ReplaceAll("/", "_");
02326 Ssiz_t posSlash = name.Last('/');
02327 if (posSlash != kNPOS)
02328 name.Remove(0, posSlash + 1);
02329 out << "<a href=\"" << link << "_Index.html\">" << name << "</a>" << endl;
02330 }
02331 }
02332 out<< "</div><br />" << endl;
02333 }
02334 }
02335
02336
02337 void TDocOutput::WriteSearch(std::ostream& out)
02338 {
02339
02340
02341
02342
02343 const TString& searchCmd = GetHtml()->GetSearchStemURL();
02344 const TString& searchEngine = GetHtml()->GetSearchEngine();
02345
02346 if (!searchCmd.Length() && !searchEngine.Length())
02347 return;
02348
02349 if (searchCmd.Length()) {
02350 TUrl url(searchCmd);
02351 TString serverName(url.GetHost());
02352 if (serverName.Length()) {
02353 serverName.Prepend(" title=\"");
02354 serverName += "\" ";
02355 }
02356
02357 out << "<script type=\"text/javascript\">" << endl
02358 << "function onSearch() {" << endl
02359 << "var s='" << searchCmd <<"';" << endl
02360 << "var ref=String(document.location.href).replace(/https?:\\/\\//,'').replace(/\\/[^\\/]*$/,'').replace(/\\//g,'%2F');" << endl
02361 << "window.location.href=s.replace(/%u/ig,ref).replace(/%s/ig,escape(document.searchform.t.value));" << endl
02362 << "return false;}" << endl
02363 << "</script>" << endl
02364 << "<form id=\"searchform\" name=\"searchform\" onsubmit=\"return onSearch()\" action=\"javascript:onSearch();\" method=\"post\">" << endl
02365 << "<input name=\"t\" size=\"30\" value=\"Search documentation...\" onfocus=\"if (document.searchform.t.value=='Search documentation...') document.searchform.t.value='';\"></input>" << endl
02366 << "<a id=\"searchlink\" " << serverName << " href=\"javascript:onSearch();\" onclick=\"return onSearch()\">Search</a></form>" << endl;
02367 } else if (searchEngine.Length())
02368
02369 out << "<a class=\"descrheadentry\" href=\"" << searchEngine
02370 << "\">Search the Class Reference Guide</a>" << endl;
02371 }
02372
02373
02374
02375 void TDocOutput::WriteLocation(std::ostream& out, TModuleDocInfo* module, const char* classname)
02376 {
02377
02378 out << "<div class=\"location\">" << endl;
02379 const char *productName = fHtml->GetProductName();
02380 out << "<a class=\"locationlevel\" href=\"index.html\">" << productName << "</a>" << endl;
02381
02382 if (module) {
02383 TString modulename(module->GetName());
02384 modulename.ToUpper();
02385 TString modulePart;
02386 TString modulePath;
02387 Ssiz_t pos = 0;
02388 while (modulename.Tokenize(modulePart, pos, "/")) {
02389 if (pos == kNPOS && !classname)
02390
02391 break;
02392 if (modulePath.Length()) modulePath += "_";
02393 modulePath += modulePart;
02394 out << " » <a class=\"locationlevel\" href=\"./" << modulePath << "_Index.html\">" << modulePart << "</a>" << endl;
02395 }
02396 }
02397
02398 TString entityName;
02399 if (classname) entityName = classname;
02400 else if (module) {
02401 entityName = module->GetName();
02402 Ssiz_t posSlash = entityName.Last('/');
02403 if (posSlash != kNPOS)
02404 entityName.Remove(0, posSlash + 1);
02405 entityName.ToUpper();
02406 }
02407 if (entityName.Length()) {
02408 out << " » <a class=\"locationlevel\" href=\"#TopOfPage\">";
02409 ReplaceSpecialChars(out, entityName);
02410 out << "</a>" << endl;
02411 }
02412 out << "</div>" << endl;
02413 }
02414
02415
02416
02417 void TDocOutput::WriteTopLinks(std::ostream& out, TModuleDocInfo* module, const char* classname,
02418 Bool_t withLocation)
02419 {
02420
02421
02422
02423
02424 out << "<div id=\"toplinks\">" << endl;
02425
02426 out << "<div class=\"descrhead\"><div class=\"descrheadcontent\">" << endl
02427 << "<span class=\"descrtitle\">Quick Links:</span>" << endl;
02428
02429
02430 const char* userHomePage = GetHtml()->GetHomepage();
02431 const char* productName = fHtml->GetProductName();
02432 if (!productName) {
02433 productName = "";
02434 } else if (!strcmp(productName, "ROOT")) {
02435 userHomePage = "";
02436 }
02437 if (userHomePage && *userHomePage)
02438 out << "<a class=\"descrheadentry\" href=\"" << userHomePage << "\">" << productName << "</a>" << endl;
02439 out << "<a class=\"descrheadentry\" href=\"http://root.cern.ch\">ROOT Homepage</a>" << endl
02440 << "<a class=\"descrheadentry\" href=\"./ClassIndex.html\">Class Index</a>" << endl
02441 << "<a class=\"descrheadentry\" href=\"./ClassHierarchy.html\">Class Hierarchy</a></div>" << endl;
02442 WriteSearch(out);
02443 out << "</div>" << endl;
02444
02445 if (withLocation) {
02446 out << "</div>" << endl;
02447 WriteLocation(out, module, classname);
02448 }
02449
02450
02451
02452
02453
02454 }