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], "-b")) {
379 MakeBatch();
380 argv[i] = null;
381 } else if (!strcmp(argv[i], "-n")) {
382 fNoLog = kTRUE;
383 argv[i] = null;
384 } else if (!strcmp(argv[i], "-t")) {
386 // EnableImplicitMT() only enables thread safety if IMT was configured;
387 // enable thread safety even with IMT off:
389 argv[i] = null;
390 } else if (!strcmp(argv[i], "-q")) {
391 fQuit = kTRUE;
392 argv[i] = null;
393 } else if (!strcmp(argv[i], "-l")) {
394 // used by front-end program to not display splash screen
395 fNoLogo = kTRUE;
396 argv[i] = null;
397 } else if (!strcmp(argv[i], "-x")) {
399 argv[i] = null;
400 } else if (!strcmp(argv[i], "-splash")) {
401 // used when started by front-end program to signal that
402 // splash screen can be popped down (TRint::PrintLogo())
403 argv[i] = null;
404 } else if (strncmp(argv[i], "--web", 5) == 0) {
405 // the web mode is requested
406 const char *opt = argv[i] + 5;
407 argv[i] = null;
408 gROOT->SetWebDisplay((*opt == '=') ? opt + 1 : "");
409 } else if (!strcmp(argv[i], "-e")) {
410 argv[i] = null;
411 ++i;
412
413 if ( i < *argc ) {
414 if (!fFiles) fFiles = new TObjArray;
415 TObjString *expr = new TObjString(argv[i]);
416 expr->SetBit(kExpression);
417 fFiles->Add(expr);
418 argv[i] = null;
419 } else {
420 Warning("GetOptions", "-e must be followed by an expression.");
421 }
422 } else if (!strcmp(argv[i], "--")) {
423 TObjString* macro = nullptr;
424 bool warnShown = false;
425
426 if (fFiles) {
427 for (auto f: *fFiles) {
428 TObjString *file = dynamic_cast<TObjString *>(f);
429 if (!file) {
430 if (!dynamic_cast<TNamed*>(f)) {
431 Error("GetOptions()", "Inconsistent file entry (not a TObjString)!");
432 if (f)
433 f->Dump();
434 } // else we did not find the file.
435 continue;
436 }
437
438 if (file->TestBit(kExpression))
439 continue;
440 if (file->String().EndsWith(".root"))
441 continue;
442 if (file->String().Contains('('))
443 continue;
444
445 if (macro && !warnShown && (warnShown = true))
446 Warning("GetOptions", "-- is used with several macros. "
447 "The arguments will be passed to the last one.");
448
449 macro = file;
450 }
451 }
452
453 if (macro) {
454 argv[i] = null;
455 ++i;
456 TString& str = macro->String();
457
458 str += '(';
459 for (; i < *argc; i++) {
460 str += argv[i];
461 str += ',';
462 argv[i] = null;
463 }
464 str.EndsWith(",") ? str[str.Length() - 1] = ')' : str += ')';
465 } else {
466 Warning("GetOptions", "no macro to pass arguments to was provided. "
467 "Everything after the -- will be ignored.");
468 for (; i < *argc; i++)
469 argv[i] = null;
470 }
471 } else if (argv[i][0] != '-' && argv[i][0] != '+') {
473 Long_t id, flags, modtime;
474 char *arg = strchr(argv[i], '(');
475 if (arg) *arg = '\0';
476 char *dir = gSystem->ExpandPathName(argv[i]);
477 // ROOT-9959: we do not continue if we could not expand the path
478 if (!dir) continue;
479 TUrl udir(dir, kTRUE);
480 // remove options and anchor to check the path
481 TString sfx = udir.GetFileAndOptions();
482 TString fln = udir.GetFile();
483 sfx.Replace(sfx.Index(fln), fln.Length(), "");
484 TString path = udir.GetFile();
485 if (strcmp(udir.GetProtocol(), "file")) {
486 path = udir.GetUrl();
487 path.Replace(path.Index(sfx), sfx.Length(), "");
488 }
489 // 'path' is the full URL without suffices (options and/or anchor)
490 if (arg) *arg = '(';
491 if (!arg && !gSystem->GetPathInfo(path.Data(), &id, &size, &flags, &modtime)) {
492 if ((flags & 2)) {
493 // if directory set it in fWorkDir
494 if (pwd == "") {
495 pwd = gSystem->WorkingDirectory();
496 fWorkDir = dir;
498 argv[i] = null;
499 } else if (!strcmp(gROOT->GetName(), "Rint")) {
500 Warning("GetOptions", "only one directory argument can be specified (%s)", dir);
501 }
502 } else if (size > 0) {
503 // if file add to list of files to be processed
504 if (!fFiles) fFiles = new TObjArray;
505 fFiles->Add(new TObjString(path.Data()));
506 argv[i] = null;
507 } else {
508 Warning("GetOptions", "file %s has size 0, skipping", dir);
509 }
510 } else {
511 if (TString(udir.GetFile()).EndsWith(".root")) {
512 if (!strcmp(udir.GetProtocol(), "file")) {
513 // file ending on .root but does not exist, likely a typo
514 // warn user if plain root...
515 if (!strcmp(gROOT->GetName(), "Rint"))
516 Warning("GetOptions", "file %s not found", dir);
517 } else {
518 // remote file, give it the benefit of the doubt and add it to list of files
519 if (!fFiles) fFiles = new TObjArray;
520 fFiles->Add(new TObjString(argv[i]));
521 argv[i] = null;
522 }
523 } else {
524 TString mode,fargs,io;
525 TString fname = gSystem->SplitAclicMode(dir,mode,fargs,io);
526 char *mac;
527 if (!fFiles) fFiles = new TObjArray;
528 if ((mac = gSystem->Which(TROOT::GetMacroPath(), fname,
529 kReadPermission))) {
530 // if file add to list of files to be processed
531 fFiles->Add(new TObjString(argv[i]));
532 argv[i] = null;
533 delete [] mac;
534 } else {
535 // if file add an invalid entry to list of files to be processed
536 fFiles->Add(new TNamed("NOT FOUND!", argv[i]));
537 // only warn if we're plain root,
538 // other progs might have their own params
539 if (!strcmp(gROOT->GetName(), "Rint"))
540 Warning("GetOptions", "macro %s not found", fname.Data());
541 }
542 }
543 }
544 delete [] dir;
545 }
546 // ignore unknown options
547 }
548
549 // go back to startup directory
550 if (pwd != "")
552
553 // remove handled arguments from argument array
554 j = 0;
555 for (i = 0; i < *argc; i++) {
556 if (strcmp(argv[i], "")) {
557 argv[j] = argv[i];
558 j++;
559 }
560 }
561
562 *argc = j;
563}
564
565////////////////////////////////////////////////////////////////////////////////
566/// Handle idle timeout. When this timer expires the registered idle command
567/// will be executed by this routine and a signal will be emitted.
568
570{
571 if (!fIdleCommand.IsNull())
573
574 Emit("HandleIdleTimer()");
575}
576
577////////////////////////////////////////////////////////////////////////////////
578/// Handle exceptions (kSigBus, kSigSegmentationViolation,
579/// kSigIllegalInstruction and kSigFloatingException) trapped in TSystem.
580/// Specific TApplication implementations may want something different here.
581
583{
584 if (TROOT::Initialized()) {
585 if (gException) {
586 gInterpreter->RewindDictionary();
587 gInterpreter->ClearFileBusy();
588 }
589 if (fExitOnException == kExit)
590 gSystem->Exit(128 + sig);
591 else if (fExitOnException == kAbort)
592 gSystem->Abort();
593 else
594 Throw(sig);
595 }
596 gSystem->Exit(128 + sig);
597}
598
599////////////////////////////////////////////////////////////////////////////////
600/// Set the exit on exception option. Setting this option determines what
601/// happens in HandleException() in case an exception (kSigBus,
602/// kSigSegmentationViolation, kSigIllegalInstruction or kSigFloatingException)
603/// is trapped. Choices are: kDontExit (default), kExit or kAbort.
604/// Returns the previous value.
605
607{
609 fExitOnException = opt;
610 return old;
611}
612
613/////////////////////////////////////////////////////////////////////////////////
614/// The function generates and executes a command that loads the Doxygen URL in
615/// a browser. It works for Mac, Windows and Linux. In the case of Linux, the
616/// function also checks if the DISPLAY is set. If it isn't, a warning message
617/// and the URL will be displayed on the terminal.
618///
619/// \param[in] url web page to be displayed in a browser
620
622{
623 // We check what operating system the user has.
624#ifdef R__MACOSX
625 // Command for opening a browser on Mac.
626 TString cMac("open ");
627 // We generate the full command and execute it.
628 cMac.Append(url);
629 gSystem->Exec(cMac);
630#elif defined(R__WIN32)
631 // Command for opening a browser on Windows.
632 TString cWindows("start \"\" ");
633 cWindows.Append(url);
634 gSystem->Exec(cWindows);
635#else
636 // Command for opening a browser in Linux.
637 TString cLinux("xdg-open ");
638 // For Linux we check if the DISPLAY is set.
639 if (gSystem->Getenv("DISPLAY")) {
640 // If the DISPLAY is set it will open the browser.
641 cLinux.Append(url);
642 gSystem->Exec(cLinux);
643 } else {
644 // Else the user will have a warning and the URL in the terminal.
645 Warning("OpenInBrowser", "The $DISPLAY is not set! Please open (e.g. Ctrl-click) %s\n", url.Data());
646 return;
647 }
648#endif
649 Info("OpenInBrowser", "A new tab should have opened in your browser.");
650}
651
652namespace {
653enum EUrl { kURLforClass, kURLforNameSpace, kURLforStruct };
654////////////////////////////////////////////////////////////////////////////////
655/// The function generates a URL address for class or namespace (scopeName).
656/// This is the URL to the online reference guide, generated by Doxygen.
657/// With the enumeration "EUrl" we pick which case we need - the one for
658/// class (kURLforClass) or the one for namespace (kURLforNameSpace).
659///
660/// \param[in] scopeName the name of the class or the namespace
661/// \param[in] scopeType the enumerator for class or namespace
662
663static TString UrlGenerator(TString scopeName, EUrl scopeType)
664{
665 // We start the URL with a static part, the same for all scopes and members.
666 TString url = "https://root.cern/doc/";
667 // Then we check the ROOT version used.
668 TPRegexp re4(R"(.*/(v\d)-(\d\d)-00-patches)");
669 const char *branchName = gROOT->GetGitBranch();
670 TObjArray *objarr = re4.MatchS(branchName);
671 TString version;
672 // We extract the correct version name for the URL.
673 if (objarr && objarr->GetEntries() == 3) {
674 // We have a valid version of ROOT and we will extract the correct name for the URL.
675 version = ((TObjString *)objarr->At(1))->GetString() + ((TObjString *)objarr->At(2))->GetString();
676 } else {
677 // If it's not a supported version, we will go to "master" branch.
678 version = "master";
679 }
680 delete objarr;
681 url.Append(version);
682 url.Append("/");
683 // We will replace all "::" with "_1_1" and all "_" with "__" in the
684 // classes definitions, due to Doxygen syntax requirements.
685 scopeName.ReplaceAll("_", "__");
686 scopeName.ReplaceAll("::", "_1_1");
687 // We build the URL for the correct scope type and name.
688 if (scopeType == kURLforClass) {
689 url.Append("class");
690 } else if (scopeType == kURLforStruct) {
691 url.Append("struct");
692 } else {
693 url.Append("namespace");
694 }
695 url.Append(scopeName);
696 url.Append(".html");
697 return url;
698}
699} // namespace
700
701namespace {
702////////////////////////////////////////////////////////////////////////////////
703/// The function returns a TString with the arguments of a method from the
704/// scope (scopeName), but modified with respect to Doxygen syntax - spacing
705/// around special symbols and adding the missing scopes ("std::").
706/// "FormatMethodArgsForDoxygen" works for functions defined inside namespaces
707/// as well. We avoid looking up twice for the TFunction by passing "func".
708///
709/// \param[in] scopeName the name of the class/namespace/struct
710/// \param[in] func pointer to the method
711
712static TString FormatMethodArgsForDoxygen(const TString &scopeName, TFunction *func)
713{
714 // With "GetSignature" we get the arguments of the method and put them in a TString.
715 TString methodArguments = func->GetSignature();
716 // "methodArguments" is modified with respect of Doxygen requirements.
717 methodArguments.ReplaceAll(" = ", "=");
718 methodArguments.ReplaceAll("* ", " *");
719 methodArguments.ReplaceAll("*=", " *=");
720 methodArguments.ReplaceAll("*)", " *)");
721 methodArguments.ReplaceAll("*,", " *,");
722 methodArguments.ReplaceAll("*& ", " *&");
723 methodArguments.ReplaceAll("& ", " &");
724 // TODO: prepend "std::" to all stdlib classes!
725 methodArguments.ReplaceAll("ostream", "std::ostream");
726 methodArguments.ReplaceAll("istream", "std::istream");
727 methodArguments.ReplaceAll("map", "std::map");
728 methodArguments.ReplaceAll("vector", "std::vector");
729 // We need to replace the "currentClass::foo" with "foo" in the arguments.
730 // TODO: protect the global functions.
731 TString scopeNameRE("\\b");
732 scopeNameRE.Append(scopeName);
733 scopeNameRE.Append("::\\b");
734 TPRegexp argFix(scopeNameRE);
735 argFix.Substitute(methodArguments, "");
736 return methodArguments;
737}
738} // namespace
739
740namespace {
741////////////////////////////////////////////////////////////////////////////////
742/// The function returns a TString with the text as an encoded url so that it
743/// can be passed to the function OpenInBrowser
744///
745/// \param[in] text the input text
746/// \return the text appropriately escaped
747
748static TString FormatHttpUrl(TString text)
749{
750 text.ReplaceAll("\n","%0A");
751 text.ReplaceAll("#","%23");
752 text.ReplaceAll(";","%3B");
753 text.ReplaceAll("\"","%22");
754 text.ReplaceAll("`","%60");
755 text.ReplaceAll("+","%2B");
756 text.ReplaceAll("/","%2F");
757 return text;
758}
759} // namespace
760
761namespace {
762////////////////////////////////////////////////////////////////////////////////
763/// The function checks if a member function of a scope is defined as inline.
764/// If so, it also checks if it is virtual. Then the return type of "func" is
765/// modified for the need of Doxygen and with respect to the function
766/// definition. We pass pointer to the method (func) to not re-do the
767/// TFunction lookup.
768///
769/// \param[in] scopeName the name of the class/namespace/struct
770/// \param[in] func pointer to the method
771
772static TString FormatReturnTypeForDoxygen(const TString &scopeName, TFunction *func)
773{
774 // We put the return type of "func" in a TString "returnType".
775 TString returnType = func->GetReturnTypeName();
776 // If the return type is a type nested in the current class, it will appear scoped (Class::Enumeration).
777 // Below we make sure to remove the current class, because the syntax of Doxygen requires it.
778 TString scopeNameRE("\\b");
779 scopeNameRE.Append(scopeName);
780 scopeNameRE.Append("::\\b");
781 TPRegexp returnFix(scopeNameRE);
782 returnFix.Substitute(returnType, "");
783 // We check is if the method is defined as inline.
784 if (func->ExtraProperty() & kIsInlined) {
785 // We check if the function is defined as virtual.
786 if (func->Property() & kIsVirtual) {
787 // If the function is virtual, we append "virtual" before the return type.
788 returnType.Prepend("virtual ");
789 }
790 returnType.ReplaceAll(" *", "*");
791 } else {
792 // If the function is not inline we only change the spacing in "returnType"
793 returnType.ReplaceAll("*", " *");
794 }
795 // In any case (with no respect to virtual/inline check) we need to change
796 // the return type as following.
797 // TODO: prepend "std::" to all stdlib classes!
798 returnType.ReplaceAll("istream", "std::istream");
799 returnType.ReplaceAll("ostream", "std::ostream");
800 returnType.ReplaceAll("map", "std::map");
801 returnType.ReplaceAll("vector", "std::vector");
802 returnType.ReplaceAll("&", " &");
803 return returnType;
804}
805} // namespace
806
807namespace {
808////////////////////////////////////////////////////////////////////////////////
809/// The function generates a URL for "dataMemberName" defined in "scopeName".
810/// It returns a TString with the URL used in the online reference guide,
811/// generated with Doxygen. For data members the URL consist of 2 parts -
812/// URL for "scopeName" and a part for "dataMemberName".
813/// For enumerator, the URL could be separated into 3 parts - URL for
814/// "scopeName", part for the enumeration and a part for the enumerator.
815///
816/// \param[in] scopeName the name of the class/namespace/struct
817/// \param[in] dataMemberName the name of the data member/enumerator
818/// \param[in] dataMember pointer to the data member/enumerator
819/// \param[in] scopeType enumerator to the scope type
820
821static TString
822GetUrlForDataMember(const TString &scopeName, const TString &dataMemberName, TDataMember *dataMember, EUrl scopeType)
823{
824 // We first check if the data member is not enumerator.
825 if (!dataMember->IsEnum()) {
826 // If we work with data members, we have to append a hashed with MD5 text, consisting of:
827 // "Type ClassName::DataMemberNameDataMemberName(arguments)".
828 // We first get the type of the data member.
829 TString md5DataMember(dataMember->GetFullTypeName());
830 md5DataMember.Append(" ");
831 // We append the scopeName and "::".
832 md5DataMember.Append(scopeName);
833 md5DataMember.Append("::");
834 // We append the dataMemberName twice.
835 md5DataMember.Append(dataMemberName);
836 md5DataMember.Append(dataMemberName);
837 // We call UrlGenerator for the scopeName.
838 TString urlForDataMember = UrlGenerator(scopeName, scopeType);
839 // Then we append "#a" and the hashed text.
840 urlForDataMember.Append("#a");
841 urlForDataMember.Append(md5DataMember.MD5());
842 return urlForDataMember;
843 }
844 // If the data member is enumerator, then we first have to check if the enumeration is anonymous.
845 // Doxygen requires different syntax for anonymous enumeration ("scopeName::@1@1").
846 // We create a TString with the name of the scope and the enumeration from which the enumerator is.
847 TString scopeEnumeration = dataMember->GetTrueTypeName();
848 TString md5EnumClass;
849 if (scopeEnumeration.Contains("(unnamed)")) {
850 // FIXME: need to investigate the numbering scheme.
851 md5EnumClass.Append(scopeName);
852 md5EnumClass.Append("::@1@1");
853 } else {
854 // If the enumeration is not anonymous we put "scopeName::Enumeration" in a TString,
855 // which will be hashed with MD5 later.
856 md5EnumClass.Append(scopeEnumeration);
857 // We extract the part after "::" (this is the enumerator name).
858 TString enumOnlyName = TClassEdit::GetUnqualifiedName(scopeEnumeration);
859 // The syntax is "Class::EnumeratorEnumerator
860 md5EnumClass.Append(enumOnlyName);
861 }
862 // The next part of the URL is hashed "@ scopeName::EnumeratorEnumerator".
863 TString md5Enumerator("@ ");
864 md5Enumerator.Append(scopeName);
865 md5Enumerator.Append("::");
866 md5Enumerator.Append(dataMemberName);
867 md5Enumerator.Append(dataMemberName);
868 // We make the URL for the "scopeName".
869 TString url = UrlGenerator(scopeName, scopeType);
870 // Then we have to append the hashed text for the enumerator.
871 url.Append("#a");
872 url.Append(md5EnumClass.MD5());
873 // We append "a" and then the next hashed text.
874 url.Append("a");
875 url.Append(md5Enumerator.MD5());
876 return url;
877}
878} // namespace
879
880namespace {
881////////////////////////////////////////////////////////////////////////////////
882/// The function generates URL for enumeration. The hashed text consist of:
883/// "Class::EnumerationEnumeration".
884///
885/// \param[in] scopeName the name of the class/namespace/struct
886/// \param[in] enumeration the name of the enumeration
887/// \param[in] scopeType enumerator for class/namespace/struct
888
889static TString GetUrlForEnumeration(TString scopeName, const TString &enumeration, EUrl scopeType)
890{
891 // The URL consists of URL for the "scopeName", "#a" and hashed as MD5 text.
892 // The text is "Class::EnumerationEnumeration.
893 TString md5Enumeration(scopeName);
894 md5Enumeration.Append("::");
895 md5Enumeration.Append(enumeration);
896 md5Enumeration.Append(enumeration);
897 // We make the URL for the scope "scopeName".
898 TString url(UrlGenerator(scopeName, scopeType));
899 // Then we have to append "#a" and the hashed text.
900 url.Append("#a");
901 url.Append(md5Enumeration.MD5());
902 return url;
903}
904} // namespace
905
906namespace {
907enum EMethodKind { kURLforMethod, kURLforStructor };
908////////////////////////////////////////////////////////////////////////////////
909/// The function generates URL for any member function (including Constructor/
910/// Destructor) of "scopeName". Doxygen first generates the URL for the scope.
911/// We do that with the help of "UrlGenerator". Then we append "#a" and a
912/// hashed with MD5 text. It consists of:
913/// "ReturnType ScopeName::MethodNameMethodName(Method arguments)".
914/// For constructor/destructor of a class, the return type is not appended.
915///
916/// \param[in] scopeName the name of the class/namespace/struct
917/// \param[in] methodName the name of the method from the scope
918/// \param[in] func pointer to the method
919/// \param[in] methodType enumerator for method or constructor
920/// \param[in] scopeType enumerator for class/namespace/struct
921
922static TString GetUrlForMethod(const TString &scopeName, const TString &methodName, TFunction *func,
923 EMethodKind methodType, EUrl scopeType)
924{
925 TString md5Text;
926 if (methodType == kURLforMethod) {
927 // In the case of method, we append the return type too.
928 // "FormatReturnTypeForDoxygen" modifies the return type with respect to Doxygen's requirement.
929 md5Text.Append((FormatReturnTypeForDoxygen(scopeName, func)));
930 if (scopeType == kURLforNameSpace) {
931 // We need to append "constexpr" if we work with constexpr functions in namespaces.
932 if (func->Property() & kIsConstexpr) {
933 md5Text.Prepend("constexpr ");
934 }
935 }
936 md5Text.Append(" ");
937 }
938 // We append ScopeName::MethodNameMethodName.
939 md5Text.Append(scopeName);
940 md5Text.Append("::");
941 md5Text.Append(methodName);
942 md5Text.Append(methodName);
943 // We use "FormatMethodArgsForDoxygen" to modify the arguments of Method with respect of Doxygen.
944 md5Text.Append(FormatMethodArgsForDoxygen(scopeName, func));
945 // We generate the URL for the class/namespace/struct.
946 TString url = UrlGenerator(scopeName, scopeType);
947 url.Append("#a");
948 // We append the hashed text.
949 url.Append(md5Text.MD5());
950 return url;
951}
952} // namespace
953
954////////////////////////////////////////////////////////////////////////////////
955/// It gets the ROOT installation setup as TString
956///
957/// \return a string with several lines
958///
960{
961 std::vector<TString> lines;
962 lines.emplace_back("```");
963 lines.emplace_back(TString::Format("ROOT v%s",
964 gROOT->GetVersion()));
965 lines.emplace_back(TString::Format("Built for %s on %s", gSystem->GetBuildArch(), gROOT->GetGitDate()));
966 if (!strcmp(gROOT->GetGitBranch(), gROOT->GetGitCommit())) {
967 static const char *months[] = {"January","February","March","April","May",
968 "June","July","August","September","October",
969 "November","December"};
970 Int_t idatqq = gROOT->GetVersionDate();
971 Int_t iday = idatqq%100;
972 Int_t imonth = (idatqq/100)%100;
973 Int_t iyear = (idatqq/10000);
974
975 lines.emplace_back(TString::Format("From tag %s, %d %s %4d",
976 gROOT->GetGitBranch(),
977 iday,months[imonth-1],iyear));
978 } else {
979 // If branch and commit are identical - e.g. "v5-34-18" - then we have
980 // a release build. Else specify the git hash this build was made from.
981 lines.emplace_back(TString::Format("From %s@%s",
982 gROOT->GetGitBranch(),
983 gROOT->GetGitCommit()));
984 }
985 lines.emplace_back(TString::Format("With %s",
987 lines.emplace_back("Binary directory: "+ gROOT->GetBinDir());
988 lines.emplace_back("```");
989 TString setup = "";
990 for (auto& line : lines) {
991 setup.Append(line);
992 setup.Append('\n');
993 }
994 setup.Chop(); // trim final `\n`
995 return setup;
996}
997
998////////////////////////////////////////////////////////////////////////////////
999/// It opens a Forum topic in a web browser with prefilled ROOT version
1000///
1001/// \param[in] type the issue type (only bug supported right now)
1002
1004{
1005 // https://meta.discourse.org/t/how-to-create-a-post-clicking-a-link/96197
1006
1007 if (type == "bug") {
1008 //OpenInBrowser("\"https://root-forum.cern.ch/new-topic?title=topic%20title&body=topic%20body&category=category/subcategory&tags=email,planned\"");
1009 TString report_template =
1010R"(___
1011_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)_
1012
1013### Describe the bug
1014<!--
1015A clear and concise description of what the wrong behavior is.
1016-->
1017### Expected behavior
1018<!--
1019A clear and concise description of what you expected to happen.
1020-->
1021
1022### To Reproduce
1023<!--
1024Steps to reproduce the behavior:
10251. Your code that triggers the issue: at least a part; ideally something we can run ourselves.
10262. Don't forget to attach the required input files!
10273. How to run your code and / or build it, e.g. `root myMacro.C`, ...
1028-->
1029
1030### Setup
1031```
1032)"+GetSetup()+
1033R"(```
1034
1035<!--
1036Please specify also how you obtained ROOT, such as `dnf install` / binary download / you built it yourself.
1037-->
1038
1039### Additional context
1040<!--
1041Add any other context about the problem here.
1042-->)";
1043 report_template = FormatHttpUrl(report_template);
1044
1045 OpenInBrowser("\"https://root-forum.cern.ch/new-topic?category=ROOT&tags=bug&body="+report_template+"&\"");
1046 } else {
1047 Warning("OpenForumTopic", "cannot find \"%s\" as type for a Forum topic\n"
1048 "Available types are 'bug'.", type.Data());
1049 }
1050}
1051
1052////////////////////////////////////////////////////////////////////////////////
1053/// It opens a GitHub issue in a web browser with prefilled ROOT version
1054///
1055/// \param[in] type the issue type (bug, feature or improvement)
1056
1058{
1059 // https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue#creating-an-issue-from-a-url-query
1060
1061 if (type == "bug") {
1063 "\"https://github.com/root-project/root/issues/new?labels=bug&template=bug_report.yml&root-version=" +
1064 FormatHttpUrl(GetSetup()) + "\"");
1065 } else if (type == "improvement") {
1066 OpenInBrowser("\"https://github.com/root-project/root/issues/"
1067 "new?labels=improvement&template=improvement_report.yml&root-version=" +
1068 FormatHttpUrl(GetSetup()) + "\"");
1069 } else if (type == "feature") {
1071 "\"https://github.com/root-project/root/issues/new?labels=new+feature&template=feature_request.yml\"");
1072 } else {
1073 Warning("OpenGitHubIssue",
1074 "Cannot find GitHub issue type \"%s\".\n"
1075 "Available types are 'bug', 'feature' and 'improvement'.",
1076 type.Data());
1077 }
1078}
1079
1080////////////////////////////////////////////////////////////////////////////////
1081/// It opens the online reference guide, generated with Doxygen, for the
1082/// chosen scope (class/namespace/struct) or member (method/function/
1083/// data member/enumeration/enumerator. If the user types incorrect value,
1084/// it will return an error or warning.
1085///
1086/// \param[in] strippedClass the scope or scope::member
1087
1088void TApplication::OpenReferenceGuideFor(const TString &strippedClass)
1089{
1090 // We check if the user is searching for a scope and if the scope exists.
1091 if (TClass *clas = TClass::GetClass(strippedClass)) {
1092 // We check what scope he is searching for (class/namespace/struct).
1093 // Enumerators will switch between the possible cases.
1094 EUrl scopeType;
1095 if (clas->Property() & kIsNamespace) {
1096 scopeType = kURLforNameSpace;
1097 } else if (clas->Property() & kIsStruct) {
1098 scopeType = kURLforStruct;
1099 } else {
1100 scopeType = kURLforClass;
1101 }
1102 // If the user search directly for a scope we open the URL for him with OpenInBrowser.
1103 OpenInBrowser(UrlGenerator(strippedClass, scopeType));
1104 return;
1105 }
1106 // Else we subtract the name of the method and remove it from the command.
1107 TString memberName = TClassEdit::GetUnqualifiedName(strippedClass);
1108 // Error out if "strippedClass" is un-scoped (and it's not a class, see `TClass::GetClass(strippedClass)` above).
1109 // TODO: Global functions.
1110 if (strippedClass == memberName) {
1111 Error("OpenReferenceGuideFor", "Unknown entity \"%s\" - global variables / functions not supported yet!",
1112 strippedClass.Data());
1113 return;
1114 }
1115 // Else we remove the member name to be left with the scope.
1116 TString scopeName = strippedClass(0, strippedClass.Length() - memberName.Length() - 2);
1117 // We check if the scope exists in ROOT.
1118 TClass *cl = TClass::GetClass(scopeName);
1119 if (!cl) {
1120 // That's a member of something ROOT doesn't know.
1121 Warning("OpenReferenceGuideFor", "\"%s\" does not exist in ROOT!", scopeName.Data());
1122 return;
1123 }
1124 // We have enumerators for the three available cases - class, namespace and struct.
1125 EUrl scopeType;
1126 if (cl->Property() & kIsNamespace) {
1127 scopeType = kURLforNameSpace;
1128 } else if (cl->Property() & kIsStruct) {
1129 scopeType = kURLforStruct;
1130 } else {
1131 scopeType = kURLforClass;
1132 }
1133 // If the user wants to search for a method, we take its name (memberName) and
1134 // modify it - we delete everything starting at the first "(" so the user won't have to
1135 // do it by hand when they use Tab.
1136 int bracket = memberName.First("(");
1137 if (bracket > 0) {
1138 memberName.Remove(bracket);
1139 }
1140 // We check if "memberName" is a member function of "cl" or any of its base classes.
1141 if (TFunction *func = cl->GetMethodAllAny(memberName)) {
1142 // If so we find the name of the class that it belongs to.
1143 TString baseClName = ((TMethod *)func)->GetClass()->GetName();
1144 // We define an enumerator to distinguish between structor and method.
1145 EMethodKind methodType;
1146 // We check if "memberName" is a constructor.
1147 if (baseClName == memberName) {
1148 methodType = kURLforStructor;
1149 // We check if "memberName" is a destructor.
1150 } else if (memberName[0] == '~') {
1151 methodType = kURLforStructor;
1152 // We check if "memberName" is a method.
1153 } else {
1154 methodType = kURLforMethod;
1155 }
1156 // We call "GetUrlForMethod" for the correct class and scope.
1157 OpenInBrowser(GetUrlForMethod(baseClName, memberName, func, methodType, scopeType));
1158 return;
1159 }
1160 // We check if "memberName" is an enumeration.
1161 if (cl->GetListOfEnums()->FindObject(memberName)) {
1162 // If so with OpenInBrowser we open the URL generated with GetUrlForEnumeration
1163 // with respect to the "scopeType".
1164 OpenInBrowser(GetUrlForEnumeration(scopeName, memberName, scopeType));
1165 return;
1166 }
1167
1168 // We check if "memberName" is enumerator defined in one the base classes of "scopeName".
1169 if (auto enumerator = (TDataMember *)cl->GetListOfAllPublicDataMembers()->FindObject(memberName)) {
1170 // We find the actual scope (might be in a base) and open the URL in a browser.
1171 TString baseClName = ((TMethod *)enumerator->GetClass())->GetName();
1172 OpenInBrowser(GetUrlForDataMember(baseClName, memberName, enumerator, scopeType));
1173 return;
1174 }
1175
1176 // Warning message will appear if the user types the function name incorrectly
1177 // or the function is not a member function of "cl" or any of its base classes.
1178 Warning("OpenReferenceGuideFor", "cannot find \"%s\" as member of %s or its base classes! Check %s\n", memberName.Data(),
1179 scopeName.Data(), UrlGenerator(scopeName, scopeType).Data());
1180}
1181
1182////////////////////////////////////////////////////////////////////////////////
1183/// The function (".forum <type>") submits a new post on the ROOT forum
1184/// via web browser.
1185/// \note You can use "bug" as <type>.
1186/// \param[in] line command from the command line
1187
1188void TApplication::Forum(const char *line)
1189{
1190 // We first check if the user chose a correct syntax.
1191 TString strippedCommand = TString(line).Strip(TString::kBoth);
1192 if (!strippedCommand.BeginsWith(".forum ")) {
1193 Error("Forum", "Unknown command! Use 'bug' after '.forum '");
1194 return;
1195 }
1196 // We remove the command ".forum" from the TString.
1197 strippedCommand.Remove(0, 7);
1198 // We strip the command line after removing ".help" or ".?".
1199 strippedCommand = strippedCommand.Strip(TString::kBoth);
1201 OpenForumTopic(strippedCommand);
1202}
1203
1204////////////////////////////////////////////////////////////////////////////////
1205/// The function (".gh <type>") submits a new issue on GitHub via web browser.
1206/// \note You can use "bug", "feature" or "improvement" as <type>.
1207/// \param[in] line command from the command line
1208
1209void TApplication::GitHub(const char *line)
1210{
1211 // We first check if the user chose a correct syntax.
1212 TString strippedCommand = TString(line).Strip(TString::kBoth);
1213 if (!strippedCommand.BeginsWith(".gh ")) {
1214 Error("GitHub", "Unknown command! Use 'bug', 'feature' or 'improvement' after '.gh '");
1215 return;
1216 }
1217 // We remove the command ".gh" from the TString.
1218 strippedCommand.Remove(0, 4);
1219 // We strip the command line after removing ".help" or ".?".
1220 strippedCommand = strippedCommand.Strip(TString::kBoth);
1221
1222 OpenGitHubIssue(strippedCommand);
1223}
1224
1225////////////////////////////////////////////////////////////////////////////////
1226/// The function lists useful commands (".help") or opens the online reference
1227/// guide, generated with Doxygen (".help scope" or ".help scope::member").
1228/// \note You can use ".?" as the short version of ".help"
1229/// \param[in] line command from the command line
1230
1231void TApplication::Help(const char *line)
1232{
1233 // We first check if the user wants to print the help on the interpreter.
1234 TString strippedCommand = TString(line).Strip(TString::kBoth);
1235 // If the user chooses ".help" or ".?".
1236 if ((strippedCommand == ".help") || (strippedCommand == ".?")) {
1237 gInterpreter->ProcessLine(line);
1238 Printf("\n ROOT special commands.");
1239 Printf(" ==============================================================================");
1240 Printf(" .L <filename>[flags]: load the given file with optional flags like\n"
1241 " + to compile or ++ to force recompile.\n"
1242 " Type .? TSystem::CompileMacro for a list of all flags.");
1243 Printf(" .(x|X) <filename>[flags](args) :\n"
1244 " same as .L <filename>[flags] and runs then a function\n"
1245 " with signature: ret_type filename(args).");
1246 Printf(" .credits : show credits");
1247 Printf(" .demo : launch GUI demo");
1248 Printf(" .forum bug : ask for help with a bug or crash at the ROOT forum.");
1249 Printf(" .gh [bug|feature|improvement]\n"
1250 " : submit a bug report, feature or improvement suggestion");
1251 Printf(" .help Class::Member : open reference guide for that class member (or .?).\n"
1252 " Specifying '::Member' is optional.");
1253 Printf(" .help edit : show line editing shortcuts (or .?)");
1254 Printf(" .license : show license");
1255 Printf(" .ls : list contents of current TDirectory");
1256 Printf(" .pwd : show current TDirectory, pad and style");
1257 Printf(" .quit (or .exit) : quit ROOT (long form of .q)");
1258 Printf(" .R [user@]host[:dir] [-l user] [-d dbg] [script] :\n"
1259 " launch process in a remote host");
1260 Printf(" .qqq : quit ROOT - mandatory");
1261 Printf(" .qqqqq : exit process immediately");
1262 Printf(" .qqqqqqq : abort process");
1263 Printf(" .which [file] : show path of macro file");
1264 Printf(" .![OS_command] : execute OS-specific shell command");
1265 Printf(" .!root -? : print ROOT usage (CLI options)");
1266 return;
1267 } else {
1268 // If the user wants to use the extended ".help scopeName" command to access
1269 // the online reference guide, we first check if the command starts correctly.
1270 if ((!strippedCommand.BeginsWith(".help ")) && (!strippedCommand.BeginsWith(".? "))) {
1271 Error("Help", "Unknown command!");
1272 return;
1273 }
1274 // We remove the command ".help" or ".?" from the TString.
1275 if (strippedCommand.BeginsWith(".? ")) {
1276 strippedCommand.Remove(0, 3);
1277 } else {
1278 strippedCommand.Remove(0, 5);
1279 }
1280 // We strip the command line after removing ".help" or ".?".
1281 strippedCommand = strippedCommand.Strip(TString::kBoth);
1282
1283 if (strippedCommand == "edit") {
1284 Printf("\n ROOT terminal keyboard shortcuts (GNU-readline style).");
1285 #ifdef R__MACOSX
1286 #define FOOTNOTE " *"
1287 Printf("* Some of these commands might be intercepted by macOS predefined system shortcuts.");
1288 // https://apple.stackexchange.com/questions/18043/how-can-i-make-ctrlright-left-arrow-stop-changing-desktops-in-lion
1289 #else
1290 #define FOOTNOTE ""
1291 #endif
1292 Printf(" ==============================================================================");
1293 Printf(" Arrow_Left : move cursor left [Ctrl+B]");
1294 Printf(" Arrow_Right : move cursor right [Ctrl+F] [Ctrl+G]");
1295 #ifdef R__MACOSX
1296 Printf(" Fn+Arrow_Left : move cursor to beginning of line [Ctrl+A]");
1297 #else
1298 Printf(" Home : move cursor to beginning of line [Ctrl+A]");
1299 #endif
1300 #ifdef R__MACOSX
1301 Printf(" Fn+Arrow_Right : move cursor to end of line [Ctrl+E]");
1302 #else
1303 Printf(" End : move cursor to end of line [Ctrl+E]");
1304 #endif
1305 Printf(" Ctrl+Arrow_Left : jump to previous word [Esc,B] [Alt,B]" FOOTNOTE);
1306 Printf(" Ctrl+Arrow_Right : jump to next word [Esc,F] [Alt,F]" FOOTNOTE);
1307
1308 Printf(" Backspace : delete previous character [Ctrl+H]");
1309 Printf(" Del : delete next character [Ctrl+D]");
1310 Printf(" Esc,Backspace : delete previous word [Ctrl+W] [Esc,Ctrl+H] [Alt+Backspace] [Esc,Del] [Esc,Ctrl+Del]" FOOTNOTE);// Del is 0x7F on macOS
1311 Printf(" Ctrl+Del : delete next word [Esc,D] [Alt,D]" FOOTNOTE);
1312 Printf(" Ctrl+U : cut all characters between cursor and start of line");
1313 Printf(" Ctrl+K : cut all characters between cursor and end of line");
1314
1315 Printf(" Ctrl+T : transpose characters");
1316 Printf(" Esc,C : character to upper and jump to next word");
1317 Printf(" Esc,L : word to lower case and jump to its end");
1318 Printf(" Esc,U : word to upper case and jump to its end");
1319 Printf(" Ctrl+Shift+C : copy clipboard content");
1320 Printf(" Ctrl+Shift+V : paste clipboard content [Ctrl+Y] [Alt+Y]");
1321 #ifdef R__MACOSX
1322 Printf(" Fn+Enter : toggle overwrite mode");
1323 #else
1324 Printf(" Ins : toggle overwrite mode");
1325 #endif
1326
1327 Printf(" Ctrl+_ : undo last keypress action");
1328 Printf(" Tab : autocomplete command or print suggestions [Ctrl+I] [Esc,Tab]");
1329 Printf(" Enter : execute command [Ctrl+J] [Ctrl+M]");
1330 Printf(" Ctrl+L : clear prompt screen");
1331 Printf(" Ctrl+D : quit ROOT (if empty line)");
1332 Printf(" Ctrl+C : send kSigInt interrupt signal");
1333 Printf(" Ctrl+Z : send kSigStop pause job signal");
1334
1335 Printf(" Arrow_Down : navigate downwards in command history [Ctrl+N]");
1336 Printf(" Arrow_Up : navigate upwards in command history [Ctrl+P]");
1337 Printf(" Ctrl+R ; Ctrl+S : search command in your history by typing a string.\n"
1338 " Use Backspace if you mistyped (but not arrows).\n"
1339 " Press Ctrl+R (Ctrl+S) repeateadly to navigate matches in reverse (forward) order");
1340 Printf(" Arrow_Right : after Ctrl+R (Ctrl+S), select current match of the history search\n"
1341 " [Ctrl+O] [Enter] [Ctrl+J] [Ctrl+M] [Arrow_Left] [Esc,Esc].\n"
1342 " Use Ctrl+F or Ctrl+G to cancel search and revert original line");
1343
1344 return;
1345 }
1346 // We call the function what handles the extended ".help scopeName" command.
1347 OpenReferenceGuideFor(strippedCommand);
1348 }
1349}
1350
1351/// Load shared libs necessary for graphics. These libraries are only
1352/// loaded when gROOT->IsBatch() is kFALSE.
1353
1355{
1356 if (gROOT->IsBatch())
1357 return;
1358
1359 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualPad"))
1360 if (h->LoadPlugin() == -1)
1361 return;
1362
1363 TString name;
1364 TString title1 = "ROOT interface to ";
1365 TString nativex, title;
1366
1367#ifdef R__WIN32
1368 nativex = "win32gdk";
1369 name = "Win32gdk";
1370 title = title1 + "Win32gdk";
1371#elif defined(R__HAS_COCOA)
1372 nativex = "quartz";
1373 name = "quartz";
1374 title = title1 + "Quartz";
1375#else
1376 nativex = "x11";
1377 name = "X11";
1378 title = title1 + "X11";
1379#endif
1380
1381 TString guiBackend = gEnv->GetValue("Gui.Backend", "native");
1382 guiBackend.ToLower();
1383 if (guiBackend == "native") {
1384 guiBackend = nativex;
1385 } else {
1386 name = guiBackend;
1387 title = title1 + guiBackend;
1388 }
1389
1390 if (auto h = gROOT->GetPluginManager()->FindHandler("TVirtualX", guiBackend)) {
1391 if (h->LoadPlugin() == -1) {
1392 gROOT->SetBatch(kTRUE);
1393 return;
1394 }
1395 gVirtualX = (TVirtualX *) h->ExecPlugin(2, name.Data(), title.Data());
1397 }
1398
1399 TString guiFactory = gEnv->GetValue("Gui.Factory", "native");
1400 guiFactory.ToLower();
1401 if (guiFactory == "native")
1402 guiFactory = "root";
1403
1404 if (auto h = gROOT->GetPluginManager()->FindHandler("TGuiFactory", guiFactory)) {
1405 if (h->LoadPlugin() == -1) {
1406 gROOT->SetBatch(kTRUE);
1407 return;
1408 }
1409 gGuiFactory = (TGuiFactory *) h->ExecPlugin(0);
1410 }
1411}
1412
1413////////////////////////////////////////////////////////////////////////////////
1414/// Switch to batch mode.
1415
1417{
1418 gROOT->SetBatch();
1421#ifndef R__WIN32
1422 if (gVirtualX != gGXBatch) delete gVirtualX;
1423#endif
1425}
1426
1427////////////////////////////////////////////////////////////////////////////////
1428/// Parse the content of a line starting with ".R" (already stripped-off)
1429/// The format is
1430/// ~~~ {.cpp}
1431/// [user@]host[:dir] [-l user] [-d dbg] [script]
1432/// ~~~
1433/// The variable 'dir' is the remote directory to be used as working dir.
1434/// The username can be specified in two ways, "-l" having the priority
1435/// (as in ssh).
1436/// A 'dbg' value > 0 gives increasing verbosity.
1437/// The last argument 'script' allows to specify an alternative script to
1438/// be executed remotely to startup the session.
1439
1441 TString &hostdir, TString &user,
1442 Int_t &dbg, TString &script)
1443{
1444 if (!ln || strlen(ln) <= 0)
1445 return 0;
1446
1447 Int_t rc = 0;
1448 Bool_t isHostDir = kTRUE;
1449 Bool_t isScript = kFALSE;
1450 Bool_t isUser = kFALSE;
1451 Bool_t isDbg = kFALSE;
1452
1453 TString line(ln);
1454 TString tkn;
1455 Int_t from = 0;
1456 while (line.Tokenize(tkn, from, " ")) {
1457 if (tkn == "-l") {
1458 // Next is a user name
1459 isUser = kTRUE;
1460 } else if (tkn == "-d") {
1461 isDbg = kTRUE;
1462 } else if (tkn == "-close") {
1463 rc = 1;
1464 } else if (tkn.BeginsWith("-")) {
1465 ::Warning("TApplication::ParseRemoteLine","unknown option: %s", tkn.Data());
1466 } else {
1467 if (isUser) {
1468 user = tkn;
1469 isUser = kFALSE;
1470 } else if (isDbg) {
1471 dbg = tkn.Atoi();
1472 isDbg = kFALSE;
1473 } else if (isHostDir) {
1474 hostdir = tkn;
1475 hostdir.ReplaceAll(":","/");
1476 isHostDir = kFALSE;
1477 isScript = kTRUE;
1478 } else if (isScript) {
1479 // Add everything left
1480 script = tkn;
1481 script.Insert(0, "\"");
1482 script += "\"";
1483 // isScript = kFALSE; // [clang-tidy] never read
1484 break;
1485 }
1486 }
1487 }
1488
1489 // Done
1490 return rc;
1491}
1492
1493////////////////////////////////////////////////////////////////////////////////
1494/// Process the content of a line starting with ".R" (already stripped-off)
1495/// The format is
1496/// ~~~ {.cpp}
1497/// [user@]host[:dir] [-l user] [-d dbg] [script] | [host] -close
1498/// ~~~
1499/// The variable 'dir' is the remote directory to be used as working dir.
1500/// The username can be specified in two ways, "-l" having the priority
1501/// (as in ssh).
1502/// A 'dbg' value > 0 gives increasing verbosity.
1503/// The last argument 'script' allows to specify an alternative script to
1504/// be executed remotely to startup the session.
1505
1507{
1508 if (!line) return 0;
1509
1510 if (!strncmp(line, "-?", 2) || !strncmp(line, "-h", 2) ||
1511 !strncmp(line, "--help", 6)) {
1512 Info("ProcessRemote", "remote session help:");
1513 Printf(".R [user@]host[:dir] [-l user] [-d dbg] [[<]script] | [host] -close");
1514 Printf("Create a ROOT session on the specified remote host.");
1515 Printf("The variable \"dir\" is the remote directory to be used as working dir.");
1516 Printf("The username can be specified in two ways, \"-l\" having the priority");
1517 Printf("(as in ssh). A \"dbg\" value > 0 gives increasing verbosity.");
1518 Printf("The last argument \"script\" allows to specify an alternative script to");
1519 Printf("be executed remotely to startup the session, \"roots\" being");
1520 Printf("the default. If the script is preceded by a \"<\" the script will be");
1521 Printf("sourced, after which \"roots\" is executed. The sourced script can be ");
1522 Printf("used to change the PATH and other variables, allowing an alternative");
1523 Printf("\"roots\" script to be found.");
1524 Printf("To close down a session do \".R host -close\".");
1525 Printf("To switch between sessions do \".R host\", to switch to the local");
1526 Printf("session do \".R\".");
1527 Printf("To list all open sessions do \"gApplication->GetApplications()->Print()\".");
1528 return 0;
1529 }
1530
1531 TString hostdir, user, script;
1532 Int_t dbg = 0;
1533 Int_t rc = ParseRemoteLine(line, hostdir, user, dbg, script);
1534 if (hostdir.Length() <= 0) {
1535 // Close the remote application if required
1536 if (rc == 1) {
1538 delete fAppRemote;
1539 }
1540 // Return to local run
1541 fAppRemote = nullptr;
1542 // Done
1543 return 1;
1544 } else if (rc == 1) {
1545 // close an existing remote application
1546 TApplication *ap = TApplication::Open(hostdir, 0, nullptr);
1547 if (ap) {
1549 delete ap;
1550 }
1551 }
1552 // Attach or start a remote application
1553 if (user.Length() > 0)
1554 hostdir.Insert(0, TString::Format("%s@", user.Data()));
1555 const char *sc = (script.Length() > 0) ? script.Data() : nullptr;
1556 TApplication *ap = TApplication::Open(hostdir, dbg, sc);
1557 if (ap) {
1558 fAppRemote = ap;
1559 }
1560
1561 // Done
1562 return 1;
1563}
1564
1565namespace {
1566 static int PrintFile(const char* filename) {
1567 TString sFileName(filename);
1568 gSystem->ExpandPathName(sFileName);
1569 if (gSystem->AccessPathName(sFileName)) {
1570 Error("ProcessLine()", "Cannot find file %s", filename);
1571 return 1;
1572 }
1573 std::ifstream instr(sFileName);
1574 TString content;
1575 content.ReadFile(instr);
1576 Printf("%s", content.Data());
1577 return 0;
1578 }
1579 } // namespace
1580
1581////////////////////////////////////////////////////////////////////////////////
1582/// Process a single command line, either a C++ statement or an interpreter
1583/// command starting with a ".".
1584/// Return the return value of the command cast to a long.
1585
1586Longptr_t TApplication::ProcessLine(const char *line, Bool_t sync, Int_t *err)
1587{
1588 if (!line || !*line) return 0;
1589
1590 // If we are asked to go remote do it
1591 if (!strncmp(line, ".R", 2)) {
1592 Int_t n = 2;
1593 while (*(line+n) == ' ')
1594 n++;
1595 return ProcessRemote(line+n, err);
1596 }
1597
1598 // Redirect, if requested
1601 return fAppRemote->ProcessLine(line, err);
1602 }
1603
1604 if (!strncasecmp(line, ".qqqqqqq", 7)) {
1605 gSystem->Abort();
1606 } else if (!strncasecmp(line, ".qqqqq", 5)) {
1607 Info("ProcessLine", "Bye... (try '.qqqqqqq' if still running)");
1608 gSystem->Exit(1);
1609 } else if (!strncasecmp(line, ".exit", 4) || !strncasecmp(line, ".quit", 2)) {
1610 Terminate(0);
1611 return 0;
1612 }
1613
1614 if (!strncmp(line, ".gh", 3)) {
1615 GitHub(line);
1616 return 1;
1617 }
1618
1619 if (!strncmp(line, ".forum", 6)) {
1620 Forum(line);
1621 return 1;
1622 }
1623
1624 if (!strncmp(line, ".?", 2) || !strncmp(line, ".help", 5)) {
1625 Help(line);
1626 return 1;
1627 }
1628
1629 if (!strncmp(line, ".demo", 5)) {
1630 if (gROOT->IsBatch()) {
1631 Error("ProcessLine", "Cannot show demos in batch mode!");
1632 return 1;
1633 }
1634 ProcessLine(".x " + TROOT::GetTutorialDir() + "/demos.C");
1635 return 0;
1636 }
1637
1638 if (!strncmp(line, ".license", 8)) {
1639 return PrintFile(TROOT::GetDocDir() + "/LICENSE");
1640 }
1641
1642 if (!strncmp(line, ".credits", 8)) {
1643 TString credits = TROOT::GetDocDir() + "/CREDITS";
1644 if (gSystem->AccessPathName(credits, kReadPermission))
1645 credits = TROOT::GetDocDir() + "/README/CREDITS";
1646 return PrintFile(credits);
1647 }
1648
1649 if (!strncmp(line, ".pwd", 4)) {
1650 if (gDirectory)
1651 Printf("Current directory: %s", gDirectory->GetPath());
1652 if (gPad)
1653 Printf("Current pad: %s", gPad->GetName());
1654 if (gStyle)
1655 Printf("Current style: %s", gStyle->GetName());
1656 return 1;
1657 }
1658
1659 if (!strncmp(line, ".ls", 3)) {
1660 const char *opt = nullptr;
1661 if (line[3]) opt = &line[3];
1662 if (gDirectory) gDirectory->ls(opt);
1663 return 1;
1664 }
1665
1666 if (!strncmp(line, ".which", 6)) {
1667 char *fn = Strip(line+7);
1668 char *s = strtok(fn, "+("); // this method does not need to be reentrant
1670 if (!mac)
1671 Printf("No macro %s in path %s", s, TROOT::GetMacroPath());
1672 else
1673 Printf("%s", mac);
1674 delete [] fn;
1675 delete [] mac;
1676 return mac ? 1 : 0;
1677 }
1678
1679 if (!strncmp(line, ".L", 2) || !strncmp(line, ".U", 2)) {
1680 TString aclicMode, arguments, io;
1681 TString fname = gSystem->SplitAclicMode(line+3, aclicMode, arguments, io);
1682
1683 char *mac = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1684 if (arguments.Length())
1685 Warning("ProcessLine", "argument(s) \"%s\" ignored with .%c", arguments.Data(), line[1]);
1686 Longptr_t retval = 0;
1687 if (!mac) {
1688 Error("ProcessLine", "macro %s not found in path %s", fname.Data(), TROOT::GetMacroPath());
1689 } else {
1690 TString cmd(line + 1);
1691 Ssiz_t posSpace = cmd.Index(' ');
1692 if (posSpace == kNPOS)
1693 cmd.Remove(1);
1694 else
1695 cmd.Remove(posSpace);
1696 auto tempbuf = TString::Format(".%s %s%s%s", cmd.Data(), mac, aclicMode.Data(), io.Data());
1697 delete[] mac;
1698 if (sync)
1699 retval = gInterpreter->ProcessLineSynch(tempbuf.Data(), (TInterpreter::EErrorCode *)err);
1700 else
1701 retval = gInterpreter->ProcessLine(tempbuf.Data(), (TInterpreter::EErrorCode *)err);
1702 }
1703
1704 InitializeGraphics(gROOT->IsWebDisplay());
1705
1706 return retval;
1707 }
1708
1709 if (!strncmp(line, ".X", 2) || !strncmp(line, ".x", 2)) {
1710 return ProcessFile(line+3, err, line[2] == 'k');
1711 }
1712
1713 if (!strcmp(line, ".reset")) {
1714 // Do nothing, .reset disabled in Cling because too many side effects
1715 Printf("*** .reset not allowed, please use gROOT->Reset() ***");
1716 return 0;
1717
1718#if 0
1719 // delete the ROOT dictionary since CINT will destroy all objects
1720 // referenced by the dictionary classes (TClass et. al.)
1721 gROOT->GetListOfClasses()->Delete();
1722 // fall through
1723#endif
1724 }
1725
1726 if (sync)
1727 return gInterpreter->ProcessLineSynch(line, (TInterpreter::EErrorCode*)err);
1728 else
1729 return gInterpreter->ProcessLine(line, (TInterpreter::EErrorCode*)err);
1730}
1731
1732////////////////////////////////////////////////////////////////////////////////
1733/// Process a file containing a C++ macro.
1734
1735Longptr_t TApplication::ProcessFile(const char *file, Int_t *error, Bool_t keep)
1736{
1737 return ExecuteFile(file, error, keep);
1738}
1739
1740////////////////////////////////////////////////////////////////////////////////
1741/// Execute a file containing a C++ macro (static method). Can be used
1742/// while TApplication is not yet created.
1743
1744Longptr_t TApplication::ExecuteFile(const char *file, Int_t *error, Bool_t keep)
1745{
1746 static const Int_t kBufSize = 1024;
1747
1748 if (!file || !*file) return 0;
1749
1750 TString aclicMode;
1751 TString arguments;
1752 TString io;
1753 TString fname = gSystem->SplitAclicMode(file, aclicMode, arguments, io);
1754
1755 char *exnam = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
1756 if (!exnam) {
1757 ::Error("TApplication::ExecuteFile", "macro %s not found in path %s", fname.Data(),
1759 delete [] exnam;
1760 if (error)
1762 return 0;
1763 }
1764
1765 ::std::ifstream macro(exnam, std::ios::in);
1766 if (!macro.good()) {
1767 ::Error("TApplication::ExecuteFile", "%s no such file", exnam);
1768 if (error)
1770 delete [] exnam;
1771 return 0;
1772 }
1773
1774 char currentline[kBufSize];
1775 char dummyline[kBufSize];
1776 int tempfile = 0;
1777 int comment = 0;
1778 int ifndefc = 0;
1779 int ifdef = 0;
1780 char *s = nullptr;
1781 Bool_t execute = kFALSE;
1782 Longptr_t retval = 0;
1783
1784 while (1) {
1785 bool res = (bool)macro.getline(currentline, kBufSize);
1786 if (macro.eof()) break;
1787 if (!res) {
1788 // Probably only read kBufSize, let's ignore the remainder of
1789 // the line.
1790 macro.clear();
1791 while (!macro.getline(dummyline, kBufSize) && !macro.eof()) {
1792 macro.clear();
1793 }
1794 }
1795 s = currentline;
1796 while (s && (*s == ' ' || *s == '\t')) s++; // strip-off leading blanks
1797
1798 // very simple minded pre-processor parsing, only works in case macro file
1799 // starts with "#ifndef __CINT__". In that case everything till next
1800 // "#else" or "#endif" will be skipped.
1801 if (*s == '#') {
1802 char *cs = Compress(currentline);
1803 if (strstr(cs, "#ifndef__CINT__") ||
1804 strstr(cs, "#if!defined(__CINT__)"))
1805 ifndefc = 1;
1806 else if (ifndefc && (strstr(cs, "#ifdef") || strstr(cs, "#ifndef") ||
1807 strstr(cs, "#ifdefined") || strstr(cs, "#if!defined")))
1808 ifdef++;
1809 else if (ifndefc && strstr(cs, "#endif")) {
1810 if (ifdef)
1811 ifdef--;
1812 else
1813 ifndefc = 0;
1814 } else if (ifndefc && !ifdef && strstr(cs, "#else"))
1815 ifndefc = 0;
1816 delete [] cs;
1817 }
1818 if (!*s || *s == '#' || ifndefc || !strncmp(s, "//", 2)) continue;
1819
1820 if (!comment && (!strncmp(s, ".X", 2) || !strncmp(s, ".x", 2))) {
1821 retval = ExecuteFile(s+3);
1822 execute = kTRUE;
1823 continue;
1824 }
1825
1826 if (!strncmp(s, "/*", 2)) comment = 1;
1827 if (comment) {
1828 // handle slightly more complex cases like: /* */ /*
1829again:
1830 s = strstr(s, "*/");
1831 if (s) {
1832 comment = 0;
1833 s += 2;
1834
1835 while (s && (*s == ' ' || *s == '\t')) s++; // strip-off leading blanks
1836 if (!*s) continue;
1837 if (!strncmp(s, "//", 2)) continue;
1838 if (!strncmp(s, "/*", 2)) {
1839 comment = 1;
1840 goto again;
1841 }
1842 }
1843 }
1844 if (!comment && *s == '{') tempfile = 1;
1845 if (!comment) break;
1846 }
1847 macro.close();
1848
1849 if (!execute) {
1850 TString exname = exnam;
1851 if (!tempfile) {
1852 // We have a script that does NOT contain an unnamed macro,
1853 // so we can call the script compiler on it.
1854 exname += aclicMode;
1855 }
1856 exname += arguments;
1857 exname += io;
1859 TString tempbuf;
1860 if (tempfile) {
1861 tempbuf.Form(".x %s", exname.Data());
1862 } else {
1863 tempbuf.Form(".X%s %s", keep ? "k" : " ", exname.Data());
1864 }
1865 retval = gInterpreter->ProcessLineSynch(tempbuf,(TInterpreter::EErrorCode*)error);
1866 }
1867
1868 delete [] exnam;
1869 return retval;
1870}
1871
1872////////////////////////////////////////////////////////////////////////////////
1873/// Main application eventloop. Calls system dependent eventloop via gSystem.
1874
1875void TApplication::Run(Bool_t retrn)
1876{
1877 SetReturnFromRun(retrn);
1878
1879 fIsRunning = kTRUE;
1881 gSystem->Run();
1883}
1884
1885////////////////////////////////////////////////////////////////////////////////
1886/// Set the command to be executed after the system has been idle for
1887/// idleTimeInSec seconds. Normally called via TROOT::Idle(...).
1888
1889void TApplication::SetIdleTimer(UInt_t idleTimeInSec, const char *command)
1890{
1892 fIdleCommand = command;
1893 fIdleTimer = new TIdleTimer(idleTimeInSec*1000);
1895}
1896
1897////////////////////////////////////////////////////////////////////////////////
1898/// Remove idle timer. Normally called via TROOT::Idle(0).
1899
1902 if (fIdleTimer) {
1903 // timers are removed from the gSystem timer list by their dtor
1905 }
1906}
1907
1908////////////////////////////////////////////////////////////////////////////////
1909/// Called when system starts idleing.
1910
1912{
1913 if (fIdleTimer) {
1914 fIdleTimer->Reset();
1916 }
1917}
1918
1919////////////////////////////////////////////////////////////////////////////////
1920/// Called when system stops idleing.
1921
1923{
1924 if (fIdleTimer)
1926}
1927
1928////////////////////////////////////////////////////////////////////////////////
1929/// What to do when tab is pressed. Re-implemented by TRint.
1930/// See TTabCom::Hook() for meaning of return values.
1931
1932Int_t TApplication::TabCompletionHook(char* /*buf*/, int* /*pLoc*/, std::ostream& /*out*/)
1934 return -1;
1935}
1936
1937
1938////////////////////////////////////////////////////////////////////////////////
1939/// Terminate the application by call TSystem::Exit() unless application has
1940/// been told to return from Run(), by a call to SetReturnFromRun().
1942void TApplication::Terminate(Int_t status)
1943{
1944 Emit("Terminate(Int_t)", status);
1945
1946 if (fReturnFromRun)
1947 gSystem->ExitLoop();
1948 else {
1949 gSystem->Exit(status);
1950 }
1951}
1953////////////////////////////////////////////////////////////////////////////////
1954/// Emit signal when a line has been processed.
1955
1956void TApplication::LineProcessed(const char *line)
1957{
1958 Emit("LineProcessed(const char*)", line);
1960
1961////////////////////////////////////////////////////////////////////////////////
1962/// Emit signal when console keyboard key was pressed.
1963
1965{
1966 Emit("KeyPressed(Int_t)", key);
1967}
1968
1969////////////////////////////////////////////////////////////////////////////////
1970/// Emit signal when return key was pressed.
1971
1973{
1974 Emit("ReturnPressed(char*)", text);
1975}
1976
1977////////////////////////////////////////////////////////////////////////////////
1978/// Set console echo mode:
1979///
1980/// - mode = kTRUE - echo input symbols
1981/// - mode = kFALSE - noecho input symbols
1982
1984{
1985}
1986
1987////////////////////////////////////////////////////////////////////////////////
1988/// Static function used to create a default application environment.
1989
1991{
1993 // gApplication is set at the end of 'new TApplication.
1994 if (!gApplication) {
1995 char *a = StrDup("RootApp");
1996 char *b = StrDup("-b");
1997 char *argv[2];
1998 Int_t argc = 2;
1999 argv[0] = a;
2000 argv[1] = b;
2001 new TApplication("RootApp", &argc, argv, nullptr, 0);
2002 if (gDebug > 0)
2003 Printf("<TApplication::CreateApplication>: "
2004 "created default TApplication");
2005 delete [] a; delete [] b;
2007 }
2008}
2009
2010////////////////////////////////////////////////////////////////////////////////
2011/// Static function used to attach to an existing remote application
2012/// or to start one.
2013
2014TApplication *TApplication::Open(const char *url,
2015 Int_t debug, const char *script)
2016{
2017 TApplication *ap = nullptr;
2018 TUrl nu(url);
2019 Int_t nnew = 0;
2020
2021 // Look among the existing ones
2022 if (fgApplications) {
2023 TIter nxa(fgApplications);
2024 while ((ap = (TApplication *) nxa())) {
2025 TString apn(ap->ApplicationName());
2026 if (apn == url) {
2027 // Found matching application
2028 return ap;
2029 } else {
2030 // Check if same machine and user
2031 TUrl au(apn);
2032 if (strlen(au.GetUser()) > 0 && strlen(nu.GetUser()) > 0 &&
2033 !strcmp(au.GetUser(), nu.GetUser())) {
2034 if (!strncmp(au.GetHost(), nu.GetHost(), strlen(nu.GetHost())))
2035 // New session on a known machine
2036 nnew++;
2037 }
2038 }
2039 }
2040 } else {
2041 ::Error("TApplication::Open", "list of applications undefined - protocol error");
2042 return ap;
2043 }
2044
2045 // If new session on a known machine pass the number as option
2046 if (nnew > 0) {
2047 nnew++;
2048 nu.SetOptions(TString::Format("%d", nnew).Data());
2049 }
2050
2051 // Instantiate the TApplication object to be run
2052 TPluginHandler *h = nullptr;
2053 if ((h = gROOT->GetPluginManager()->FindHandler("TApplication","remote"))) {
2054 if (h->LoadPlugin() == 0) {
2055 ap = (TApplication *) h->ExecPlugin(3, nu.GetUrl(), debug, script);
2056 } else {
2057 ::Error("TApplication::Open", "failed to load plugin for TApplicationRemote");
2058 }
2059 } else {
2060 ::Error("TApplication::Open", "failed to find plugin for TApplicationRemote");
2061 }
2062
2063 // Add to the list
2064 if (ap && !(ap->TestBit(kInvalidObject))) {
2065 fgApplications->Add(ap);
2066 gROOT->GetListOfBrowsables()->Add(ap, ap->ApplicationName());
2067 TIter next(gROOT->GetListOfBrowsers());
2068 TBrowser *b;
2069 while ((b = (TBrowser*) next()))
2070 b->Add(ap, ap->ApplicationName());
2071 gROOT->RefreshBrowsers();
2072 } else {
2073 SafeDelete(ap);
2074 ::Error("TApplication::Open",
2075 "TApplicationRemote for %s could not be instantiated", url);
2076 }
2077
2078 // Done
2079 return ap;
2080}
2081
2082////////////////////////////////////////////////////////////////////////////////
2083/// Static function used to close a remote application
2084
2086{
2087 if (app) {
2088 app->Terminate(0);
2089 fgApplications->Remove(app);
2090 gROOT->GetListOfBrowsables()->RecursiveRemove(app);
2091 TIter next(gROOT->GetListOfBrowsers());
2092 TBrowser *b;
2093 while ((b = (TBrowser*) next()))
2094 b->RecursiveRemove(app);
2095 gROOT->RefreshBrowsers();
2096 }
2097}
2098
2099////////////////////////////////////////////////////////////////////////////////
2100/// Show available sessions
2101
2102void TApplication::ls(Option_t *opt) const
2103{
2104 if (fgApplications) {
2105 TIter nxa(fgApplications);
2106 TApplication *a = nullptr;
2107 while ((a = (TApplication *) nxa())) {
2108 a->Print(opt);
2109 }
2110 } else {
2111 Print(opt);
2112 }
2113}
2114
2115////////////////////////////////////////////////////////////////////////////////
2116/// Static method returning the list of available applications
2117
2119{
2120 return fgApplications;
2121}
#define SafeDelete(p)
Definition RConfig.hxx:550
#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
Definition TClassTable.h:97
@ 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:74
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:376
Int_t gDebug
Definition TROOT.cxx:595
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:406
char * Compress(const char *str)
Remove all blanks from the string str.
Definition TString.cxx:2550
char * Strip(const char *str, char c=' ')
Strip leading and trailing c (blanks by default) from a string.
Definition TString.cxx:2499
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2481
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2535
R__EXTERN TStyle * gStyle
Definition TStyle.h:433
@ kReadPermission
Definition TSystem.h:47
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
#define R__LOCKGUARD(mutex)
#define gPad
#define gVirtualX
Definition TVirtualX.h:338
R__EXTERN TVirtualX * gGXBatch
Definition TVirtualX.h:341
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:578
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:822
virtual TObjLink * FirstLink() const
Definition TList.h:102
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:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
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:962
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:976
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1004
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:200
@ 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:950
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:2723
static void ShutDown()
Shut down ROOT.
Definition TROOT.cxx:3078
static const TString & GetTTFFontDir()
Get the fonts directory in the installation. Static utility function.
Definition TROOT.cxx:3131
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition TROOT.cxx:2848
static const TString & GetTutorialDir()
Get the tutorials directory in the installation. Static utility function.
Definition TROOT.cxx:3057
static const TString & GetDocDir()
Get the documentation directory in the installation. Static utility function.
Definition TROOT.cxx:3020
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:419
void ToLower()
Change string to lower-case.
Definition TString.cxx:1170
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:659
Int_t Atoi() const
Return integer value of string.
Definition TString.cxx:1966
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2222
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1151
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition TString.h:692
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:531
const char * Data() const
Definition TString.h:378
TString & Chop()
Definition TString.h:689
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:702
TString MD5() const
Return the MD5 digest for this string, in a string representation.
Definition TString.cxx:933
@ kBoth
Definition TString.h:278
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:625
TString & Prepend(const char *cs)
Definition TString.h:671
Bool_t IsNull() const
Definition TString.h:416
std::istream & ReadFile(std::istream &str)
Replace string with the contents of strm, stopping at an EOF.
Definition Stringio.cxx:28
TString & Remove(Ssiz_t pos)
Definition TString.h:683
TString & Append(const char *cs)
Definition TString.h:574
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:2356
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2334
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:634
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:649
void SetScreenFactor(Float_t factor=1)
Definition TStyle.h:315
virtual void NotifyApplicationCreated()
Hook to tell TSystem that the TApplication object has been created.
Definition TSystem.cxx:298
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition TSystem.cxx:1261
virtual const char * Getenv(const char *env)
Get environment variable.
Definition TSystem.cxx:1650
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition TSystem.cxx:4235
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:640
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:1385
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:1283
virtual void Run()
System event loop.
Definition TSystem.cxx:330
virtual void ExitLoop()
Exit from event loop.
Definition TSystem.cxx:379
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition TSystem.cxx:849
virtual void AddTimer(TTimer *t)
Add timer to list of system timers.
Definition TSystem.cxx:458
virtual const char * GetBuildCompilerVersionStr() const
Return the build compiler version identifier string.
Definition TSystem.cxx:3876
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition TSystem.cxx:703
virtual const char * WorkingDirectory()
Return working directory.
Definition TSystem.cxx:858
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition TSystem.cxx:1533
virtual void SetProgname(const char *name)
Set the application name (from command line, argv[0]) and copy it in gProgName.
Definition TSystem.cxx:225
virtual const char * GetBuildArch() const
Return the build architecture.
Definition TSystem.cxx:3852
virtual void Abort(int code=0)
Abort the application.
Definition TSystem.cxx:712
virtual TTimer * RemoveTimer(TTimer *t)
Remove timer from list of system timers.
Definition TSystem.cxx:468
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:537
void EnableThreadSafety()
Enable support for multi-threading within the ROOT code in particular, enables the global mutex to ma...
Definition TROOT.cxx:499
const char * GetUnqualifiedName(const char *name)
Return the start of the unqualified name include in 'original'.