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