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