Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TApplication.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Fons Rademakers 22/12/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TApplication
13\ingroup Base
14
15This class creates the ROOT Application Environment that interfaces
16to the windowing system eventloop and eventhandlers.
17This class must be instantiated exactly once in any given
18application. Normally the specific application class inherits from
19TApplication (see TRint).
20*/
21
22#include "RConfigure.h"
23#include "TApplication.h"
24#include "TException.h"
25#include "TGuiFactory.h"
26#include "TVirtualX.h"
27#include "TROOT.h"
28#include "TSystem.h"
29#include "TString.h"
30#include "TError.h"
31#include "TObjArray.h"
32#include "TObjString.h"
33#include "TTimer.h"
34#include "TInterpreter.h"
35#include "TStyle.h"
36#include "TVirtualPad.h"
37#include "TEnv.h"
38#include "TColor.h"
39#include "TPluginManager.h"
40#include "TClassTable.h"
41#include "TBrowser.h"
42#include "TUrl.h"
43#include "TVirtualMutex.h"
44#include "TClassEdit.h"
45#include "TMethod.h"
46#include "TDataMember.h"
47#include "TApplicationCommandLineOptionsHelp.h"
48#include "TPRegexp.h"
49#include <cstdlib>
50#include <iostream>
51#include <fstream>
52
56TList *TApplication::fgApplications = nullptr; // List of available applications
57
58////////////////////////////////////////////////////////////////////////////////
59
60class TIdleTimer : public TTimer {
61public:
63 Bool_t Notify() override;
64};
65
66////////////////////////////////////////////////////////////////////////////////
67/// Notify handler.
68
70{
72 Reset();
73 return kFALSE;
74}
75
76
78
80{
81 // Insure that the files, canvases and sockets are closed.
82
83 // If we get here, the tear down has started. We have no way to know what
84 // has or has not yet been done. In particular on Ubuntu, this was called
85 // after the function static in TSystem.cxx has been destructed. So we
86 // set gROOT in its end-of-life mode which prevents executing code, like
87 // autoloading libraries (!) that is pointless ...
88 if (gROOT) {
89 gROOT->SetBit(kInvalidObject);
90 gROOT->EndOfProcessCleanups();
91 }
92}
93
94////////////////////////////////////////////////////////////////////////////////
95/// Default ctor. Can be used by classes deriving from TApplication.
96
98 fArgc(0), fArgv(nullptr), fAppImp(nullptr), fIsRunning(kFALSE), fReturnFromRun(kFALSE),
99 fNoLog(kFALSE), fNoLogo(kFALSE), fQuit(kFALSE),
100 fFiles(nullptr), fIdleTimer(nullptr), fSigHandler(nullptr), fExitOnException(kDontExit),
101 fAppRemote(nullptr)
102{
104}
105
106////////////////////////////////////////////////////////////////////////////////
107/// Create an application environment. The application environment
108/// provides an interface to the graphics system and eventloop
109/// (be it X, Windows, macOS or BeOS). After creating the application
110/// object start the eventloop by calling its Run() method. The command
111/// line options recognized by TApplication are described in the GetOptions()
112/// method. The recognized options are removed from the argument array.
113/// The original list of argument options can be retrieved via the Argc()
114/// and Argv() methods. The appClassName "proofserv" is reserved for the
115/// PROOF system. The "options" and "numOptions" arguments are not used,
116/// except if you want to by-pass the argv processing by GetOptions()
117/// in which case you should specify numOptions<0. All options will
118/// still be available via the Argv() method for later use.
119
120TApplication::TApplication(const char *appClassName, Int_t *argc, char **argv,
121 void * /*options*/, Int_t numOptions) :
122 fArgc(0), fArgv(nullptr), fAppImp(nullptr), fIsRunning(kFALSE), fReturnFromRun(kFALSE),
123 fNoLog(kFALSE), fNoLogo(kFALSE), fQuit(kFALSE),
124 fFiles(nullptr), fIdleTimer(nullptr), fSigHandler(nullptr), fExitOnException(kDontExit),
125 fAppRemote(nullptr)
126{
128
129 // Create the list of applications the first time
130 if (!fgApplications)
131 fgApplications = new TList;
132
133 // Add the new TApplication early, so that the destructor of the
134 // default TApplication (if it is called in the block of code below)
135 // will not destroy the files, socket or TColor that have already been
136 // created.
137 fgApplications->Add(this);
138
140 // allow default TApplication to be replaced by a "real" TApplication
141 delete gApplication;
142 gApplication = nullptr;
143 gROOT->SetBatch(kFALSE);
145 }
146
147 if (gApplication) {
148 Error("TApplication", "only one instance of TApplication allowed");
149 fgApplications->Remove(this);
150 return;
151 }
152
153 if (!gROOT)
154 ::Fatal("TApplication::TApplication", "ROOT system not initialized");
155
156 if (!gSystem)
157 ::Fatal("TApplication::TApplication", "gSystem not initialized");
158
159 static Bool_t hasRegisterAtExit(kFALSE);
160 if (!hasRegisterAtExit) {
161 // If we are the first TApplication register the atexit)
163 hasRegisterAtExit = kTRUE;
164 }
165 gROOT->SetName(appClassName);
166
167 // copy command line arguments, can be later accessed via Argc() and Argv()
168 if (argc && *argc > 0) {
169 fArgc = *argc;
170 fArgv = (char **)new char*[fArgc];
171 }
172
173 for (int i = 0; i < fArgc; i++)
174 fArgv[i] = StrDup(argv[i]);
175
176 if (numOptions >= 0)
177 GetOptions(argc, argv);
178
179 if (fArgv)
181
182 // Tell TSystem the TApplication has been created
184
185 fAppImp = gGuiFactory->CreateApplicationImp(appClassName, argc, argv);
187
188 // Initialize the graphics environment
189 if (gClassTable->GetDict("TPad")) {
191 InitializeGraphics(gROOT->IsWebDisplay());
192 }
193
194 // Save current interpreter context
195 gInterpreter->SaveContext();
196 gInterpreter->SaveGlobalsContext();
197
198 // to allow user to interact with TCanvas's under WIN32
199 gROOT->SetLineHasBeenProcessed();
200
201 //Needs to be done last
202 gApplication = this;
203 gROOT->SetApplication(this);
204
205}
206
207////////////////////////////////////////////////////////////////////////////////
208/// TApplication dtor.
209
211{
212 for (int i = 0; i < fArgc; i++)
213 if (fArgv[i]) delete [] fArgv[i];
214 delete [] fArgv;
215
216 if (fgApplications)
217 fgApplications->Remove(this);
218
219 // Reduce the risk of the files or sockets being closed after the
220 // end of 'main' (or more exactly before the library start being
221 // unloaded).
222 if (fgApplications == nullptr || fgApplications->FirstLink() == nullptr ) {
224 }
225
226 // Now that all the canvases and files have been closed we can
227 // delete the implementation.
229}
230
231////////////////////////////////////////////////////////////////////////////////
232/// Static method. This method should be called from static library
233/// initializers if the library needs the low level graphics system.
234
236{
238}
239
240////////////////////////////////////////////////////////////////////////////////
241/// Initialize the graphics environment.
242/// If @param only_web is specified, only web-related part of graphics is loaded
243
245{
247 return;
248
249 if (!only_web) {
250 // Load the graphics related libraries
252
253 // Try to load TrueType font renderer. Only try to load if not in batch
254 // mode and Root.UseTTFonts is true and Root.TTFontPath exists. Abort silently
255 // if libttf or libGX11TTF are not found in $ROOTSYS/lib or $ROOTSYS/ttf/lib.
256 const char *ttpath = gEnv->GetValue("Root.TTFontPath",
258 char *ttfont = gSystem->Which(ttpath, "arialbd.ttf", kReadPermission);
259 // Check for use of DFSG - fonts
260 if (!ttfont)
261 ttfont = gSystem->Which(ttpath, "FreeSansBold.ttf", kReadPermission);
262
263 #if !defined(R__WIN32)
264 if (!gROOT->IsBatch() && !strcmp(gVirtualX->GetName(), "X11") &&
265 ttfont && gEnv->GetValue("Root.UseTTFonts", 1)) {
266 if (gClassTable->GetDict("TGX11TTF")) {
267 // in principle we should not have linked anything against libGX11TTF
268 // but with ACLiC this can happen, initialize TGX11TTF by hand
269 // (normally this is done by the static library initializer)
270 ProcessLine("TGX11TTF::Activate();");
271 } else {
273 if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualX", "x11ttf")))
274 if (h->LoadPlugin() == -1)
275 Info("InitializeGraphics", "no TTF support");
276 }
277 }
278 #endif
279 delete [] ttfont;
280 }
281
282 if (!only_web || !fAppImp) {
283 // Create WM dependent application environment
284 if (fAppImp)
285 delete fAppImp;
287 if (!fAppImp) {
288 MakeBatch();
290 }
291 }
292
293 // Create the canvas colors early so they are allocated before
294 // any color table expensive bitmaps get allocated in GUI routines (like
295 // creation of XPM bitmaps).
297
298 // Hook for further initializing the WM dependent application environment
299 Init();
300
301 // Set default screen factor (if not disabled in rc file)
302 if (!only_web && gEnv->GetValue("Canvas.UseScreenFactor", 1)) {
303 Int_t x, y;
304 UInt_t w, h;
305 if (gVirtualX) {
306 gVirtualX->GetGeometry(-1, x, y, w, h);
307 if (h > 0)
308 gStyle->SetScreenFactor(0.001 * h);
309 }
310 }
311}
312
313////////////////////////////////////////////////////////////////////////////////
314/// Clear list containing macro files passed as program arguments.
315/// This method is called from TRint::Run() to ensure that the macro
316/// files are only executed the first time Run() is called.
317
319{
320 if (fFiles) {
321 fFiles->Delete();
323 }
324}
325
326////////////////////////////////////////////////////////////////////////////////
327/// Return specified argument.
328
330{
331 if (fArgv) {
332 if (index >= fArgc) {
333 Error("Argv", "index (%d) >= number of arguments (%d)", index, fArgc);
334 return nullptr;
335 }
336 return fArgv[index];
337 }
338 return nullptr;
339}
340
341////////////////////////////////////////////////////////////////////////////////
342/// Get and handle command line options. Arguments handled are removed
343/// from the argument array. See CommandLineOptionsHelp.h for options.
344
345void TApplication::GetOptions(Int_t *argc, char **argv)
346{
347 static char null[1] = { "" };
348
349 fNoLog = kFALSE;
350 fQuit = kFALSE;
351 fFiles = nullptr;
352
353 if (!argc)
354 return;
355
356 int i, j;
357 TString pwd;
358
359 for (i = 1; i < *argc; i++) {
360 if (!strcmp(argv[i], "-?") || !strncmp(argv[i], "-h", 2) ||
361 !strncmp(argv[i], "--help", 6)) {
362 fprintf(stderr, kCommandLineOptionsHelp);
363 Terminate(0);
364 } else if (!strncmp(argv[i], "--version", 9)) {
365 fprintf(stderr, "ROOT Version: %s\n", gROOT->GetVersion());
366 fprintf(stderr, "Built for %s on %s\n",
368 gROOT->GetGitDate());
369
370 fprintf(stderr, "From %s@%s\n",
371 gROOT->GetGitBranch(),
372 gROOT->GetGitCommit());
373
374 Terminate(0);
375 } else if (!strcmp(argv[i], "-config")) {
376 fprintf(stderr, "ROOT ./configure options:\n%s\n", gROOT->GetConfigOptions());
377 Terminate(0);
378 } else if (!strcmp(argv[i], "-a")) {
379 fprintf(stderr, "ROOT splash screen is not visible with root.exe, use root instead.\n");
380 Terminate(0);
381 } else if (!strcmp(argv[i], "-b")) {
382 MakeBatch();
383 argv[i] = null;
384 } else if (!strcmp(argv[i], "-n")) {
385 fNoLog = kTRUE;
386 argv[i] = null;
387 } else if (!strcmp(argv[i], "-t")) {
389 // EnableImplicitMT() only enables thread safety if IMT was configured;
390 // enable thread safety even with IMT off:
392 argv[i] = null;
393 } else if (!strcmp(argv[i], "-q")) {
394 fQuit = kTRUE;
395 argv[i] = null;
396 } else if (!strcmp(argv[i], "-l")) {
397 // used by front-end program to not display splash screen
398 fNoLogo = kTRUE;
399 argv[i] = null;
400 } else if (!strcmp(argv[i], "-x")) {
402 argv[i] = null;
403 } else if (!strcmp(argv[i], "-splash")) {
404 // used when started by front-end program to signal that
405 // splash screen can be popped down (TRint::PrintLogo())
406 argv[i] = null;
407 } else if (strncmp(argv[i], "--web", 5) == 0) {
408 // the web mode is requested
409 const char *opt = argv[i] + 5;
410 argv[i] = null;
411 gROOT->SetWebDisplay((*opt == '=') ? opt + 1 : "");
412 } else if (!strcmp(argv[i], "-e")) {
413 argv[i] = null;
414 ++i;
415
416 if ( i < *argc ) {
417 if (!fFiles) fFiles = new TObjArray;
418 TObjString *expr = new TObjString(argv[i]);
419 expr->SetBit(kExpression);
420 fFiles->Add(expr);
421 argv[i] = null;
422 } else {
423 Warning("GetOptions", "-e must be followed by an expression.");
424 }
425 } else if (!strcmp(argv[i], "--")) {
426 TObjString* macro = nullptr;
427 bool warnShown = false;
428
429 if (fFiles) {
430 for (auto f: *fFiles) {
431 TObjString *file = dynamic_cast<TObjString *>(f);
432 if (!file) {
433 if (!dynamic_cast<TNamed*>(f)) {
434 Error("GetOptions()", "Inconsistent file entry (not a TObjString)!");
435 if (f)
436 f->Dump();
437 } // else we did not find the file.
438 continue;
439 }
440
441 if (file->TestBit(kExpression))
442 continue;
443 if (file->String().EndsWith(".root"))
444 continue;
445 if (file->String().Contains('('))
446 continue;
447
448 if (macro && !warnShown && (warnShown = true))
449 Warning("GetOptions", "-- is used with several macros. "
450 "The arguments will be passed to the last one.");
451
452 macro = file;
453 }
454 }
455
456 if (macro) {
457 argv[i] = null;
458 ++i;
459 TString& str = macro->String();
460
461 str += '(';
462 for (; i < *argc; i++) {
463 str += argv[i];
464 str += ',';
465 argv[i] = null;
466 }
467 str.EndsWith(",") ? str[str.Length() - 1] = ')' : str += ')';
468 } else {
469 Warning("GetOptions", "no macro to pass arguments to was provided. "
470 "Everything after the -- will be ignored.");
471 for (; i < *argc; i++)
472 argv[i] = null;
473 }
474 } else if (argv[i][0] != '-' && argv[i][0] != '+') {
476 Long_t id, flags, modtime;
477 char *arg = strchr(argv[i], '(');
478 if (arg) *arg = '\0';
479 TString expandedDir(argv[i]);
480 if (gSystem->ExpandPathName(expandedDir)) {
481 // ROOT-9959: we do not continue if we could not expand the path
482 continue;
483 }
484 TUrl udir(expandedDir, kTRUE);
485 // remove options and anchor to check the path
486 TString sfx = udir.GetFileAndOptions();
487 TString fln = udir.GetFile();
488 sfx.Replace(sfx.Index(fln), fln.Length(), "");
489 TString path = udir.GetFile();
490 if (strcmp(udir.GetProtocol(), "file")) {
491 path = udir.GetUrl();
492 path.Replace(path.Index(sfx), sfx.Length(), "");
493 }
494 // 'path' is the full URL without suffices (options and/or anchor)
495 if (arg) *arg = '(';
496 if (!arg && !gSystem->GetPathInfo(path.Data(), &id, &size, &flags, &modtime)) {
497 if ((flags & 2)) {
498 // if directory set it in fWorkDir
499 if (pwd == "") {
500 pwd = gSystem->WorkingDirectory();
501 fWorkDir = expandedDir;
502 gSystem->ChangeDirectory(expandedDir);
503 argv[i] = null;
504 } else if (!strcmp(gROOT->GetName(), "Rint")) {
505 Warning("GetOptions", "only one directory argument can be specified (%s)", expandedDir.Data());
506 }
507 } else if (size > 0) {
508 // if file add to list of files to be processed
509 if (!fFiles) fFiles = new TObjArray;
510 fFiles->Add(new TObjString(path.Data()));
511 argv[i] = null;
512 } else {
513 Warning("GetOptions", "file %s has size 0, skipping", expandedDir.Data());
514 }
515 } else {
516 if (TString(udir.GetFile()).EndsWith(".root")) {
517 if (!strcmp(udir.GetProtocol(), "file")) {
518 // file ending on .root but does not exist, likely a typo
519 // warn user if plain root...
520 if (!strcmp(gROOT->GetName(), "Rint"))
521 Warning("GetOptions", "file %s not found", expandedDir.Data());
522 } else {
523 // remote file, give it the benefit of the doubt and add it to list of files
524 if (!fFiles) fFiles = new TObjArray;
525 fFiles->Add(new TObjString(argv[i]));
526 argv[i] = null;
527 }
528 } else {
529 TString mode,fargs,io;
530 TString fname = gSystem->SplitAclicMode(expandedDir,mode,fargs,io);
531 char *mac;
532 if (!fFiles) fFiles = new TObjArray;
533 if ((mac = gSystem->Which(TROOT::GetMacroPath(), fname,
534 kReadPermission))) {
535 // if file add to list of files to be processed
536 fFiles->Add(new TObjString(argv[i]));
537 argv[i] = null;
538 delete [] mac;
539 } else {
540 // if file add an invalid entry to list of files to be processed
541 fFiles->Add(new TNamed("NOT FOUND!", argv[i]));
542 // only warn if we're plain root,
543 // other progs might have their own params
544 if (!strcmp(gROOT->GetName(), "Rint"))
545 Warning("GetOptions", "macro %s not found", fname.Data());
546 }
547 }
548 }
549 }
550 // ignore unknown options
551 }
552
553 // go back to startup directory
554 if (pwd != "")
556
557 // remove handled arguments from argument array
558 j = 0;
559 for (i = 0; i < *argc; i++) {
560 if (strcmp(argv[i], "")) {
561 argv[j] = argv[i];
562 j++;
563 }
564 }
565
566 *argc = j;
567}
568
569////////////////////////////////////////////////////////////////////////////////
570/// Handle idle timeout. When this timer expires the registered idle command
571/// will be executed by this routine and a signal will be emitted.
572
574{
575 if (!fIdleCommand.IsNull())
577
578 Emit("HandleIdleTimer()");
579}
580
581////////////////////////////////////////////////////////////////////////////////
582/// Handle exceptions (kSigBus, kSigSegmentationViolation,
583/// kSigIllegalInstruction and kSigFloatingException) trapped in TSystem.
584/// Specific TApplication implementations may want something different here.
585
587{
588 if (TROOT::Initialized()) {
589 if (gException) {
590 gInterpreter->RewindDictionary();
591 gInterpreter->ClearFileBusy();
592 }
593 if (fExitOnException == kExit)
594 gSystem->Exit(128 + sig);
595 else if (fExitOnException == kAbort)
596 gSystem->Abort();
597 else
598 Throw(sig);
599 }
600 gSystem->Exit(128 + sig);
601}
602
603////////////////////////////////////////////////////////////////////////////////
604/// Set the exit on exception option. Setting this option determines what
605/// happens in HandleException() in case an exception (kSigBus,
606/// kSigSegmentationViolation, kSigIllegalInstruction or kSigFloatingException)
607/// is trapped. Choices are: kDontExit (default), kExit or kAbort.
608/// Returns the previous value.
609
611{
613 fExitOnException = opt;
614 return old;
615}
616
617/////////////////////////////////////////////////////////////////////////////////
618/// The function generates and executes a command that loads the Doxygen URL in
619/// a browser. It works for Mac, Windows and Linux. In the case of Linux, the
620/// function also checks if the DISPLAY is set. If it isn't, a warning message
621/// and the URL will be displayed on the terminal.
622///
623/// \param[in] url web page to be displayed in a browser
624
626{
627 // We check what operating system the user has.
628#ifdef R__MACOSX
629 // Command for opening a browser on Mac.
630 TString cMac("open ");
631 // We generate the full command and execute it.
632 cMac.Append(url);
633 gSystem->Exec(cMac);
634#elif defined(R__WIN32)
635 // Command for opening a browser on Windows.
636 TString cWindows("start \"\" ");
637 cWindows.Append(url);
638 gSystem->Exec(cWindows);
639#else
640 // Command for opening a browser in Linux.
641 TString cLinux("xdg-open ");
642 // For Linux we check if the DISPLAY is set.
643 if (gSystem->Getenv("DISPLAY")) {
644 // If the DISPLAY is set it will open the browser.
645 cLinux.Append(url);
646 gSystem->Exec(cLinux);
647 } else {
648 // Else the user will have a warning and the URL in the terminal.
649 Warning("OpenInBrowser", "The $DISPLAY is not set! Please open (e.g. Ctrl-click) %s\n", url.Data());
650 return;
651 }
652#endif
653 Info("OpenInBrowser", "A new tab should have opened in your browser.");
654}
655
656namespace {
657enum EUrl { kURLforClass, kURLforNameSpace, kURLforStruct };
658////////////////////////////////////////////////////////////////////////////////
659/// The function generates a URL address for class or namespace (scopeName).
660/// This is the URL to the online reference guide, generated by Doxygen.
661/// With the enumeration "EUrl" we pick which case we need - the one for
662/// class (kURLforClass) or the one for namespace (kURLforNameSpace).
663///
664/// \param[in] scopeName the name of the class or the namespace
665/// \param[in] scopeType the enumerator for class or namespace
666
667static TString UrlGenerator(TString scopeName, EUrl scopeType)
668{
669 // We start the URL with a static part, the same for all scopes and members.
670 TString url = "https://root.cern/doc/";
671 // Then we check the ROOT version used.
672 TPRegexp re4(R"(.*/(v\d)-(\d\d)-00-patches)");
673 const char *branchName = gROOT->GetGitBranch();
674 TObjArray *objarr = re4.MatchS(branchName);
675 TString version;
676 // We extract the correct version name for the URL.
677 if (objarr && objarr->GetEntries() == 3) {
678 // We have a valid version of ROOT and we will extract the correct name for the URL.
679 version = ((TObjString *)objarr->At(1))->GetString() + ((TObjString *)objarr->At(2))->GetString();
680 } else {
681 // If it's not a supported version, we will go to "master" branch.
682 version = "master";
683 }
684 delete objarr;
685 url.Append(version);
686 url.Append("/");
687 // We will replace all "::" with "_1_1" and all "_" with "__" in the
688 // classes definitions, due to Doxygen syntax requirements.
689 scopeName.ReplaceAll("_", "__");
690 scopeName.ReplaceAll("::", "_1_1");
691 // We build the URL for the correct scope type and name.
692 if (scopeType == kURLforClass) {
693 url.Append("class");
694 } else if (scopeType == kURLforStruct) {
695 url.Append("struct");
696 } else {
697 url.Append("namespace");
698 }
699 url.Append(scopeName);
700 url.Append(".html");
701 return url;
702}
703} // namespace
704
705namespace {
706////////////////////////////////////////////////////////////////////////////////
707/// The function returns a TString with the arguments of a method from the
708/// scope (scopeName), but modified with respect to Doxygen syntax - spacing
709/// around special symbols and adding the missing scopes ("std::").
710/// "FormatMethodArgsForDoxygen" works for functions defined inside namespaces
711/// as well. We avoid looking up twice for the TFunction by passing "func".
712///
713/// \param[in] scopeName the name of the class/namespace/struct
714/// \param[in] func pointer to the method
715
716static TString FormatMethodArgsForDoxygen(const TString &scopeName, TFunction *func)
717{
718 // With "GetSignature" we get the arguments of the method and put them in a TString.
719 TString methodArguments = func->GetSignature();
720 // "methodArguments" is modified with respect of Doxygen requirements.
721 methodArguments.ReplaceAll(" = ", "=");
722 methodArguments.ReplaceAll("* ", " *");
723 methodArguments.ReplaceAll("*=", " *=");
724 methodArguments.ReplaceAll("*)", " *)");
725 methodArguments.ReplaceAll("*,", " *,");
726 methodArguments.ReplaceAll("*& ", " *&");
727 methodArguments.ReplaceAll("& ", " &");
728 // TODO: prepend "std::" to all stdlib classes!
729 methodArguments.ReplaceAll("ostream", "std::ostream");
730 methodArguments.ReplaceAll("istream", "std::istream");
731 methodArguments.ReplaceAll("map", "std::map");
732 methodArguments.ReplaceAll("vector", "std::vector");
733 // We need to replace the "currentClass::foo" with "foo" in the arguments.
734 // TODO: protect the global functions.
735 TString scopeNameRE("\\b");
736 scopeNameRE.Append(scopeName);
737 scopeNameRE.Append("::\\b");
738 TPRegexp argFix(scopeNameRE);
739 argFix.Substitute(methodArguments, "");
740 return methodArguments;
741}
742} // namespace
743
744namespace {
745////////////////////////////////////////////////////////////////////////////////
746/// The function returns a TString with the text as an encoded url so that it
747/// can be passed to the function OpenInBrowser
748///
749/// \param[in] text the input text
750/// \return the text appropriately escaped
751
752static TString FormatHttpUrl(TString text)
753{
754 text.ReplaceAll("\n","%0A");
755 text.ReplaceAll("#","%23");
756 text.ReplaceAll(";","%3B");
757 text.ReplaceAll("\"","%22");
758 text.ReplaceAll("`","%60");
759 text.ReplaceAll("+","%2B");
760 text.ReplaceAll("/","%2F");
761 return text;
762}
763} // namespace
764
765namespace {
766////////////////////////////////////////////////////////////////////////////////
767/// The function checks if a member function of a scope is defined as inline.
768/// If so, it also checks if it is virtual. Then the return type of "func" is
769/// modified for the need of Doxygen and with respect to the function
770/// definition. We pass pointer to the method (func) to not re-do the
771/// TFunction lookup.
772///
773/// \param[in] scopeName the name of the class/namespace/struct
774/// \param[in] func pointer to the method
775
776static TString FormatReturnTypeForDoxygen(const TString &scopeName, TFunction *func)
777{
778 // We put the return type of "func" in a TString "returnType".
779 TString returnType = func->GetReturnTypeName();
780 // If the return type is a type nested in the current class, it will appear scoped (Class::Enumeration).
781 // Below we make sure to remove the current class, because the syntax of Doxygen requires it.
782 TString scopeNameRE("\\b");
783 scopeNameRE.Append(scopeName);
784 scopeNameRE.Append("::\\b");
785 TPRegexp returnFix(scopeNameRE);
786 returnFix.Substitute(returnType, "");
787 // We check is if the method is defined as inline.
788 if (func->ExtraProperty() & kIsInlined) {
789 // We check if the function is defined as virtual.
790 if (func->Property() & kIsVirtual) {
791 // If the function is virtual, we append "virtual" before the return type.
792 returnType.Prepend("virtual ");
793 }
794 returnType.ReplaceAll(" *", "*");
795 } else {
796 // If the function is not inline we only change the spacing in "returnType"
797 returnType.ReplaceAll("*", " *");
798 }
799 // In any case (with no respect to virtual/inline check) we need to change
800 // the return type as following.
801 // TODO: prepend "std::" to all stdlib classes!
802 returnType.ReplaceAll("istream", "std::istream");
803 returnType.ReplaceAll("ostream", "std::ostream");
804 returnType.ReplaceAll("map", "std::map");
805 returnType.ReplaceAll("vector", "std::vector");
806 returnType.ReplaceAll("&", " &");
807 return returnType;
808}
809} // namespace
810
811namespace {
812////////////////////////////////////////////////////////////////////////////////
813/// The function generates a URL for "dataMemberName" defined in "scopeName".
814/// It returns a TString with the URL used in the online reference guide,
815/// generated with Doxygen. For data members the URL consist of 2 parts -
816/// URL for "scopeName" and a part for "dataMemberName".
817/// For enumerator, the URL could be separated into 3 parts - URL for
818/// "scopeName", part for the enumeration and a part for the enumerator.
819///
820/// \param[in] scopeName the name of the class/namespace/struct
821/// \param[in] dataMemberName the name of the data member/enumerator
822/// \param[in] dataMember pointer to the data member/enumerator
823/// \param[in] scopeType enumerator to the scope type
824
825static TString
826GetUrlForDataMember(const TString &scopeName, const TString &dataMemberName, TDataMember *dataMember, EUrl scopeType)
827{
828 // We first check if the data member is not enumerator.
829 if (!dataMember->IsEnum()) {
830 // If we work with data members, we have to append a hashed with MD5 text, consisting of:
831 // "Type ClassName::DataMemberNameDataMemberName(arguments)".
832 // We first get the type of the data member.
833 TString md5DataMember(dataMember->GetFullTypeName());
834 md5DataMember.Append(" ");
835 // We append the scopeName and "::".
836 md5DataMember.Append(scopeName);
837 md5DataMember.Append("::");
838 // We append the dataMemberName twice.
839 md5DataMember.Append(dataMemberName);
840 md5DataMember.Append(dataMemberName);
841 // We call UrlGenerator for the scopeName.
842 TString urlForDataMember = UrlGenerator(scopeName, scopeType);
843 // Then we append "#a" and the hashed text.
844 urlForDataMember.Append("#a");
845 urlForDataMember.Append(md5DataMember.MD5());
846 return urlForDataMember;
847 }
848 // If the data member is enumerator, then we first have to check if the enumeration is anonymous.
849 // Doxygen requires different syntax for anonymous enumeration ("scopeName::@1@1").
850 // We create a TString with the name of the scope and the enumeration from which the enumerator is.
851 TString scopeEnumeration = dataMember->GetTrueTypeName();
852 TString md5EnumClass;
853 if (scopeEnumeration.Contains("(unnamed)")) {
854 // FIXME: need to investigate the numbering scheme.
855 md5EnumClass.Append(scopeName);
856 md5EnumClass.Append("::@1@1");
857 } else {
858 // If the enumeration is not anonymous we put "scopeName::Enumeration" in a TString,
859 // which will be hashed with MD5 later.
860 md5EnumClass.Append(scopeEnumeration);
861 // We extract the part after "::" (this is the enumerator name).
862 TString enumOnlyName = TClassEdit::GetUnqualifiedName(scopeEnumeration);
863 // The syntax is "Class::EnumeratorEnumerator
864 md5EnumClass.Append(enumOnlyName);
865 }
866 // The next part of the URL is hashed "@ scopeName::EnumeratorEnumerator".
867 TString md5Enumerator("@ ");
868 md5Enumerator.Append(scopeName);
869 md5Enumerator.Append("::");
870 md5Enumerator.Append(dataMemberName);
871 md5Enumerator.Append(dataMemberName);
872 // We make the URL for the "scopeName".
873 TString url = UrlGenerator(scopeName, scopeType);
874 // Then we have to append the hashed text for the enumerator.
875 url.Append("#a");
876 url.Append(md5EnumClass.MD5());
877 // We append "a" and then the next hashed text.
878 url.Append("a");
879 url.Append(md5Enumerator.MD5());
880 return url;
881}
882} // namespace
883
884namespace {
885////////////////////////////////////////////////////////////////////////////////
886/// The function generates URL for enumeration. The hashed text consist of:
887/// "Class::EnumerationEnumeration".
888///
889/// \param[in] scopeName the name of the class/namespace/struct
890/// \param[in] enumeration the name of the enumeration
891/// \param[in] scopeType enumerator for class/namespace/struct
892
893static TString GetUrlForEnumeration(TString scopeName, const TString &enumeration, EUrl scopeType)
894{
895 // The URL consists of URL for the "scopeName", "#a" and hashed as MD5 text.
896 // The text is "Class::EnumerationEnumeration.
897 TString md5Enumeration(scopeName);
898 md5Enumeration.Append("::");
899 md5Enumeration.Append(enumeration);
900 md5Enumeration.Append(enumeration);
901 // We make the URL for the scope "scopeName".
902 TString url(UrlGenerator(scopeName, scopeType));
903 // Then we have to append "#a" and the hashed text.
904 url.Append("#a");
905 url.Append(md5Enumeration.MD5());
906 return url;
907}
908} // namespace
909
910namespace {
911enum EMethodKind { kURLforMethod, kURLforStructor };
912////////////////////////////////////////////////////////////////////////////////
913/// The function generates URL for any member function (including Constructor/
914/// Destructor) of "scopeName". Doxygen first generates the URL for the scope.
915/// We do that with the help of "UrlGenerator". Then we append "#a" and a
916/// hashed with MD5 text. It consists of:
917/// "ReturnType ScopeName::MethodNameMethodName(Method arguments)".
918/// For constructor/destructor of a class, the return type is not appended.
919///
920/// \param[in] scopeName the name of the class/namespace/struct
921/// \param[in] methodName the name of the method from the scope
922/// \param[in] func pointer to the method
923/// \param[in] methodType enumerator for method or constructor
924/// \param[in] scopeType enumerator for class/namespace/struct
925
926static TString GetUrlForMethod(const TString &scopeName, const TString &methodName, TFunction *func,
927 EMethodKind methodType, EUrl scopeType)
928{
929 TString md5Text;
930 if (methodType == kURLforMethod) {
931 // In the case of method, we append the return type too.
932 // "FormatReturnTypeForDoxygen" modifies the return type with respect to Doxygen's requirement.
933 md5Text.Append((FormatReturnTypeForDoxygen(scopeName, func)));
934 if (scopeType == kURLforNameSpace) {
935 // We need to append "constexpr" if we work with constexpr functions in namespaces.
936 if (func->Property() & kIsConstexpr) {
937 md5Text.Prepend("constexpr ");
938 }
939 }
940 md5Text.Append(" ");
941 }
942 // We append ScopeName::MethodNameMethodName.
943 md5Text.Append(scopeName);
944 md5Text.Append("::");
945 md5Text.Append(methodName);
946 md5Text.Append(methodName);
947 // We use "FormatMethodArgsForDoxygen" to modify the arguments of Method with respect of Doxygen.
948 md5Text.Append(FormatMethodArgsForDoxygen(scopeName, func));
949 // We generate the URL for the class/namespace/struct.
950 TString url = UrlGenerator(scopeName, scopeType);
951 url.Append("#a");
952 // We append the hashed text.
953 url.Append(md5Text.MD5());
954 return url;
955}
956} // namespace
957
958////////////////////////////////////////////////////////////////////////////////
959/// It gets the ROOT installation setup as TString
960///
961/// \return a string with several lines
962///
964{
965 std::vector<TString> lines;
966 lines.emplace_back("```");
967 lines.emplace_back(TString::Format("ROOT v%s",
968 gROOT->GetVersion()));
969 lines.emplace_back(TString::Format("Built for %s on %s", gSystem->GetBuildArch(), gROOT->GetGitDate()));
970 if (!strcmp(gROOT->GetGitBranch(), gROOT->GetGitCommit())) {
971 static const char *months[] = {"January","February","March","April","May",
972 "June","July","August","September","October",
973 "November","December"};
974 Int_t idatqq = gROOT->GetVersionDate();
975 Int_t iday = idatqq%100;
976 Int_t imonth = (idatqq/100)%100;
977 Int_t iyear = (idatqq/10000);
978
979 lines.emplace_back(TString::Format("From tag %s, %d %s %4d",
980 gROOT->GetGitBranch(),
981 iday,months[imonth-1],iyear));
982 } else {
983 // If branch and commit are identical - e.g. "v5-34-18" - then we have
984 // a release build. Else specify the git hash this build was made from.
985 lines.emplace_back(TString::Format("From %s@%s",
986 gROOT->GetGitBranch(),
987 gROOT->GetGitCommit()));
988 }
989 lines.emplace_back(TString::Format("With %s",
991 lines.emplace_back("Binary directory: "+ gROOT->GetBinDir());
992 lines.emplace_back("```");
993 TString setup = "";
994 for (auto& line : lines) {
995 setup.Append(line);
996 setup.Append('\n');
997 }
998 setup.Chop(); // trim final `\n`
999 return setup;
1000}
1001
1002////////////////////////////////////////////////////////////////////////////////
1003/// It opens a Forum topic in a web browser with prefilled ROOT version
1004///
1005/// \param[in] type the issue type (only bug supported right now)
1006
1008{
1009 // https://meta.discourse.org/t/how-to-create-a-post-clicking-a-link/96197
1010
1011 if (type == "bug") {
1012 //OpenInBrowser("\"https://root-forum.cern.ch/new-topic?title=topic%20title&body=topic%20body&category=category/subcategory&tags=email,planned\"");
1013 TString report_template =
1014R"(___
1015_Please read [tips for efficient and successful posting](https://root-forum.cern.ch/t/tips-for-efficient-and-successful-posting/28292) and [posting code](https://root-forum.cern.ch/t/posting-code-read-this-first/28293)_
1016
1017### Describe the bug
1018<!--
1019A clear and concise description of what the wrong behavior is.
1020-->
1021### Expected behavior
1022<!--
1023A clear and concise description of what you expected to happen.
1024-->
1025
1026### To Reproduce
1027<!--
1028Steps to reproduce the behavior:
10291. Your code that triggers the issue: at least a part; ideally something we can run ourselves.
10302. Don't forget to attach the required input files!
10313. How to run your code and / or build it, e.g. `root myMacro.C`, ...
1032-->
1033
1034### Setup
1035```
1036)"+GetSetup()+
1037R"(```
1038
1039<!--
1040Please specify also how you obtained ROOT, such as `dnf install` / binary download / you built it yourself.
1041-->
1042
1043### Additional context
1044<!--
1045Add any other context about the problem here.
1046-->)";
1047 report_template = FormatHttpUrl(report_template);
1048
1049 OpenInBrowser("\"https://root-forum.cern.ch/new-topic?category=ROOT&tags=bug&body="+report_template+"&\"");
1050 } else {
1051 Warning("OpenForumTopic", "cannot find \"%s\" as type for a Forum topic\n"
1052 "Available types are 'bug'.", type.Data());
1053 }
1054}
1055
1056////////////////////////////////////////////////////////////////////////////////
1057/// It opens a GitHub issue in a web browser with prefilled ROOT version
1058///
1059/// \param[in] type the issue type (bug, feature or improvement)
1060
1062{
1063 // https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue#creating-an-issue-from-a-url-query
1064
1065 if (type == "bug") {
1067 "\"https://github.com/root-project/root/issues/new?labels=bug&template=bug_report.yml&root-version=" +
1068 FormatHttpUrl(GetSetup()) + "\"");
1069 } else if (type == "improvement") {
1070 OpenInBrowser("\"https://github.com/root-project/root/issues/"
1071 "new?labels=improvement&template=improvement_report.yml&root-version=" +
1072 FormatHttpUrl(GetSetup()) + "\"");
1073 } else if (type == "feature") {
1075 "\"https://github.com/root-project/root/issues/new?labels=new+feature&template=feature_request.yml\"");
1076 } else {
1077 Warning("OpenGitHubIssue",
1078 "Cannot find GitHub issue type \"%s\".\n"
1079 "Available types are 'bug', 'feature' and 'improvement'.",
1080 type.Data());
1081 }
1082}
1083
1084////////////////////////////////////////////////////////////////////////////////
1085/// It opens the online reference guide, generated with Doxygen, for the
1086/// chosen scope (class/namespace/struct) or member (method/function/
1087/// data member/enumeration/enumerator. If the user types incorrect value,
1088/// it will return an error or warning.
1089///
1090/// \param[in] strippedClass the scope or scope::member
1091
1092void TApplication::OpenReferenceGuideFor(const TString &strippedClass)
1093{
1094 // We check if the user is searching for a scope and if the scope exists.
1095 if (TClass *clas = TClass::GetClass(strippedClass)) {
1096 // We check what scope he is searching for (class/namespace/struct).
1097 // Enumerators will switch between the possible cases.
1098 EUrl scopeType;
1099 if (clas->Property() & kIsNamespace) {
1100 scopeType = kURLforNameSpace;
1101 } else if (clas->Property() & kIsStruct) {
1102 scopeType = kURLforStruct;
1103 } else {
1104 scopeType = kURLforClass;
1105 }
1106 // If the user search directly for a scope we open the URL for him with OpenInBrowser.
1107 OpenInBrowser(UrlGenerator(strippedClass, scopeType));
1108 return;
1109 }
1110 // Else we subtract the name of the method and remove it from the command.
1111 TString memberName = TClassEdit::GetUnqualifiedName(strippedClass);
1112 // Error out if "strippedClass" is un-scoped (and it's not a class, see `TClass::GetClass(strippedClass)` above).
1113 // TODO: Global functions.
1114 if (strippedClass == memberName) {
1115 Error("OpenReferenceGuideFor", "Unknown entity \"%s\" - global variables / functions not supported yet!",
1116 strippedClass.Data());
1117 return;
1118 }
1119 // Else we remove the member name to be left with the scope.
1120 TString scopeName = strippedClass(0, strippedClass.Length() - memberName.Length() - 2);
1121 // We check if the scope exists in ROOT.
1122 TClass *cl = TClass::GetClass(scopeName);
1123 if (!cl) {
1124 // That's a member of something ROOT doesn't know.
1125 Warning("OpenReferenceGuideFor", "\"%s\" does not exist in ROOT!", scopeName.Data());
1126 return;
1127 }
1128 // We have enumerators for the three available cases - class, namespace and struct.
1129 EUrl scopeType;
1130 if (cl->Property() & kIsNamespace) {
1131 scopeType = kURLforNameSpace;
1132 } else if (cl->Property() & kIsStruct) {
1133 scopeType = kURLforStruct;
1134 } else {
1135 scopeType = kURLforClass;
1136 }
1137 // If the user wants to search for a method, we take its name (memberName) and
1138 // modify it - we delete everything starting at the first "(" so the user won't have to
1139 // do it by hand when they use Tab.
1140 int bracket = memberName.First("(");
1141 if (bracket > 0) {
1142 memberName.Remove(bracket);
1143 }
1144 // We check if "memberName" is a member function of "cl" or any of its base classes.
1145 if (TFunction *func = cl->GetMethodAllAny(memberName)) {
1146 // If so we find the name of the class that it belongs to.
1147 TString baseClName = ((TMethod *)func)->GetClass()->GetName();
1148 // We define an enumerator to distinguish between structor and method.
1149 EMethodKind methodType;
1150 // We check if "memberName" is a constructor.
1151 if (baseClName == memberName) {
1152 methodType = kURLforStructor;
1153 // We check if "memberName" is a destructor.
1154 } else if (memberName[0] == '~') {
1155 methodType = kURLforStructor;
1156 // We check if "memberName" is a method.
1157 } else {
1158 methodType = kURLforMethod;
1159 }
1160 // We call "GetUrlForMethod" for the correct class and scope.
1161 OpenInBrowser(GetUrlForMethod(baseClName, memberName, func, methodType, scopeType));
1162 return;
1163 }
1164 // We check if "memberName" is an enumeration.
1165 if (cl->GetListOfEnums()->FindObject(memberName)) {
1166 // If so with OpenInBrowser we open the URL generated with GetUrlForEnumeration
1167 // with respect to the "scopeType".
1168 OpenInBrowser(GetUrlForEnumeration(scopeName, memberName, scopeType));
1169 return;
1170 }
1171
1172 // We check if "memberName" is enumerator defined in one the base classes of "scopeName".
1173 if (auto enumerator = (TDataMember *)cl->GetListOfAllPublicDataMembers()->FindObject(memberName)) {
1174 // We find the actual scope (might be in a base) and open the URL in a browser.
1175 TString baseClName = ((TMethod *)enumerator->GetClass())->GetName();
1176 OpenInBrowser(GetUrlForDataMember(baseClName, memberName, enumerator, scopeType));
1177 return;
1178 }
1179
1180 // Warning message will appear if the user types the function name incorrectly
1181 // or the function is not a member function of "cl" or any of its base classes.
1182 Warning("OpenReferenceGuideFor", "cannot find \"%s\" as member of %s or its base classes! Check %s\n", memberName.Data(),
1183 scopeName.Data(), UrlGenerator(scopeName, scopeType).Data());
1184}
1185
1186////////////////////////////////////////////////////////////////////////////////
1187/// The function (".forum <type>") submits a new post on the ROOT forum
1188/// via web browser.
1189/// \note You can use "bug" as <type>.
1190/// \param[in] line command from the command line
1191
1192void TApplication::Forum(const char *line)
1193{
1194 // We first check if the user chose a correct syntax.
1195 TString strippedCommand = TString(line).Strip(TString::kBoth);
1196 if (!strippedCommand.BeginsWith(".forum ")) {
1197 Error("Forum", "Unknown command! Use 'bug' after '.forum '");
1198 return;
1199 }
1200 // We remove the command ".forum" from the TString.
1201 strippedCommand.Remove(0, 7);
1202 // We strip the command line after removing ".help" or ".?".
1203 strippedCommand = strippedCommand.Strip(TString::kBoth);
1205 OpenForumTopic(strippedCommand);
1206}
1207
1208////////////////////////////////////////////////////////////////////////////////
1209/// The function (".gh <type>") submits a new issue on GitHub via web browser.
1210/// \note You can use "bug", "feature" or "improvement" as <type>.
1211/// \param[in] line command from the command line
1212
1213void TApplication::GitHub(const char *line)
1214{
1215 // We first check if the user chose a correct syntax.
1216 TString strippedCommand = TString(line).Strip(TString::kBoth);
1217 if (!strippedCommand.BeginsWith(".gh ")) {
1218 Error("GitHub", "Unknown command! Use 'bug', 'feature' or 'improvement' after '.gh '");
1219 return;
1220 }
1221 // We remove the command ".gh" from the TString.
1222 strippedCommand.Remove(0, 4);
1223 // We strip the command line after removing ".help" or ".?".
1224 strippedCommand = strippedCommand.Strip(TString::kBoth);
1225
1226 OpenGitHubIssue(strippedCommand);
1227}
1228
1229////////////////////////////////////////////////////////////////////////////////
1230/// The function lists useful commands (".help") or opens the online reference
1231/// guide, generated with Doxygen (".help scope" or ".help scope::member").
1232/// \note You can use ".?" as the short version of ".help"
1233/// \param[in] line command from the command line
1234
1235void TApplication::Help(const char *line)
1236{
1237 // We first check if the user wants to print the help on the interpreter.
1238 TString strippedCommand = TString(line).Strip(TString::kBoth);
1239 // If the user chooses ".help" or ".?".
1240 if ((strippedCommand == ".help") || (strippedCommand == ".?")) {
1241 gInterpreter->ProcessLine(line);
1242 Printf("\n ROOT special commands.");
1243 Printf(" ==============================================================================");
1244 Printf(" .L <filename>[flags]: load the given file with optional flags like\n"
1245 " + to compile or ++ to force recompile.\n"
1246 " Type .? TSystem::CompileMacro for a list of all flags.\n"
1247 " <filename> can also be a shared library; skip flags.");
1248 Printf(" .(x|X) <filename>[flags](args) :\n"
1249 " same as .L <filename>[flags] and runs then a function\n"
1250 " with signature: ret_type filename(args).");
1251 Printf(" .credits : show credits");
1252 Printf(" .demo : launch GUI demo");
1253 Printf(" .forum bug : ask for help with a bug or crash at the ROOT forum.");
1254 Printf(" .gh [bug|feature|improvement]\n"
1255 " : submit a bug report, feature or improvement suggestion");
1256 Printf(" .help Class::Member : open reference guide for that class member (or .?).\n"
1257 " Specifying '::Member' is optional.");
1258 Printf(" .help edit : show line editing shortcuts (or .?)");
1259 Printf(" .license : show license");
1260 Printf(" .ls : list contents of current TDirectory");
1261 Printf(" .pwd : show current TDirectory, pad and style");
1262 Printf(" .quit (or .exit) : quit ROOT (long form of .q)");
1263 Printf(" .R [user@]host[:dir] [-l user] [-d dbg] [script] :\n"
1264 " launch process in a remote host");
1265 Printf(" .qqq : quit ROOT - mandatory");
1266 Printf(" .qqqqq : exit process immediately");
1267 Printf(" .qqqqqqq : abort process");
1268 Printf(" .which [file] : show path of macro file");
1269 Printf(" .![OS_command] : execute OS-specific shell command");
1270 Printf(" .!root -? : print ROOT usage (CLI options)");
1271 return;
1272 } else {
1273 // If the user wants to use the extended ".help scopeName" command to access
1274 // the online reference guide, we first check if the command starts correctly.
1275 if ((!strippedCommand.BeginsWith(".help ")) && (!strippedCommand.BeginsWith(".? "))) {
1276 Error("Help", "Unknown command!");
1277 return;
1278 }
1279 // We remove the command ".help" or ".?" from the TString.
1280 if (strippedCommand.BeginsWith(".? ")) {
1281 strippedCommand.Remove(0, 3);
1282 } else {
1283 strippedCommand.Remove(0, 5);
1284 }
1285 // We strip the command line after removing ".help" or ".?".
1286 strippedCommand = strippedCommand.Strip(TString::kBoth);
1287
1288 if (strippedCommand == "edit") {
1289 Printf("\n ROOT terminal keyboard shortcuts (GNU-readline style).");
1290 #ifdef R__MACOSX
1291 #define FOOTNOTE " *"
1292 Printf("* Some of these commands might be intercepted by macOS predefined system shortcuts.");
1293 // https://apple.stackexchange.com/questions/18043/how-can-i-make-ctrlright-left-arrow-stop-changing-desktops-in-lion
1294 #else
1295 #define FOOTNOTE ""
1296 #endif
1297 Printf(" ==============================================================================");
1298 Printf(" Arrow_Left : move cursor left [Ctrl+B]");
1299 Printf(" Arrow_Right : move cursor right [Ctrl+F] [Ctrl+G]");
1300 #ifdef R__MACOSX
1301 Printf(" Fn+Arrow_Left : move cursor to beginning of line [Ctrl+A]");
1302 #else
1303 Printf(" Home : move cursor to beginning of line [Ctrl+A]");
1304 #endif
1305 #ifdef R__MACOSX
1306 Printf(" Fn+Arrow_Right : move cursor to end of line [Ctrl+E]");
1307 #else
1308 Printf(" End : move cursor to end of line [Ctrl+E]");
1309 #endif
1310 Printf(" Ctrl+Arrow_Left : jump to previous word [Esc,B] [Alt,B]" FOOTNOTE);
1311 Printf(" Ctrl+Arrow_Right : jump to next word [Esc,F] [Alt,F]" FOOTNOTE);
1312
1313 Printf(" Backspace : delete previous character [Ctrl+H]");
1314 Printf(" Del : delete next character [Ctrl+D]");
1315 Printf(" Esc,Backspace : delete previous word [Ctrl+W] [Esc,Ctrl+H] [Alt+Backspace] [Esc,Del] [Esc,Ctrl+Del]" FOOTNOTE);// Del is 0x7F on macOS
1316 Printf(" Ctrl+Del : delete next word [Esc,D] [Alt,D]" FOOTNOTE);
1317 Printf(" Ctrl+U : cut all characters between cursor and start of line");
1318 Printf(" Ctrl+K : cut all characters between cursor and end of line");
1319
1320 Printf(" Ctrl+T : transpose characters");
1321 Printf(" Esc,C : character to upper and jump to next word");
1322 Printf(" Esc,L : word to lower case and jump to its end");
1323 Printf(" Esc,U : word to upper case and jump to its end");
1324 Printf(" Ctrl+Shift+C : copy clipboard content");
1325 Printf(" Ctrl+Shift+V : paste clipboard content [Ctrl+Y] [Alt+Y]");
1326 #ifdef R__MACOSX
1327 Printf(" Fn+Enter : toggle overwrite mode");
1328 #else
1329 Printf(" Ins : toggle overwrite mode");
1330 #endif
1331
1332 Printf(" Ctrl+_ : undo last keypress action");
1333 Printf(" Tab : autocomplete command or print suggestions [Ctrl+I] [Esc,Tab]");
1334 Printf(" Enter : execute command [Ctrl+J] [Ctrl+M]");
1335 Printf(" Ctrl+L : clear prompt screen");
1336 Printf(" Ctrl+D : quit ROOT (if empty line)");
1337 Printf(" Ctrl+C : send kSigInt interrupt signal");
1338 Printf(" Ctrl+Z : send kSigStop pause job signal");
1339
1340 Printf(" Arrow_Down : navigate downwards in command history [Ctrl+N]");
1341 Printf(" Arrow_Up : navigate upwards in command history [Ctrl+P]");
1342 Printf(" Ctrl+R ; Ctrl+S : search command in your history by typing a string.\n"
1343 " Use Backspace if you mistyped (but not arrows).\n"
1344 " Press Ctrl+R (Ctrl+S) repeateadly to navigate matches in reverse (forward) order");
1345 Printf(" Arrow_Right : after Ctrl+R (Ctrl+S), select current match of the history search\n"
1346 " [Ctrl+O] [Enter] [Ctrl+J] [Ctrl+M] [Arrow_Left] [Esc,Esc].\n"
1347 " Use Ctrl+F or Ctrl+G to cancel search and revert original line");
1348
1349 return;
1350 }
1351 // We call the function what handles the extended ".help scopeName" command.
1352 OpenReferenceGuideFor(strippedCommand);
1353 }
1354}
1355
1356/// Load shared libs necessary for graphics. These libraries are only
1357/// loaded when gROOT->IsBatch() is kFALSE.
1358
1360{
1361 if (gROOT->IsBatch())
1362 return;
1363
1364 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPad"))
1365 if (h->LoadPlugin() == -1)
1366 return;
1367
1368 TString name;
1369 TString title1 = "ROOT interface to ";
1370 TString nativex, title;
1371
1372#ifdef R__WIN32
1373 nativex = "win32gdk";
1374 name = "Win32gdk";
1375 title = title1 + "Win32gdk";
1376#elif defined(R__HAS_COCOA)
1377 nativex = "quartz";
1378 name = "quartz";
1379 title = title1 + "Quartz";
1380#else
1381 nativex = "x11";
1382 name = "X11";
1383 title = title1 + "X11";
1384#endif
1385
1386 TString guiBackend = gEnv->GetValue("Gui.Backend", "native");
1387 guiBackend.ToLower();
1388 if (guiBackend == "native") {
1389 guiBackend = nativex;
1390 } else {
1391 name = guiBackend;
1392 title = title1 + guiBackend;
1393 }
1394
1395 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualX", guiBackend)) {
1396 if (h->LoadPlugin() == -1) {
1397 gROOT->SetBatch(kTRUE);
1398 return;
1399 }
1400 gVirtualX = (TVirtualX *) h->ExecPlugin(2, name.Data(), title.Data());
1402 }
1403
1404 TString guiFactory = gEnv->GetValue("Gui.Factory", "native");
1405 guiFactory.ToLower();
1406 if (guiFactory == "native")
1407 guiFactory = "root";
1408
1409 if (auto h = gROOT->GetPluginManager()->FindHandler("TGuiFactory", guiFactory)) {
1410 if (h->LoadPlugin() == -1) {
1411 gROOT->SetBatch(kTRUE);
1412 return;
1413 }
1414 gGuiFactory = (TGuiFactory *) h->ExecPlugin(0);
1415 }
1416}
1417
1418////////////////////////////////////////////////////////////////////////////////
1419/// Switch to batch mode.
1420
1422{
1423 gROOT->SetBatch();
1426#ifndef R__WIN32
1427 if (gVirtualX != gGXBatch) delete gVirtualX;
1428#endif
1430}
1431
1432////////////////////////////////////////////////////////////////////////////////
1433/// Parse the content of a line starting with ".R" (already stripped-off)
1434/// The format is
1435/// ~~~ {.cpp}
1436/// [user@]host[:dir] [-l user] [-d dbg] [script]
1437/// ~~~
1438/// The variable 'dir' is the remote directory to be used as working dir.
1439/// The username can be specified in two ways, "-l" having the priority
1440/// (as in ssh).
1441/// A 'dbg' value > 0 gives increasing verbosity.
1442/// The last argument 'script' allows to specify an alternative script to
1443/// be executed remotely to startup the session.
1444
1446 TString &hostdir, TString &user,
1447 Int_t &dbg, TString &script)
1448{
1449 if (!ln || strlen(ln) <= 0)
1450 return 0;
1451
1452 Int_t rc = 0;
1453 Bool_t isHostDir = kTRUE;
1454 Bool_t isScript = kFALSE;
1455 Bool_t isUser = kFALSE;
1456 Bool_t isDbg = kFALSE;
1457
1458 TString line(ln);
1459 TString tkn;
1460 Int_t from = 0;
1461 while (line.Tokenize(tkn, from, " ")) {
1462 if (tkn == "-l") {
1463 // Next is a user name
1464 isUser = kTRUE;
1465 } else if (tkn == "-d") {
1466 isDbg = kTRUE;
1467 } else if (tkn == "-close") {
1468 rc = 1;
1469 } else if (tkn.BeginsWith("-")) {
1470 ::Warning("TApplication::ParseRemoteLine","unknown option: %s", tkn.Data());
1471 } else {
1472 if (isUser) {
1473 user = tkn;
1474 isUser = kFALSE;
1475 } else if (isDbg) {
1476 dbg = tkn.Atoi();
1477 isDbg = kFALSE;
1478 } else if (isHostDir) {
1479 hostdir = tkn;
1480 hostdir.ReplaceAll(":","/");
1481 isHostDir = kFALSE;
1482 isScript = kTRUE;
1483 } else if (isScript) {
1484 // Add everything left
1485 script = tkn;
1486 script.Insert(0, "\"");
1487 script += "\"";
1488 // isScript = kFALSE; // [clang-tidy] never read
1489 break;
1490 }
1491 }
1492 }
1493
1494 // Done
1495 return rc;
1496}
1497
1498////////////////////////////////////////////////////////////////////////////////
1499/// Process the content of a line starting with ".R" (already stripped-off)
1500/// The format is
1501/// ~~~ {.cpp}
1502/// [user@]host[:dir] [-l user] [-d dbg] [script] | [host] -close
1503/// ~~~
1504/// The variable 'dir' is the remote directory to be used as working dir.
1505/// The username can be specified in two ways, "-l" having the priority
1506/// (as in ssh).
1507/// A 'dbg' value > 0 gives increasing verbosity.
1508/// The last argument 'script' allows to specify an alternative script to
1509/// be executed remotely to startup the session.
1510
1512{
1513 if (!line) return 0;
1514
1515 if (!strncmp(line, "-?", 2) || !strncmp(line, "-h", 2) ||
1516 !strncmp(line, "--help", 6)) {
1517 Info("ProcessRemote", "remote session help:");
1518 Printf(".R [user@]host[:dir] [-l user] [-d dbg] [[<]script] | [host] -close");
1519 Printf("Create a ROOT session on the specified remote host.");
1520 Printf("The variable \"dir\" is the remote directory to be used as working dir.");
1521 Printf("The username can be specified in two ways, \"-l\" having the priority");
1522 Printf("(as in ssh). A \"dbg\" value > 0 gives increasing verbosity.");
1523 Printf("The last argument \"script\" allows to specify an alternative script to");
1524 Printf("be executed remotely to startup the session, \"roots\" being");
1525 Printf("the default. If the script is preceded by a \"<\" the script will be");
1526 Printf("sourced, after which \"roots\" is executed. The sourced script can be ");
1527 Printf("used to change the PATH and other variables, allowing an alternative");
1528 Printf("\"roots\" script to be found.");
1529 Printf("To close down a session do \".R host -close\".");
1530 Printf("To switch between sessions do \".R host\", to switch to the local");
1531 Printf("session do \".R\".");
1532 Printf("To list all open sessions do \"gApplication->GetApplications()->Print()\".");
1533 return 0;
1534 }
1535
1536 TString hostdir, user, script;
1537 Int_t dbg = 0;
1538 Int_t rc = ParseRemoteLine(line, hostdir, user, dbg, script);
1539 if (hostdir.Length() <= 0) {
1540 // Close the remote application if required
1541 if (rc == 1) {
1543 delete fAppRemote;
1544 }
1545 // Return to local run
1546 fAppRemote = nullptr;
1547 // Done
1548 return 1;
1549 } else if (rc == 1) {
1550 // close an existing remote application
1551 TApplication *ap = TApplication::Open(hostdir, 0, nullptr);
1552 if (ap) {
1554 delete ap;
1555 }
1556 }
1557 // Attach or start a remote application
1558 if (user.Length() > 0)
1559 hostdir.Insert(0, TString::Format("%s@", user.Data()));
1560 const char *sc = (script.Length() > 0) ? script.Data() : nullptr;
1561 TApplication *ap = TApplication::Open(hostdir, dbg, sc);
1562 if (ap) {
1563 fAppRemote = ap;
1564 }
1565
1566 // Done
1567 return 1;
1568}
1569
1570namespace {
1571 static int PrintFile(const char* filename) {
1572 TString sFileName(filename);
1573 gSystem->ExpandPathName(sFileName);
1574 if (gSystem->AccessPathName(sFileName)) {
1575 Error("ProcessLine()", "Cannot find file %s", filename);
1576 return 1;
1577 }
1578 std::ifstream instr(sFileName);
1579 TString content;
1580 content.ReadFile(instr);
1581 Printf("%s", content.Data());
1582 return 0;
1583 }
1584 } // namespace
1585
1586////////////////////////////////////////////////////////////////////////////////
1587/// Process a single command line, either a C++ statement or an interpreter
1588/// command starting with a ".".
1589/// Return the return value of the command cast to a long.
1590
1591Longptr_t TApplication::ProcessLine(const char *line, Bool_t sync, Int_t *err)
1592{
1593 if (!line || !*line) return 0;
1594
1595 // If we are asked to go remote do it
1596 if (!strncmp(line, ".R", 2)) {
1597 Int_t n = 2;
1598 while (*(line+n) == ' ')
1599 n++;
1600 return ProcessRemote(line+n, err);
1601 }
1602
1603 // Redirect, if requested
1606 return fAppRemote->ProcessLine(line, err);
1607 }
1608
1609 if (!strncasecmp(line, ".qqqqqqq", 7)) {
1610 gSystem->Abort();
1611 } else if (!strncasecmp(line, ".qqqqq", 5)) {
1612 Info("ProcessLine", "Bye... (try '.qqqqqqq' if still running)");
1613 gSystem->Exit(1);
1614 } else if (!strncasecmp(line, ".exit", 4) || !strncasecmp(line, ".quit", 2)) {
1615 Terminate(0);
1616 return 0;
1617 }
1618
1619 if (!strncmp(line, ".gh", 3)) {
1620 GitHub(line);
1621 return 1;
1622 }
1623
1624 if (!strncmp(line, ".forum", 6)) {
1625 Forum(line);
1626 return 1;
1627 }
1628
1629 if (!strncmp(line, ".?", 2) || !strncmp(line, ".help", 5)) {
1630 Help(line);
1631 return 1;
1632 }
1633
1634 if (!strncmp(line, ".demo", 5)) {
1635 if (gROOT->IsBatch()) {
1636 Error("ProcessLine", "Cannot show demos in batch mode!");
1637 return 1;
1638 }
1639 ProcessLine(".x " + TROOT::GetTutorialDir() + "/demos.C");
1640 return 0;
1641 }
1642
1643 if (!strncmp(line, ".license", 8)) {
1644 return PrintFile(TROOT::GetDocDir() + "/LICENSE");
1645 }
1646
1647 if (!strncmp(line, ".credits", 8)) {
1648 TString credits = TROOT::GetDocDir() + "/CREDITS";
1649 if (gSystem->AccessPathName(credits, kReadPermission))
1650 credits = TROOT::GetDocDir() + "/README/CREDITS";
1651 return PrintFile(credits);
1652 }
1653
1654 if (!strncmp(line, ".pwd", 4)) {
1655 if (gDirectory)
1656 Printf("Current directory: %s", gDirectory->GetPath());
1657 if (gPad)
1658 Printf("Current pad: %s", gPad->GetName());
1659 if (gStyle)
1660 Printf("Current style: %s", gStyle->GetName());
1661 return 1;
1662 }
1663
1664 if (!strncmp(line, ".ls", 3)) {
1665 const char *opt = nullptr;
1666 if (line[3]) opt = &line[3];
1667 if (gDirectory) gDirectory->ls(opt);
1668 return 1;
1669 }
1670
1671 if (!strncmp(line, ".which", 6)) {
1672 char *fn = Strip(line+7);
1673 char *s = strtok(fn, "+("); // this method does not need to be reentrant
1675 if (!mac)
1676 Printf("No macro %s in path %s", s, TROOT::GetMacroPath());
1677 else
1678 Printf("%s", mac);
1679 delete [] fn;
1680 delete [] mac;
1681 return mac ? 1 : 0;
1682 }
1683
1684 if (!strncmp(line, ".L", 2) || !strncmp(line, ".U", 2)) {
1685 TString aclicMode, arguments, io;
1686 TString fname = gSystem->SplitAclicMode(line+3, aclicMode, arguments, io);
1687
1688 char *mac = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1689 if (arguments.Length())
1690 Warning("ProcessLine", "argument(s) \"%s\" ignored with .%c", arguments.Data(), line[1]);
1691 Longptr_t retval = 0;
1692 if (!mac) {
1693 Error("ProcessLine", "macro %s not found in path %s", fname.Data(), TROOT::GetMacroPath());
1694 } else {
1695 TString cmd(line + 1);
1696 Ssiz_t posSpace = cmd.Index(' ');
1697 if (posSpace == kNPOS)
1698 cmd.Remove(1);
1699 else
1700 cmd.Remove(posSpace);
1701 auto tempbuf = TString::Format(".%s %s%s%s", cmd.Data(), mac, aclicMode.Data(), io.Data());
1702 delete[] mac;
1703 if (sync)
1704 retval = gInterpreter->ProcessLineSynch(tempbuf.Data(), (TInterpreter::EErrorCode *)err);
1705 else
1706 retval = gInterpreter->ProcessLine(tempbuf.Data(), (TInterpreter::EErrorCode *)err);
1707 }
1708
1709 InitializeGraphics(gROOT->IsWebDisplay());
1710
1711 return retval;
1712 }
1713
1714 if (!strncmp(line, ".X", 2) || !strncmp(line, ".x", 2)) {
1715 return ProcessFile(line+3, err, line[2] == 'k');
1716 }
1717
1718 if (!strcmp(line, ".reset")) {
1719 // Do nothing, .reset disabled in Cling because too many side effects
1720 Printf("*** .reset not allowed, please use gROOT->Reset() ***");
1721 return 0;
1722
1723#if 0
1724 // delete the ROOT dictionary since CINT will destroy all objects
1725 // referenced by the dictionary classes (TClass et. al.)
1726 gROOT->GetListOfClasses()->Delete();
1727 // fall through
1728#endif
1729 }
1730
1731 if (sync)
1732 return gInterpreter->ProcessLineSynch(line, (TInterpreter::EErrorCode*)err);
1733 else
1734 return gInterpreter->ProcessLine(line, (TInterpreter::EErrorCode*)err);
1735}
1736
1737////////////////////////////////////////////////////////////////////////////////
1738/// Process a file containing a C++ macro.
1739
1740Longptr_t TApplication::ProcessFile(const char *file, Int_t *error, Bool_t keep)
1741{
1742 return ExecuteFile(file, error, keep);
1743}
1744
1745////////////////////////////////////////////////////////////////////////////////
1746/// Execute a file containing a C++ macro (static method). Can be used
1747/// while TApplication is not yet created.
1748
1749Longptr_t TApplication::ExecuteFile(const char *file, Int_t *error, Bool_t keep)
1750{
1751 static const Int_t kBufSize = 1024;
1752
1753 if (!file || !*file) return 0;
1754
1755 TString aclicMode;
1756 TString arguments;
1757 TString io;
1758 TString fname = gSystem->SplitAclicMode(file, aclicMode, arguments, io);
1759
1760 char *exnam = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1761 if (!exnam) {
1762 ::Error("TApplication::ExecuteFile", "macro %s not found in path %s", fname.Data(),
1764 delete [] exnam;
1765 if (error)
1767 return 0;
1768 }
1769
1770 ::std::ifstream macro(exnam, std::ios::in);
1771 if (!macro.good()) {
1772 ::Error("TApplication::ExecuteFile", "%s no such file", exnam);
1773 if (error)
1775 delete [] exnam;
1776 return 0;
1777 }
1778
1779 char currentline[kBufSize];
1780 char dummyline[kBufSize];
1781 int tempfile = 0;
1782 int comment = 0;
1783 int ifndefc = 0;
1784 int ifdef = 0;
1785 char *s = nullptr;
1786 Bool_t execute = kFALSE;
1787 Longptr_t retval = 0;
1788
1789 while (1) {
1790 bool res = (bool)macro.getline(currentline, kBufSize);
1791 if (macro.eof()) break;
1792 if (!res) {
1793 // Probably only read kBufSize, let's ignore the remainder of
1794 // the line.
1795 macro.clear();
1796 while (!macro.getline(dummyline, kBufSize) && !macro.eof()) {
1797 macro.clear();
1798 }
1799 }
1800 s = currentline;
1801 while (s && (*s == ' ' || *s == '\t')) s++; // strip-off leading blanks
1802
1803 // very simple minded pre-processor parsing, only works in case macro file
1804 // starts with "#ifndef __CINT__". In that case everything till next
1805 // "#else" or "#endif" will be skipped.
1806 if (*s == '#') {
1807 char *cs = Compress(currentline);
1808 if (strstr(cs, "#ifndef__CINT__") ||
1809 strstr(cs, "#if!defined(__CINT__)"))
1810 ifndefc = 1;
1811 else if (ifndefc && (strstr(cs, "#ifdef") || strstr(cs, "#ifndef") ||
1812 strstr(cs, "#ifdefined") || strstr(cs, "#if!defined")))
1813 ifdef++;
1814 else if (ifndefc && strstr(cs, "#endif")) {
1815 if (ifdef)
1816 ifdef--;
1817 else
1818 ifndefc = 0;
1819 } else if (ifndefc && !ifdef && strstr(cs, "#else"))
1820 ifndefc = 0;
1821 delete [] cs;
1822 }
1823 if (!*s || *s == '#' || ifndefc || !strncmp(s, "//", 2)) continue;
1824
1825 if (!comment && (!strncmp(s, ".X", 2) || !strncmp(s, ".x", 2))) {
1826 retval = ExecuteFile(s+3);
1827 execute = kTRUE;
1828 continue;
1829 }
1830
1831 if (!strncmp(s, "/*", 2)) comment = 1;
1832 if (comment) {
1833 // handle slightly more complex cases like: /* */ /*
1834again:
1835 s = strstr(s, "*/");
1836 if (s) {
1837 comment = 0;
1838 s += 2;
1839
1840 while (s && (*s == ' ' || *s == '\t')) s++; // strip-off leading blanks
1841 if (!*s) continue;
1842 if (!strncmp(s, "//", 2)) continue;
1843 if (!strncmp(s, "/*", 2)) {
1844 comment = 1;
1845 goto again;
1846 }
1847 }
1848 }
1849 if (!comment && *s == '{') tempfile = 1;
1850 if (!comment) break;
1851 }
1852 macro.close();
1853
1854 if (!execute) {
1855 TString exname = exnam;
1856 if (!tempfile) {
1857 // We have a script that does NOT contain an unnamed macro,
1858 // so we can call the script compiler on it.
1859 exname += aclicMode;
1860 }
1861 exname += arguments;
1862 exname += io;
1864 TString tempbuf;
1865 if (tempfile) {
1866 tempbuf.Form(".x %s", exname.Data());
1867 } else {
1868 tempbuf.Form(".X%s %s", keep ? "k" : " ", exname.Data());
1869 }
1870 retval = gInterpreter->ProcessLineSynch(tempbuf,(TInterpreter::EErrorCode*)error);
1871 }
1872
1873 delete [] exnam;
1874 return retval;
1875}
1876
1877////////////////////////////////////////////////////////////////////////////////
1878/// Main application eventloop. Calls system dependent eventloop via gSystem.
1879
1880void TApplication::Run(Bool_t retrn)
1881{
1882 SetReturnFromRun(retrn);
1883
1884 fIsRunning = kTRUE;
1886 gSystem->Run();
1888}
1889
1890////////////////////////////////////////////////////////////////////////////////
1891/// Set the command to be executed after the system has been idle for
1892/// idleTimeInSec seconds. Normally called via TROOT::Idle(...).
1893
1894void TApplication::SetIdleTimer(UInt_t idleTimeInSec, const char *command)
1895{
1897 fIdleCommand = command;
1898 fIdleTimer = new TIdleTimer(idleTimeInSec*1000);
1900}
1901
1902////////////////////////////////////////////////////////////////////////////////
1903/// Remove idle timer. Normally called via TROOT::Idle(0).
1904
1907 if (fIdleTimer) {
1908 // timers are removed from the gSystem timer list by their dtor
1910 }
1911}
1912
1913////////////////////////////////////////////////////////////////////////////////
1914/// Called when system starts idleing.
1915
1917{
1918 if (fIdleTimer) {
1919 fIdleTimer->Reset();
1921 }
1922}
1923
1924////////////////////////////////////////////////////////////////////////////////
1925/// Called when system stops idleing.
1926
1928{
1929 if (fIdleTimer)
1931}
1932
1933////////////////////////////////////////////////////////////////////////////////
1934/// What to do when tab is pressed. Re-implemented by TRint.
1935/// See TTabCom::Hook() for meaning of return values.
1936
1937Int_t TApplication::TabCompletionHook(char* /*buf*/, int* /*pLoc*/, std::ostream& /*out*/)
1939 return -1;
1940}
1941
1942
1943////////////////////////////////////////////////////////////////////////////////
1944/// Terminate the application by call TSystem::Exit() unless application has
1945/// been told to return from Run(), by a call to SetReturnFromRun().
1947void TApplication::Terminate(Int_t status)
1948{
1949 Emit("Terminate(Int_t)", status);
1950
1951 if (fReturnFromRun)
1952 gSystem->ExitLoop();
1953 else {
1954 gSystem->Exit(status);
1955 }
1956}
1958////////////////////////////////////////////////////////////////////////////////
1959/// Emit signal when a line has been processed.
1960
1961void TApplication::LineProcessed(const char *line)
1962{
1963 Emit("LineProcessed(const char*)", line);
1965
1966////////////////////////////////////////////////////////////////////////////////
1967/// Emit signal when console keyboard key was pressed.
1968
1970{
1971 Emit("KeyPressed(Int_t)", key);
1972}
1973
1974////////////////////////////////////////////////////////////////////////////////
1975/// Emit signal when return key was pressed.
1976
1978{
1979 Emit("ReturnPressed(char*)", text);
1980}
1981
1982////////////////////////////////////////////////////////////////////////////////
1983/// Set console echo mode:
1984///
1985/// - mode = kTRUE - echo input symbols
1986/// - mode = kFALSE - noecho input symbols
1987
1989{
1990}
1991
1992////////////////////////////////////////////////////////////////////////////////
1993/// Static function used to create a default application environment.
1994
1996{
1998 // gApplication is set at the end of 'new TApplication.
1999 if (!gApplication) {
2000 char *a = StrDup("RootApp");
2001 char *b = StrDup("-b");
2002 char *argv[2];
2003 Int_t argc = 2;
2004 argv[0] = a;
2005 argv[1] = b;
2006 new TApplication("RootApp", &argc, argv, nullptr, 0);
2007 if (gDebug > 0)
2008 Printf("<TApplication::CreateApplication>: "
2009 "created default TApplication");
2010 delete [] a; delete [] b;
2012 }
2013}
2014
2015////////////////////////////////////////////////////////////////////////////////
2016/// Static function used to attach to an existing remote application
2017/// or to start one.
2018
2019TApplication *TApplication::Open(const char *url,
2020 Int_t debug, const char *script)
2021{
2022 TApplication *ap = nullptr;
2023 TUrl nu(url);
2024 Int_t nnew = 0;
2025
2026 // Look among the existing ones
2027 if (fgApplications) {
2028 TIter nxa(fgApplications);
2029 while ((ap = (TApplication *) nxa())) {
2030 TString apn(ap->ApplicationName());
2031 if (apn == url) {
2032 // Found matching application
2033 return ap;
2034 } else {
2035 // Check if same machine and user
2036 TUrl au(apn);
2037 if (strlen(au.GetUser()) > 0 && strlen(nu.GetUser()) > 0 &&
2038 !strcmp(au.GetUser(), nu.GetUser())) {
2039 if (!strncmp(au.GetHost(), nu.GetHost(), strlen(nu.GetHost())))
2040 // New session on a known machine
2041 nnew++;
2042 }
2043 }
2044 }
2045 } else {
2046 ::Error("TApplication::Open", "list of applications undefined - protocol error");
2047 return ap;
2048 }
2049
2050 // If new session on a known machine pass the number as option
2051 if (nnew > 0) {
2052 nnew++;
2053 nu.SetOptions(TString::Format("%d", nnew).Data());
2054 }
2055
2056 // Instantiate the TApplication object to be run
2057 TPluginHandler *h = nullptr;
2058 if ((h = gROOT->GetPluginManager()->FindHandler("TApplication","remote"))) {
2059 if (h->LoadPlugin() == 0) {
2060 ap = (TApplication *) h->ExecPlugin(3, nu.GetUrl(), debug, script);
2061 } else {
2062 ::Error("TApplication::Open", "failed to load plugin for TApplicationRemote");
2063 }
2064 } else {
2065 ::Error("TApplication::Open", "failed to find plugin for TApplicationRemote");
2066 }
2067
2068 // Add to the list
2069 if (ap && !(ap->TestBit(kInvalidObject))) {
2070 fgApplications->Add(ap);
2071 gROOT->GetListOfBrowsables()->Add(ap, ap->ApplicationName());
2072 TIter next(gROOT->GetListOfBrowsers());
2073 TBrowser *b;
2074 while ((b = (TBrowser*) next()))
2075 b->Add(ap, ap->ApplicationName());
2076 gROOT->RefreshBrowsers();
2077 } else {
2078 SafeDelete(ap);
2079 ::Error("TApplication::Open",
2080 "TApplicationRemote for %s could not be instantiated", url);
2081 }
2082
2083 // Done
2084 return ap;
2085}
2086
2087////////////////////////////////////////////////////////////////////////////////
2088/// Static function used to close a remote application
2089
2091{
2092 if (app) {
2093 app->Terminate(0);
2094 fgApplications->Remove(app);
2095 gROOT->GetListOfBrowsables()->RecursiveRemove(app);
2096 TIter next(gROOT->GetListOfBrowsers());
2097 TBrowser *b;
2098 while ((b = (TBrowser*) next()))
2099 b->RecursiveRemove(app);
2100 gROOT->RefreshBrowsers();
2101 }
2102}
2103
2104////////////////////////////////////////////////////////////////////////////////
2105/// Show available sessions
2106
2107void TApplication::ls(Option_t *opt) const
2108{
2109 if (fgApplications) {
2110 TIter nxa(fgApplications);
2111 TApplication *a = nullptr;
2112 while ((a = (TApplication *) nxa())) {
2113 a->Print(opt);
2114 }
2115 } else {
2116 Print(opt);
2117 }
2118}
2119
2120////////////////////////////////////////////////////////////////////////////////
2121/// Static method returning the list of available applications
2122
2124{
2125 return fgApplications;
2126}
#define SafeDelete(p)
Definition RConfig.hxx:517
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
long Longptr_t
Definition RtypesCore.h:82
int Ssiz_t
Definition RtypesCore.h:67
long Long_t
Definition RtypesCore.h:54
unsigned int UInt_t
Definition RtypesCore.h:46
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
static void CallEndOfProcessCleanups()
#define FOOTNOTE
TApplication * gApplication
R__EXTERN TApplication * gApplication
R__EXTERN TClassTable * gClassTable
@ kIsInlined
@ kIsConstexpr
Definition TDictionary.h:93
@ kIsStruct
Definition TDictionary.h:66
@ kIsVirtual
Definition TDictionary.h:72
@ kIsNamespace
Definition TDictionary.h:95
#define gDirectory
Definition TDirectory.h:384
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
R__EXTERN ExceptionContext_t * gException
Definition TException.h:69
R__EXTERN void Throw(int code)
If an exception context has been set (using the TRY and RETRY macros) jump back to where it was set.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint const char text
char name[80]
Definition TGX11.cxx:110
R__EXTERN TGuiFactory * gBatchGuiFactory
Definition TGuiFactory.h:67
R__EXTERN TGuiFactory * gGuiFactory
Definition TGuiFactory.h:66
R__EXTERN TVirtualMutex * gInterpreterMutex
#define gInterpreter
@ kInvalidObject
Definition TObject.h:374
Int_t gDebug
Definition TROOT.cxx:597
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:407
char * Compress(const char *str)
Remove all blanks from the string str.
Definition TString.cxx:2572
char * Strip(const char *str, char c=' ')
Strip leading and trailing c (blanks by default) from a string.
Definition TString.cxx:2521
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2557
R__EXTERN TStyle * gStyle
Definition TStyle.h:436
@ kReadPermission
Definition TSystem.h:45
R__EXTERN TSystem * gSystem
Definition TSystem.h:555
#define R__LOCKGUARD(mutex)
#define gPad
#define gVirtualX
Definition TVirtualX.h:337
R__EXTERN TVirtualX * gGXBatch
Definition TVirtualX.h:339
This class creates the ROOT Application Environment that interfaces to the windowing system eventloop...
EExitOnException ExitOnException(EExitOnException opt=kExit)
Set the exit on exception option.
virtual void KeyPressed(Int_t key)
Emit signal when console keyboard key was pressed.
virtual Longptr_t ProcessLine(const char *line, Bool_t sync=kFALSE, Int_t *error=nullptr)
Process a single command line, either a C++ statement or an interpreter command starting with a "....
static TList * fgApplications
static void Close(TApplication *app)
Static function used to close a remote application.
virtual void SetEchoMode(Bool_t mode)
Set console echo mode:
virtual void Help(const char *line)
The function lists useful commands (".help") or opens the online reference guide, generated with Doxy...
virtual void LineProcessed(const char *line)
Emit signal when a line has been processed.
void ClearInputFiles()
Clear list containing macro files passed as program arguments.
TApplicationImp * fAppImp
static Longptr_t ExecuteFile(const char *file, Int_t *error=nullptr, Bool_t keep=kFALSE)
Execute a file containing a C++ macro (static method).
void InitializeGraphics(Bool_t only_web=kFALSE)
Initialize the graphics environment.
virtual void Open()
virtual void LoadGraphicsLibs()
Load shared libs necessary for graphics.
virtual void StopIdleing()
Called when system stops idleing.
virtual void StartIdleing()
Called when system starts idleing.
virtual void Run(Bool_t retrn=kFALSE)
Main application eventloop. Calls system dependent eventloop via gSystem.
virtual ~TApplication()
TApplication dtor.
void OpenReferenceGuideFor(const TString &strippedClass)
It opens the online reference guide, generated with Doxygen, for the chosen scope (class/namespace/st...
virtual void HandleException(Int_t sig)
Handle exceptions (kSigBus, kSigSegmentationViolation, kSigIllegalInstruction and kSigFloatingExcepti...
virtual void MakeBatch()
Switch to batch mode.
void OpenGitHubIssue(const TString &type)
It opens a GitHub issue in a web browser with prefilled ROOT version.
Bool_t fReturnFromRun
virtual void Init()
TString fIdleCommand
char ** Argv() const
static Bool_t fgGraphNeeded
virtual void Terminate(Int_t status=0)
Terminate the application by call TSystem::Exit() unless application has been told to return from Run...
void OpenInBrowser(const TString &url)
The function generates and executes a command that loads the Doxygen URL in a browser.
virtual const char * ApplicationName() const
virtual void Forum(const char *line)
The function (".forum <type>") submits a new post on the ROOT forum via web browser.
void SetReturnFromRun(Bool_t ret)
virtual Int_t TabCompletionHook(char *buf, int *pLoc, std::ostream &out)
What to do when tab is pressed.
EExitOnException fExitOnException
TObjArray * fFiles
const char * GetIdleCommand() const
TApplication()
Default ctor. Can be used by classes deriving from TApplication.
virtual Longptr_t ProcessFile(const char *file, Int_t *error=nullptr, Bool_t keep=kFALSE)
Process a file containing a C++ macro.
void OpenForumTopic(const TString &type)
It opens a Forum topic in a web browser with prefilled ROOT version.
TString fWorkDir
virtual void ReturnPressed(char *text)
Emit signal when return key was pressed.
static Bool_t fgGraphInit
virtual void RemoveIdleTimer()
Remove idle timer. Normally called via TROOT::Idle(0).
virtual void SetIdleTimer(UInt_t idleTimeInSec, const char *command)
Set the command to be executed after the system has been idle for idleTimeInSec seconds.
virtual void GitHub(const char *line)
The function (".gh <type>") submits a new issue on GitHub via web browser.
static void CreateApplication()
Static function used to create a default application environment.
virtual void GetOptions(Int_t *argc, char **argv)
Get and handle command line options.
static TList * GetApplications()
Static method returning the list of available applications.
std::atomic< bool > fIsRunning
Window system specific application implementation.
static void NeedGraphicsLibs()
Static method.
static Int_t ParseRemoteLine(const char *ln, TString &hostdir, TString &user, Int_t &dbg, TString &script)
Parse the content of a line starting with ".R" (already stripped-off) The format is.
TTimer * fIdleTimer
void ls(Option_t *option="") const override
Show available sessions.
TString GetSetup()
It gets the ROOT installation setup as TString.
virtual void HandleIdleTimer()
Handle idle timeout.
virtual Longptr_t ProcessRemote(const char *line, Int_t *error=nullptr)
Process the content of a line starting with ".R" (already stripped-off) The format is.
TApplication * fAppRemote
char ** fArgv
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
void RecursiveRemove(TObject *obj) override
Recursively remove obj from browser.
Definition TBrowser.cxx:408
void Add(TObject *obj, const char *name=nullptr, Int_t check=-1)
Add object with name to browser.
Definition TBrowser.cxx:303
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
TList * GetListOfAllPublicDataMembers(Bool_t load=kTRUE)
Returns a list of all public data members of this class and its base classes.
Definition TClass.cxx:3862
TList * GetListOfEnums(Bool_t load=kTRUE)
Return a list containing the TEnums of a class.
Definition TClass.cxx:3686
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition TClass.cxx:6086
TMethod * GetMethodAllAny(const char *method)
Return pointer to method without looking at parameters.
Definition TClass.cxx:4384
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2968
static void InitializeColors()
Initialize colors used by the TCanvas based graphics (via TColor objects).
Definition TColor.cxx:1148
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
const char * GetTrueTypeName() const
Get the desugared type name of this data member, including const and volatile qualifiers.
Bool_t IsEnum() const
Return true if data member is an enum.
const char * GetFullTypeName() const
Get the concrete type name of this data member, including const and volatile qualifiers.
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
Global functions class (global functions are obtained from CINT).
Definition TFunction.h:30
Long_t Property() const override
Get property description word. For meaning of bits see EProperty.
const char * GetSignature()
Return signature of function.
Long_t ExtraProperty() const
Get property description word. For meaning of bits see EProperty.
const char * GetReturnTypeName() const
Get full type description of function return type, e,g.: "class TDirectory*".
This ABC is a factory for GUI components.
Definition TGuiFactory.h:42
virtual TApplicationImp * CreateApplicationImp(const char *classname, int *argc, char **argv)
Create a batch version of TApplicationImp.
TIdleTimer(Long_t ms)
Bool_t Notify() override
Notify handler.
void ls(Option_t *option="") const override
List this line with its attributes.
Definition TLine.cxx:380
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:83
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:820
virtual TObjLink * FirstLink() const
Definition TList.h:104
Each ROOT class (see TClass) has a linked list of methods.
Definition TMethod.h:38
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
An array of TObjects.
Definition TObjArray.h:31
Int_t GetEntries() const override
Return the number of objects in array (i.e.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
void Add(TObject *obj) override
Definition TObjArray.h:68
Collectable string class.
Definition TObjString.h:28
TString & String()
Definition TObjString.h:48
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:438
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Definition TObject.cxx:659
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1015
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition TObject.cxx:636
void ResetBit(UInt_t f)
Definition TObject.h:198
@ kInvalidObject
if object ctor succeeded but object should not be used
Definition TObject.h:72
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:961
void Emit(const char *signal, const T &arg)
Activate signal with single parameter.
Definition TQObject.h:164
static const char * GetMacroPath()
Get macro search path. Static utility function.
Definition TROOT.cxx:2762
static void ShutDown()
Shut down ROOT.
Definition TROOT.cxx:3122
static const TString & GetTTFFontDir()
Get the fonts directory in the installation. Static utility function.
Definition TROOT.cxx:3175
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition TROOT.cxx:2892
static const TString & GetTutorialDir()
Get the tutorials directory in the installation. Static utility function.
Definition TROOT.cxx:3101
static const TString & GetDocDir()
Get the documentation directory in the installation. Static utility function.
Definition TROOT.cxx:3064
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
void ToLower()
Change string to lower-case.
Definition TString.cxx:1182
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:661
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:1988
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2244
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:694
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:538
const char * Data() const
Definition TString.h:376
TString & Chop()
Definition TString.h:691
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
TString MD5() const
Return the MD5 digest for this string, in a string representation.
Definition TString.cxx:940
@ kBoth
Definition TString.h:276
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
TString & Prepend(const char *cs)
Definition TString.h:673
Bool_t IsNull() const
Definition TString.h:414
std::istream & ReadFile(std::istream &str)
Replace string with the contents of strm, stopping at an EOF.
Definition Stringio.cxx:29
TString & Remove(Ssiz_t pos)
Definition TString.h:685
TString & Append(const char *cs)
Definition TString.h:572
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2378
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2356
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:632
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
void SetScreenFactor(Float_t factor=1)
Definition TStyle.h:317
virtual void NotifyApplicationCreated()
Hook to tell TSystem that the TApplication object has been created.
Definition TSystem.cxx:311
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1274
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1665
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition TSystem.cxx:4258
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:653
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition TSystem.cxx:1398
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:1296
virtual void Run()
System event loop.
Definition TSystem.cxx:343
virtual void ExitLoop()
Exit from event loop.
Definition TSystem.cxx:392
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition TSystem.cxx:862
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition TSystem.cxx:471
virtual const char * GetBuildCompilerVersionStr() const
Return the build compiler version identifier string.
Definition TSystem.cxx:3899
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition TSystem.cxx:716
virtual const char * WorkingDirectory()
Return working directory.
Definition TSystem.cxx:871
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1548
virtual void SetProgname(const char *name)
Set the application name (from command line, argv[0]) and copy it in gProgName.
Definition TSystem.cxx:226
virtual const char * GetBuildArch() const
Return the build architecture.
Definition TSystem.cxx:3875
virtual void Abort(int code=0)
Abort the application.
Definition TSystem.cxx:725
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition TSystem.cxx:481
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
void Reset()
Reset the timer.
Definition TTimer.cxx:159
This class represents a WWW compatible URL.
Definition TUrl.h:33
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition TUrl.cxx:390
const char * GetFileAndOptions() const
Return the file and its options (the string specified behind the ?).
Definition TUrl.cxx:504
const char * GetFile() const
Definition TUrl.h:69
const char * GetProtocol() const
Definition TUrl.h:64
Semi-Abstract base class defining a generic interface to the underlying, low level,...
Definition TVirtualX.h:46
TLine * line
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
void EnableImplicitMT(UInt_t numthreads=0)
Enable ROOT's implicit multi-threading for all objects and methods that provide an internal paralleli...
Definition TROOT.cxx:539
void EnableThreadSafety()
Enable support for multi-threading within the ROOT code in particular, enables the global mutex to ma...
Definition TROOT.cxx:501
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.