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