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