Logo ROOT   6.12/07
Reference Guide
TDocDirective.cxx
Go to the documentation of this file.
1 #include "TDocDirective.h"
2 
3 #include "TApplication.h"
4 #include "TClass.h"
5 #include "TDocInfo.h"
6 #include "TDocOutput.h"
7 #include "TDocParser.h"
8 #include "TError.h"
9 #include "THtml.h"
10 #include "TInterpreter.h"
11 #include "TLatex.h"
12 #include "TMacro.h"
13 #include "TObjString.h"
14 #include "TPRegexp.h"
15 #include "TROOT.h"
16 #include "TStyle.h"
17 #include "TSystem.h"
18 #include "TVirtualPad.h"
19 #include "TVirtualMutex.h"
20 #include <typeinfo>
21 #include <fstream>
22 #include <sstream>
23 #include <stdlib.h>
24 
25 //______________________________________________________________________________
26 //
27 // When THtml parses documentation (through TDocParser), it checks for special
28 // words ("begin_something", "end_something", where the begin and end are the
29 // significant part). THtml then searches for a TDocDirective which can handle
30 // these tags ("whatever" in the example), passes the text enclosed by these
31 // tags to the directive, which in turn processes it.
32 //
33 // That way, HTML, latex, and C++ macros can be processed by THtml, e.g. to
34 // generate plain HTML or GIF pictures. The classes reposinsible for parsing
35 // that are TDocHtmlDirective, TDocLatexDirective, and TDocMacroDirective,
36 // respecively.
37 //
38 // Directives can have optional parameters; these are passed as paranthesis
39 // enclosed, comma delimited name=value pairs; see SetParameters().
40 //
41 // You can implement your own directive simply by deriving from TDocDirective;
42 // the tag corresponds to TDocDirective's name (e.g. "HTML" for "begin_html" /
43 // "end_html").
44 //______________________________________________________________________________
45 
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 /// Delete all output generated by the directive beginning
50 /// with Name() and ending with ext
51 
52 void TDocDirective::DeleteOutputFiles(const char* ext) const
53 {
54  TString basename;
55  GetName(basename);
56  basename += "_";
57  TString dirname(GetOutputDir());
58  void* hDir = gSystem->OpenDirectory(dirname);
59  const char* entry = 0;
60  while ((entry = gSystem->GetDirEntry(hDir))) {
61  TString sEntry(entry);
62  if (sEntry.BeginsWith(basename) && isdigit(sEntry[basename.Length()]) && (!ext || sEntry.EndsWith(ext)))
63  gSystem->Unlink((dirname + "/" + entry).Data());
64  }
65  gSystem->FreeDirectory(hDir);
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Get the full name, based on fName, fTitle, fDocParser's tag.
70 
72 {
73  name = fName;
75  name += "_";
76  TString outfilename;
78  outfilename = gSystem->BaseName(outfilename);
79  Ssiz_t posExt = outfilename.Last('.');
80  outfilename.Remove(posExt, outfilename.Length() - posExt);
81  name += outfilename;
82  }
83  if (GetTitle() && strlen(GetTitle())) {
84  name += "_";
85  name += GetTitle();
86  }
87  if (fCounter != -1) {
88  name += "_";
89  name += fCounter;
90  }
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Get the directory for documentation output.
95 
96 const char* TDocDirective::GetOutputDir() const
97 {
98  return fHtml ? fHtml->GetOutputDir().Data() : 0;
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Given a string containing parameters in params,
103 /// we call AddParameter() for each of them.
104 /// This function splits the parameter names and
105 /// extracts their values if they are given.
106 /// Parameters are separated by ",", values are
107 /// separated from parameter names by "=".
108 /// params being
109 /// a = "a, b, c", b='d,e'
110 /// will issue two calls to AddParameter(), one for
111 /// a with value "a, b, c" and one for b with value
112 /// "d,e" (each without the quotation marks).
113 
114 void TDocDirective::SetParameters(const char* params)
115 {
116  fParameters = params;
117 
118  if (!fParameters.Length())
119  return;
120 
121  TString param;
122  Ssiz_t pos = 0;
123  while (fParameters.Tokenize(param, pos, ",")) {
124  param = param.Strip(TString::kBoth);
125  if (!param.Length())
126  continue;
127 
128  Ssiz_t posAssign = param.Index('=');
129  if (posAssign != kNPOS) {
130  TString value(param(posAssign + 1, param.Length()));
131  value = value.Strip(TString::kBoth);
132  if (value[0] == '\'')
133  value = value.Strip(TString::kBoth, '\'');
134  else if (value[0] == '"')
135  value = value.Strip(TString::kBoth, '"');
136  param.Remove(posAssign, param.Length());
137  param = param.Strip(TString::kBoth);
138  AddParameter(param, value);
139  } else {
140  param = param.Strip(TString::kBoth);
141  AddParameter(param, 0);
142  }
143  }
144 }
145 
146 ////////////////////////////////////////////////////////////////////////////////
147 /// Set the parser, and fDocOutput, fHtml from that
148 
150 {
151  fDocParser = parser;
152  fDocOutput = parser ? parser->GetDocOutput() : 0;
154 }
155 
156 
157 //______________________________________________________________________________
158 //
159 // Process a "begin_html" / "end_html" block. Stop linking keywords and simply
160 // copy the text enclosed by the directive to the output HTML file.
161 //______________________________________________________________________________
162 
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Add a line of HTML
167 
169 {
170  if (line.Start() == -1) return;
171 
172  TPRegexp pretag("</?[pP][rR][eE][ >]");
173  TSubString iLine(line);
174  Ssiz_t posPre = iLine.String().Index(pretag, iLine.Start());
175  if (posPre == kNPOS)
176  fText += line;
177  else {
178  // remove <pre> in fVerbatim environments, and
179  // </pre> in !fVerbatim environments.
180  while (posPre != kNPOS && posPre > 0) {
181  Bool_t isOpen = line[posPre + 1 - line.Start()] != '/';
182  Ssiz_t posClose = iLine.String().Index(">", posPre);
183  if (posClose ==kNPOS) break; // aka oops.
184  Ssiz_t len = posClose - posPre;
185 
186  if (fVerbatim) {
187  if (isOpen) {
188  // skip
189  fText += iLine.String()(iLine.Start(), posPre - iLine.Start());
190  } else {
191  // write it out
192  fText += iLine.String()(iLine.Start(), posPre + len - iLine.Start());
193  fVerbatim = kFALSE;
194  }
195  } else {
196  if (!isOpen) {
197  // skip
198  fText += iLine.String()(iLine.Start(), posPre - iLine.Start());
199  } else {
200  // write it out
201  fText += iLine.String()(iLine.Start(), posPre + len - iLine.Start());
202  fVerbatim = kTRUE;
203  }
204  }
205 
206  iLine = iLine.String()(posPre + len, iLine.Length());
207  posPre = iLine.String().Index(pretag, iLine.Start());
208  }
209 
210  fText += iLine;
211  }
212  fText += "\n";
213 }
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 /// Set result to the HTML code that was passed in via AddLine().
217 /// Prepend a closing </pre>, append an opening <pre>
218 
220 {
221  result = "</pre><!-- TDocHtmlDirective start -->";
222  result += fText + "<!-- TDocHtmlDirective end --><pre>";
223  return kTRUE;
224 }
225 
226 
227 
228 //______________________________________________________________________________
229 //
230 // Process a "begin_macro" / "end_macro" block. The block can be a file name
231 // or a CINT script (i.e. even ".x file.C" is allowed). See AddParameter() for
232 // supported options. Example (the quotes prevent THtml from expanding the
233 // example):
234 //
235 // "BEGIN_MACRO"
236 // .x $ROOTSYS/tutorials/hsimple.C
237 // "END_MACRO"
238 //
239 // The macro is meant to create an object that can be saved as a GIF file by
240 // calling object->SaveAs(outputfile.gif). The macro is expected to return that
241 // object as a TObject*; if it does not, gPad is used and saved. The object
242 // is deleted by TDocMacroDirective once saved.
243 //______________________________________________________________________________
244 
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Destructor
249 
251 {
252  delete fMacro;
253 }
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 
257 void TDocMacroDirective::SubProcess(const TString& what, const TString& out) {
259  Long_t ret = gROOT->ProcessLine(TString(".x ") + what, &error);
260  Int_t sleepCycles = 50; // 50 = 5 seconds
261  while (error == TInterpreter::kProcessing && --sleepCycles > 0)
262  gSystem->Sleep(100);
263 
264  gSystem->ProcessEvents(); // in case ret needs to handle some events first
265 
266  if (error != TInterpreter::kNoError) {
267  ::Error("TDocMacroDirective::HandleDirective_Macro",
268  "Error processing macro for %s!", out.Data());
269  return;
270  }
271  if (!ret) {
272  return;
273  }
274 
275  // Something with a vtable
276  const TObject* objRet = (const TObject*)ret;
277  try {
278  typeid(*objRet).name(); // needed to test whether ret is indeed an object with a vtable!
279  objRet = dynamic_cast<const TObject*>(objRet);
280  }
281  catch (...) {
282  objRet = 0;
283  }
284 
285  if (!objRet) {
286  return;
287  }
288 
289  if (gDebug > 3)
290  ::Info("TDocMacroDirective::HandleDirective_Macro",
291  "Saving returned %s to file %s.",
292  objRet->IsA()->GetName(), out.Data());
293 
294  if (!gROOT->IsBatch()) {
295  // to get X11 to sync :-( gVirtualX->Update()/Sync() don't do it
296  gSystem->Sleep(1000);
297  gVirtualX->Update(0);
298  gVirtualX->Update(1);
299  }
300 
302  if (!gROOT->IsBatch()) {
303  gVirtualX->Update(0);
304  gVirtualX->Update(1);
305  }
306 
307  objRet->SaveAs(out);
308  gSystem->ProcessEvents(); // SaveAs triggers an event
309 
310 #ifdef R__BEPAEPSTLICHERALSDERPAPST
311  // ensure objRet is not e.g. the TGMainFrame of a new TCanvas: require padSave == gPad
312  if (objRet != gPad && padSave == gPad)
313  delete objRet;
314  }
315 #endif
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Add a macro line.
320 /// Lines ending on "*HIDE*" will be executed as part of the
321 /// macro, but not shown in the source tab if the parameter
322 /// source is supplied.
323 
325 {
326  if (!fMacro) {
327  TString name;
328  GetName(name);
329  fMacro = new TMacro(name);
330  }
331 
332  // return if no line - or if there was an intentinal line-break,
333  // i.e. an empty line
334  if (line.Start() == -1 && const_cast<TSubString&>(line).String().Length()) return;
335 
336  TString sLine(line);
337  fMacro->AddLine(sLine);
338  fIsFilename &= !sLine.Contains('{');
339 }
340 
341 ////////////////////////////////////////////////////////////////////////////////
342 /// Create the input file for SubProcess().
343 
345  if (!fIsFilename) {
346  TString fileSysName;
347  GetName(fileSysName);
348  fileSysName += ".C";
349  gSystem->PrependPathName(gSystem->TempDirectory(), fileSysName);
350  fMacro->SaveSource(fileSysName);
351  return fileSysName;
352  }
353 
354  // We have a filename; find it and build the invocation.
355  TString filename;
356  TIter iLine(fMacro->GetListOfLines());
357  while (filename.Length() == 0)
358  filename = ((TObjString*)iLine())->String().Strip(TString::kBoth);
359 
360  TString macroPath;
361  TString modulename;
362  if (GetHtml() && GetDocParser()) {
363  if (GetDocParser()->GetCurrentClass())
364  GetHtml()->GetModuleNameForClass(modulename, GetDocParser()->GetCurrentClass());
365  else GetDocParser()->GetCurrentModule(modulename);
366  }
367  if (modulename.Length()) {
368  GetHtml()->GetModuleMacroPath(modulename, macroPath);
369  } else macroPath = gSystem->pwd();
370 
371  const char* pathDelimiter = ":"; // use ":" even on windows
372  TObjArray* arrDirs(macroPath.Tokenize(pathDelimiter));
373  TIter iDir(arrDirs);
374  TObjString* osDir = 0;
375  macroPath = "";
376  TString filenameDirPart(gSystem->DirName(filename));
377  filenameDirPart.Prepend('/'); // as dir delimiter, not as root dir
378  while ((osDir = (TObjString*)iDir())) {
379  if (osDir->String().EndsWith("\\"))
380  osDir->String().Remove(osDir->String().Length() - 1);
381  osDir->String() += filenameDirPart;
382  macroPath += osDir->String() + pathDelimiter;
383  }
384 
385  TString plusplus;
386  while (filename.EndsWith("+")) {
387  plusplus += '+';
388  filename.Remove(filename.Length() - 1);
389  }
390 
391  TString params;
392  if (filename.EndsWith(")")) {
393  Ssiz_t posOpen = filename.Last('(');
394  if (posOpen != kNPOS) {
395  params = filename(posOpen, filename.Length());
396  filename.Remove(posOpen, filename.Length());
397  }
398  }
399 
400  TString fileSysName(gSystem->BaseName(filename));
401  if (!gSystem->FindFile(macroPath, fileSysName)) {
402  Error("GetResult", "Cannot find macro '%s' in path '%s'!",
403  gSystem->BaseName(filename), macroPath.Data());
404  return "";
405  }
406  fileSysName += params;
407  fileSysName += plusplus;
408 
409 
410  if (fShowSource) {
411  // copy macro into fMacro - before running it, in case the macro blocks its file
412  std::ifstream ifMacro(fileSysName);
413  fMacro->GetListOfLines()->Delete();
414  TString line;
415  while (ifMacro) {
416  if (!line.ReadLine(ifMacro, kFALSE) || ifMacro.eof())
417  break;
418  fMacro->AddLine(line);
419  }
420  }
421  return fileSysName;
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 /// Get the result (i.e. an HTML img tag) for the macro invocation.
426 /// If fShowSource is set, a second tab will be created which shows
427 /// the source.
428 
430 {
431  if (!fMacro)
432  return kFALSE;
433 
434  if (!fMacro->GetListOfLines()
435  || !fMacro->GetListOfLines()->First()) {
436  Warning("GetResult", "Empty directive found!");
437  return kTRUE;
438  }
439 
440  R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
441 
442  if (gDebug > 3)
443  Info("HandleDirective_Macro", "executing macro \"%s\" with %d lines.",
444  fMacro->GetName(), fMacro->GetListOfLines() ? fMacro->GetListOfLines()->GetEntries() + 1 : 0);
445 
446  Bool_t wasBatch = gROOT->IsBatch();
447  Bool_t wantBatch = kFALSE;
448  if (!wasBatch && !fNeedGraphics)
449  wantBatch = kTRUE;
450  else if (fNeedGraphics) {
451  if (fHtml->IsBatch()) {
452  Warning("GetResult()", "Will not initialize the graphics system; skipping macro %s!", GetName());
453  result = "";
454  return kFALSE;
455  }
456  }
457 
458  TString outFileName;
459  {
460  GetName(outFileName);
461  GetDocOutput()->NameSpace2FileName(outFileName);
462  outFileName += ".gif";
463  outFileName.ReplaceAll(" ", "_");
464  gSystem->PrependPathName(GetOutputDir(), outFileName);
465  }
466 
467  TString subProcInputFile = CreateSubprocessInputFile();
468  if (!subProcInputFile.Length()) return kFALSE;
469 
470  subProcInputFile.ReplaceAll("\\", "\\\\");
471  subProcInputFile.ReplaceAll("\"", "\\\"");
472  TString invoc("root.exe -l -q ");
473  if (wantBatch) {
474  invoc += "-b ";
475  }
476  invoc += "-e 'TDocMacroDirective::SubProcess(\""
477  + subProcInputFile + "\",\"" + outFileName + "\");'";
478  gSystem->Unlink(outFileName);
479  Int_t exitCode = gSystem->Exec(invoc.Data());
480 
481  if (exitCode && gDebug > 0) {
482  Info("GetResult()", "Subprocess exited with status %d\n", exitCode);
483  } else if (!fIsFilename) {
484  // we have created the input file.
485  gSystem->Unlink(subProcInputFile);
486  }
487 
488  if (!gSystem->AccessPathName(outFileName)) {
489  // Output file was created
490  result = "<span class=\"macro\"><img class=\"macro\" alt=\"output of ";
491  result += outFileName;
492 
493  result += "\" title=\"MACRO\" src=\"";
494  result += gSystem->BaseName(outFileName);
495  result += "\" /></span>";
496  }
497 
498  if (fShowSource) {
499  // convert the macro source
500  TIter iLine(fMacro->GetListOfLines());
501  TObjString* osLine = 0;
502  std::stringstream ssRaw;
503  while ((osLine = (TObjString*)iLine()))
504  ssRaw << osLine->String() << std::endl;
505 
506  TDocParser *dparser = 0;
507  if (GetDocParser()->GetCurrentClass())
508  dparser = new TDocParser(*(TClassDocOutput*)GetDocOutput(), GetDocParser()->GetCurrentClass());
509  else dparser = new TDocParser(*GetDocOutput());
510  std::stringstream ssConverted;
511  dparser->Convert(ssConverted, ssRaw, "./", kTRUE /*code*/, kFALSE /*process directives*/);
512  delete dparser;
513 
514  fMacro->GetListOfLines()->Delete();
515  TString line;
516  while (!ssConverted.fail()) {
517  if (!line.ReadLine(ssConverted, kFALSE) || ssConverted.eof())
518  break;
519  fMacro->AddLine(line);
520  }
521 
522  TString id(gSystem->BaseName(outFileName));
523  id = id(0, id.Length()-4); // remove ".gif"
524  // TODO: we need an accessible version of the source, i.e. visible w/o javascript
525  TString tags("</pre><div class=\"tabs\">\n"
526  "<a id=\"" + id + "_A0\" class=\"tabsel\" href=\"" + gSystem->BaseName(outFileName) + "\" onclick=\"javascript:return SetDiv('" + id + "',0);\">Picture</a>\n"
527  "<a id=\"" + id + "_A1\" class=\"tab\" href=\"#\" onclick=\"javascript:return SetDiv('" + id + "',1);\">Source</a>\n"
528  "<br /></div><div class=\"tabcontent\">\n"
529  "<div id=\"" + id + "_0\" class=\"tabvisible\">" + result + "</div>\n"
530  "<div id=\"" + id + "_1\" class=\"tabhidden\"><div class=\"listing\"><pre class=\"code\">");
531  iLine.Reset();
532  osLine = 0;
533  while ((osLine = (TObjString*) iLine()))
534  if (!TString(osLine->String().Strip()).EndsWith("*HIDE*"))
535  tags += osLine->String() + "\n";
536  if (tags.EndsWith("\n"))
537  tags.Remove(tags.Length()-1); // trailing line break
538  tags += "</pre></div></div><div class=\"clear\"></div></div><pre>";
539  result = tags;
540  // Protect the nested comments from being stripped by a
541  // TDocParser::ProcessComment() in the call stack.
542  result.ReplaceAll("<span class=\"comment\">", "<span class=\"codecomment\">");
543  }
544 
545  return kTRUE;
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////////
549 /// Setting fNeedGraphics if name is "GUI",
550 /// setting fShowSource if name is "SOURCE"
551 
552 void TDocMacroDirective::AddParameter(const TString& name, const char* /*value=0*/)
553 {
554  if (!name.CompareTo("gui", TString::kIgnoreCase))
555  fNeedGraphics = kTRUE;
556  else if (!name.CompareTo("source", TString::kIgnoreCase))
557  fShowSource = kTRUE;
558  else Warning("AddParameter", "Unknown option %s!", name.Data());
559 }
560 
561 
562 
563 namespace {
564  Float_t gLinePadding = 10.; //px
565  Float_t gColumnPadding = 10.; //px
566 
567  class TLatexLine {
568  private:
569  std::vector<Float_t> fWidths;
570  Float_t fHeight;
571  TObjArray* fColumns; // of TObjString*
572 
573  public:
574  TLatexLine(TObjArray* columns = 0):
575  fHeight(0.), fColumns(columns) { if (columns) fWidths.resize(Size());}
576 
577  Float_t& Width(UInt_t col) {return fWidths[col];}
578  Float_t& Height() {return fHeight;}
579  TString* operator[](Int_t column) {
580  if (fColumns && fColumns->GetEntriesFast() > column)
581  return &(((TObjString*)fColumns->At(column))->String());
582  return 0;
583  }
584  UInt_t Size() const { return fColumns ? fColumns->GetEntries() : 0; }
585  void Delete() { delete fColumns; }
586  };
587 }
588 
589 //______________________________________________________________________________
590 //
591 // Handle a "Begin_Latex"/"End_Latex" directive.
592 // called as
593 // "Begin_Latex(fontsize=10, separator='=,', rseparator='=|,', align=lcl)"
594 // will create and include a TLatex-processed image, with a given fontsize
595 // in pixels (defaults to 16). If (r)separator is given, the formulas on the
596 // following lines will be grouped into columns; a new column starts with
597 // (regexp) match of the separator; by default there is only one column.
598 // separator matches any character, rseparator matches as regexp with one
599 // column per pattern match. Only one of separator or rseparator can be given.
600 // align defines the alignment for each columns; be default, all columns
601 // are right aligned. NOTE that the column separator counts as a column itself!
602 //______________________________________________________________________________
603 
604 
606 
607 ////////////////////////////////////////////////////////////////////////////////
608 /// Destructor
609 
611 {
613  delete fLatex;
614  delete fBBCanvas;
616 }
617 
618 ////////////////////////////////////////////////////////////////////////////////
619 /// Add a latex line
620 
622 {
623  if (line.Length() == 0)
624  return;
625 
626  if (!fLatex) {
627  TString name;
628  GetName(name);
629  fLatex = new TMacro(name);
630  }
631 
632  TString sLine(line);
633  GetDocParser()->Strip(sLine);
634  if (sLine.Length() == 0)
635  return;
636 
637  fLatex->AddLine(sLine);
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Create a gif file named filename from a latex expression in fLatex.
642 /// Called when "Begin_Latex"/"End_Latex" is processed.
643 
644 void TDocLatexDirective::CreateLatex(const char* filename)
645 {
646  if (!fLatex
647  || !fLatex->GetListOfLines()
648  || !fLatex->GetListOfLines()->First())
649  return;
650 
651  R__LOCKGUARD(GetHtml()->GetMakeClassMutex());
652 
653  TVirtualPad* oldPad = gPad;
654 
655  Bool_t wasBatch = gROOT->IsBatch();
656  if (!wasBatch)
657  gROOT->SetBatch();
658 
659  const Float_t canvSize = 1200.;
660  if (!fBBCanvas)
661  // add magic batch vs. gui canvas sizes (4, 28)
662  fBBCanvas = (TVirtualPad*)gROOT->ProcessLineFast(
663  Form("new TCanvas(\"R__TDocLatexDirective_BBCanvas\",\"fBBCanvas\",%g,%g);", -(canvSize + 4.), canvSize + 28.));
664  if (!fBBCanvas) {
665  Error("CreateLatex", "Cannot create a TCanvas via the interpreter!");
666  return;
667  }
668  fBBCanvas->SetBorderMode(0);
669  fBBCanvas->SetFillColor(kWhite);
670 
672 
673  std::list<TLatexLine> latexLines;
674  std::vector<Float_t> maxWidth(20);
675  UInt_t numColumns = 0;
676  Float_t totalHeight = gLinePadding;
677 
678  TLatex latex;
679  latex.SetTextFont(43);
680  latex.SetTextSize((Float_t)fFontSize);
681  latex.SetTextAlign(12);
682 
683  // calculate positions
684  TIter iterLine(fLatex->GetListOfLines());
685  TObjString* line = 0;
686  TPRegexp regexp;
687  if (fSeparator.Length()) {
688  if (fSepIsRegexp)
689  regexp = TPRegexp(fSeparator);
690  } else fSepIsRegexp = kFALSE;
691 
692  while ((line = (TObjString*) iterLine())) {
693  const TString& str = line->String();
694  TObjArray* split = 0;
695  if (!fSepIsRegexp) {
696  split = new TObjArray();
697  split->SetOwner();
698  }
699  if (!fSeparator.Length())
700  split->Add(new TObjString(str));
701  else {
702  if (fSepIsRegexp)
703  split = regexp.MatchS(str);
704  else {
705  Ssiz_t prevStart = 0;
706  for (Ssiz_t pos = 0; pos < str.Length(); ++pos) {
707  if (fSeparator.Index(str[pos]) != kNPOS) {
708  split->Add(new TObjString(TString(str(prevStart, pos - prevStart))));
709  split->Add(new TObjString(TString(str(pos, 1))));
710  prevStart = pos + 1;
711  }
712  }
713  split->Add(new TObjString(TString(str(prevStart, str.Length() - prevStart))));
714  }
715  }
716 
717  latexLines.push_back(TLatexLine(split));
718  if (numColumns < (UInt_t)split->GetEntries())
719  numColumns = split->GetEntries();
720 
721  Float_t heightLine = -1.;
722  for (UInt_t col = 0; col < (UInt_t)split->GetEntries(); ++col) {
723  Float_t widthLatex = 0.;
724  Float_t heightLatex = 0.;
725  TString* strCol = latexLines.back()[col];
726  if (strCol)
727  GetBoundingBox(latex, *strCol, widthLatex, heightLatex);
728  if (heightLine < heightLatex) heightLine = heightLatex;
729  if (maxWidth.size() < col)
730  maxWidth.resize(col * 2);
731  if (maxWidth[col] < widthLatex)
732  maxWidth[col] = widthLatex;
733  latexLines.back().Width(col) = widthLatex;
734  }
735  latexLines.back().Height() = heightLine;
736  totalHeight += heightLine + gLinePadding;
737  } // while next line
738 
739  std::vector<Float_t> posX(numColumns + 1);
740  for (UInt_t col = 0; col <= numColumns; ++col) {
741  if (col == 0) posX[col] = gColumnPadding;
742  else posX[col] = posX[col - 1] + maxWidth[col - 1] + gColumnPadding;
743  }
744  Float_t totalWidth = posX[numColumns];
745 
746  // draw
747  fBBCanvas->Clear();
748  fBBCanvas->cd();
749  Float_t padSizeX = totalWidth;
750  Float_t padSizeY = totalHeight + 8.;
751  // add magic batch vs. gui canvas sizes (4, 28) + rounding
752  TVirtualPad* padImg = (TVirtualPad*)gROOT->ProcessLineFast(
753  Form("new TCanvas(\"R__TDocLatexDirective_padImg\",\"padImg\",-(Int_t)%g,(Int_t)%g);",
754  padSizeX + 4.5, padSizeY + 28.5));
755  padImg->SetBorderMode(0);
756  padImg->SetFillColor(kWhite);
757  padImg->cd();
758 
759  Float_t posY = 0.;
760  for (std::list<TLatexLine>::iterator iLine = latexLines.begin();
761  iLine != latexLines.end(); ++iLine) {
762  posY += iLine->Height()/2. + gLinePadding;
763  for (UInt_t iCol = 0; iCol < iLine->Size(); ++iCol) {
764  TString* str = (*iLine)[iCol];
765  if (!str) continue;
766  char align = 'l';
767  if ((UInt_t)fAlignment.Length() > iCol)
768  align = fAlignment[(Int_t)iCol];
769  Float_t x = posX[iCol];
770  switch (align) {
771  case 'l': break;
772  case 'r': x += maxWidth[iCol] - iLine->Width(iCol); break;
773  case 'c': x += 0.5*(maxWidth[iCol] - iLine->Width(iCol)); break;
774  default:
775  if (iLine == latexLines.begin())
776  Error("CreateLatex", "Invalid alignment character '%c'!", align);
777  }
778  latex.DrawLatex( x / padSizeX, 1. - posY / padSizeY, str->Data());
779  }
780  posY += iLine->Height()/2.;
781  }
782 
783  padImg->Print(filename);
784 
785  // delete the latex objects
786  for (std::list<TLatexLine>::iterator iLine = latexLines.begin();
787  iLine != latexLines.end(); ++iLine) {
788  iLine->Delete();
789  }
790 
791  delete padImg;
792 
793  if (!wasBatch)
794  gROOT->SetBatch(kFALSE);
795 
796  gPad = oldPad;
797 }
798 
799 ////////////////////////////////////////////////////////////////////////////////
800 /// Determines the bounding box for text as height and width.
801 /// Assumes that we are in batch mode.
802 
803 void TDocLatexDirective::GetBoundingBox(TLatex& latex, const char* text, Float_t& width, Float_t& height)
804 {
805  UInt_t uiWidth = 0;
806  UInt_t uiHeight = 0;
807  fBBCanvas->cd();
808  latex.SetText(0.1, 0.5, text);
809  latex.GetBoundingBox(uiWidth, uiHeight);
810 
811  width = uiWidth;
812  height = uiHeight;
813 }
814 
815 ////////////////////////////////////////////////////////////////////////////////
816 /// Get the list of lines as TObjStrings
817 
819 {
820  return fLatex ? fLatex->GetListOfLines() : 0;
821 }
822 
823 ////////////////////////////////////////////////////////////////////////////////
824 /// convert fLatex to a gif by creating a TLatex, drawing it on a
825 /// temporary canvas, and saving that to a filename in the output
826 /// directory.
827 
829 {
830  TString filename;
831  GetName(filename);
832  filename.ReplaceAll(" ", "_");
833  const TString& firstLine = ((TObjString*)fLatex->GetListOfLines()->First())->String();
834  TString latexFilename(firstLine);
835  for (Ssiz_t namepos = 0; namepos < latexFilename.Length(); ++namepos)
836  if (!GetDocParser()->IsWord(latexFilename[namepos])) {
837  latexFilename.Remove(namepos, 1);
838  --namepos;
839  }
840  filename += "_";
841  filename += latexFilename;
842 
843  GetDocOutput()->NameSpace2FileName(filename);
844  filename += ".gif";
845 
846  TString altText(firstLine);
847  GetDocOutput()->ReplaceSpecialChars(altText);
848  altText.ReplaceAll("\"", "&quot;");
849  result = "<span class=\"latex\"><img class=\"latex\" alt=\"";
850  result += altText;
851  result += "\" title=\"LATEX\" src=\"";
852  result += filename;
853  result += "\" /></span>";
854 
855  gSystem->PrependPathName(GetOutputDir(), filename);
856 
857  if (gDebug > 3)
858  Info("HandleDirective_Latex", "Writing Latex \"%s\" to file %s.",
859  fLatex->GetName(), filename.Data());
860 
861  CreateLatex(filename);
862 
863  return kTRUE;
864 }
865 
866 ////////////////////////////////////////////////////////////////////////////////
867 /// Parse fParameters, setting fFontSize, fAlignment, and fSeparator
868 
869 void TDocLatexDirective::AddParameter(const TString& name, const char* value /*=0*/)
870 {
871  if (!name.CompareTo("fontsize", TString::kIgnoreCase)) {
872  if (!value || !value[0])
873  Error("AddParameter", "Option \"fontsize\" needs a value!");
874  else fFontSize = atol(value);
875  } else if (!name.CompareTo("separator", TString::kIgnoreCase)) {
876  if (!value || !value[0])
877  Error("AddParameter", "Option \"separator\" needs a value!");
878  else fSeparator = value;
879  } else if (!name.CompareTo("align", TString::kIgnoreCase)) {
880  if (!value || !value[0])
881  Error("AddParameter", "Option \"align\" needs a value!");
882  else fAlignment = value;
883  } else
884  Warning("AddParameter", "Unknown option %s!", name.Data());
885 }
A zero length substring is legal.
Definition: TString.h:71
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:932
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1276
An array of TObjects.
Definition: TObjArray.h:37
const char * GetOutputDir() const
Get the directory for documentation output.
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:424
virtual void SetBorderMode(Short_t bordermode)=0
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
TLine * line
Collectable string class.
Definition: TObjString.h:28
float Float_t
Definition: RtypesCore.h:53
virtual void DeleteOutputFiles(const char *ext) const
Delete all output generated by the directive beginning with Name() and ending with ext...
const char * Size
Definition: TXMLSetup.cxx:55
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:638
std::istream & ReadLine(std::istream &str, Bool_t skipWhite=kTRUE)
Read a line from stream upto newline skipping any whitespace.
Definition: Stringio.cxx:65
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TObjArray * MatchS(const TString &s, const TString &mods="", Int_t start=0, Int_t nMaxMatch=10)
Returns a TObjArray of matched substrings as TObjString&#39;s.
Definition: TPRegexp.cxx:370
TList * GetListOfLines() const
Get the list of lines as TObjStrings.
virtual void AddLine(const TSubString &line)
Add a line of HTML.
#define gROOT
Definition: TROOT.h:402
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
Class supporting a collection of lines with C++ code.
Definition: TMacro.h:31
Ssiz_t Start() const
Definition: TString.h:109
Basic string class.
Definition: TString.h:125
int Int_t
Definition: RtypesCore.h:41
virtual void AddParameter(const TString &name, const char *value=0)
Parse fParameters, setting fFontSize, fAlignment, and fSeparator.
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1004
bool Bool_t
Definition: RtypesCore.h:59
Ssiz_t Length() const
Definition: TString.h:108
virtual void AddParameter(const TString &, const char *=0)
Definition: TDocDirective.h:42
void GetCurrentModule(TString &out_module) const
Return the name of module for which sources are currently parsed.
Definition: TDocParser.cxx:967
TString & Prepend(const char *cs)
Definition: TString.h:607
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
TDocParser * GetDocParser() const
Definition: TDocDirective.h:51
virtual Bool_t GetResult(TString &result)
Set result to the HTML code that was passed in via AddLine().
virtual const char * FindFile(const char *search, TString &file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1512
virtual void GetBoundingBox(TLatex &latex, const char *text, Float_t &width, Float_t &height)
Determines the bounding box for text as height and width.
const char * String
Definition: TXMLSetup.cxx:93
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition: TAttText.h:45
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:851
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1357
Double_t x[n]
Definition: legend1.C:17
virtual void SetText(Double_t x, Double_t y, const char *text)
Definition: TText.h:72
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:445
virtual void SaveAs(const char *filename="", Option_t *option="") const
Save this object in the file specified by filename.
Definition: TObject.cxx:599
THtml * GetHtml() const
Definition: TDocDirective.h:53
To draw Mathematical Formula.
Definition: TLatex.h:18
void Convert(std::ostream &out, std::istream &in, const char *relpath, Bool_t isCode, Bool_t interpretDirectives)
Parse text file "in", add links etc, and write output to "out".
Definition: TDocParser.cxx:402
TLatex * DrawLatex(Double_t x, Double_t y, const char *text)
Make a copy of this object with the new parameters And copy object attributes.
Definition: TLatex.cxx:1918
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1062
static Bool_t Strip(TString &s)
strips &#39; &#39;, tabs, and newlines from both sides of str
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2231
virtual const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Definition: TSystem.cxx:1458
XFontStruct * id
Definition: TGX11.cxx:108
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:49
virtual void GetModuleNameForClass(TString &module, TClass *cl) const
Return the module name for a given class.
Definition: THtml.cxx:1530
void SetParser(TDocParser *parser)
Set the parser, and fDocOutput, fHtml from that.
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition: TAttText.h:41
virtual ~TDocMacroDirective()
Destructor.
static Bool_t IsWord(UChar_t c)
Check if c is a valid first character for C++ name.
A doubly linked list.
Definition: TList.h:44
virtual Bool_t GetResult(TString &result)
Get the result (i.e.
Definition: Rtypes.h:58
const char * pwd()
Definition: TSystem.h:405
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:169
virtual Bool_t GetResult(TString &result)
convert fLatex to a gif by creating a TLatex, drawing it on a temporary canvas, and saving that to a ...
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
virtual const char * ReplaceSpecialChars(char c)
Replace ampersand, less-than and greater-than character, writing to out.
virtual void NameSpace2FileName(TString &name)
Replace "::" in name by "__" Replace "<", ">", " ", ",", "~", "=" in name by "_" Replace "A::X<A::Y>"...
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:561
const char * GetName() const
Returns name of object.
Definition: TDocDirective.h:49
virtual void AddParameter(const TString &name, const char *value=0)
Setting fNeedGraphics if name is "GUI", setting fShowSource if name is "SOURCE".
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:386
friend class TDocParser
Definition: TDocDirective.h:75
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1080
void GetBoundingBox(UInt_t &w, UInt_t &h, Bool_t angle=kFALSE)
Return text size in pixels.
Definition: TLatex.cxx:2545
const TString & GetOutputDir(Bool_t createDir=kTRUE) const
Return the output directory as set by SetOutputDir().
Definition: THtml.cxx:2169
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:661
TString fParameters
Definition: TDocDirective.h:39
TString fName
Definition: TNamed.h:32
TString & String()
Definition: TObjString.h:49
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:843
#define gVirtualX
Definition: TVirtualX.h:350
const Bool_t kFALSE
Definition: RtypesCore.h:88
TString & Remove(Ssiz_t pos)
Definition: TString.h:619
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
void SetParameters(const char *params)
Given a string containing parameters in params, we call AddParameter() for each of them...
Bool_t IsBatch() const
Definition: THtml.h:353
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2251
#define ClassImp(name)
Definition: Rtypes.h:359
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:875
TText * text
virtual ~TDocLatexDirective()
Destructor.
virtual void AddLine(const TSubString &line)
Add a macro line.
TDocOutput * fDocOutput
Definition: TDocDirective.h:38
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:570
#define R__LOCKGUARD(mutex)
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:396
virtual void GetHtmlFileName(TClass *classPtr, TString &filename) const
Return real HTML filename.
Definition: THtml.cxx:1991
static void SubProcess(const TString &what, const TString &out)
void GetModuleMacroPath(const TString &module, TString &out_path) const
Definition: THtml.h:324
Mother of all ROOT objects.
Definition: TObject.h:37
TDocOutput * GetDocOutput() const
Definition: TDocParser.h:173
TString CreateSubprocessInputFile()
Create the input file for SubProcess().
virtual void AddLine(const TSubString &line)
Add a latex line.
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
#define gPad
Definition: TVirtualPad.h:285
THtml * GetHtml()
Definition: TDocOutput.h:90
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:834
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
void Add(TObject *obj)
Definition: TObjArray.h:73
TDocParser * fDocParser
Definition: TDocDirective.h:36
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition: TAttText.h:46
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
const Bool_t kTRUE
Definition: RtypesCore.h:87
TClass * GetCurrentClass() const
Definition: TDocParser.h:171
TString & String()
Definition: TString.h:110
char name[80]
Definition: TGX11.cxx:109
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void CreateLatex(const char *filename)
Create a gif file named filename from a latex expression in fLatex.
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
TDocOutput * GetDocOutput() const
Definition: TDocDirective.h:52
virtual void Print(const char *filename="") const =0
Print function.
const char * Data() const
Definition: TString.h:345