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