TApplication.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TApplication.cxx 36381 2010-10-20 12:24:14Z brun $
00002 // Author: Fons Rademakers   22/12/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TApplication                                                         //
00015 //                                                                      //
00016 // This class creates the ROOT Application Environment that interfaces  //
00017 // to the windowing system eventloop and eventhandlers.                 //
00018 // This class must be instantiated exactly once in any given            //
00019 // application. Normally the specific application class inherits from   //
00020 // TApplication (see TRint).                                            //
00021 //                                                                      //
00022 //////////////////////////////////////////////////////////////////////////
00023 
00024 #include "RConfigure.h"
00025 #include "Riostream.h"
00026 #include "TApplication.h"
00027 #include "TException.h"
00028 #include "TGuiFactory.h"
00029 #include "TVirtualX.h"
00030 #include "TROOT.h"
00031 #include "TSystem.h"
00032 #include "TString.h"
00033 #include "TError.h"
00034 #include "TObjArray.h"
00035 #include "TObjString.h"
00036 #include "TTimer.h"
00037 #include "TInterpreter.h"
00038 #include "TStyle.h"
00039 #include "TVirtualPad.h"
00040 #include "TEnv.h"
00041 #include "TColor.h"
00042 #include "TClassTable.h"
00043 #include "TPluginManager.h"
00044 #include "TClassTable.h"
00045 #include "TBrowser.h"
00046 #include "TUrl.h"
00047 
00048 TApplication *gApplication = 0;
00049 Bool_t TApplication::fgGraphNeeded = kFALSE;
00050 Bool_t TApplication::fgGraphInit = kFALSE;
00051 TList *TApplication::fgApplications = 0;  // List of available applications
00052 
00053 //______________________________________________________________________________
00054 class TIdleTimer : public TTimer {
00055 public:
00056    TIdleTimer(Long_t ms) : TTimer(ms, kTRUE) { }
00057    Bool_t Notify();
00058 };
00059 
00060 //______________________________________________________________________________
00061 Bool_t TIdleTimer::Notify()
00062 {
00063    // Notify handler.
00064    gApplication->HandleIdleTimer();
00065    Reset();
00066    return kFALSE;
00067 }
00068 
00069 
00070 ClassImp(TApplication)
00071 
00072 //______________________________________________________________________________
00073 TApplication::TApplication()
00074 {
00075    // Default ctor. Can be used by classes deriving from TApplication.
00076 
00077    fArgc            = 0;
00078    fArgv            = 0;
00079    fAppImp          = 0;
00080    fAppRemote       = 0;
00081    fIsRunning       = kFALSE;
00082    fReturnFromRun   = kFALSE;
00083    fNoLog           = kFALSE;
00084    fNoLogo          = kFALSE;
00085    fQuit            = kFALSE;
00086    fUseMemstat      = kFALSE;
00087    fFiles           = 0;
00088    fIdleTimer       = 0;
00089    fSigHandler      = 0;
00090    fExitOnException = kDontExit;
00091    ResetBit(kProcessRemotely);
00092 }
00093 
00094 //______________________________________________________________________________
00095 TApplication::TApplication(const char *appClassName,
00096                            Int_t *argc, char **argv, void *options,
00097                            Int_t numOptions)
00098 {
00099    // Create an application environment. The application environment
00100    // provides an interface to the graphics system and eventloop
00101    // (be it X, Windoze, MacOS or BeOS). After creating the application
00102    // object start the eventloop by calling its Run() method. The command
00103    // line options recogized by TApplication are described in the GetOptions()
00104    // method. The recognized options are removed from the argument array.
00105    // The original list of argument options can be retrieved via the Argc()
00106    // and Argv() methods. The appClassName "proofserv" is reserved for the
00107    // PROOF system. The "options" and "numOptions" arguments are not used,
00108    // except if you want to by-pass the argv processing by GetOptions()
00109    // in which case you should specify numOptions<0. All options will
00110    // still be available via the Argv() method for later use.
00111 
00112    if (gApplication && gApplication->TestBit(kDefaultApplication)) {
00113       // allow default TApplication to be replaced by a "real" TApplication
00114       delete gApplication;
00115       gApplication = 0;
00116       gROOT->SetBatch(kFALSE);
00117       fgGraphInit = kFALSE;
00118    }
00119 
00120    if (gApplication) {
00121       Error("TApplication", "only one instance of TApplication allowed");
00122       return;
00123    }
00124 
00125    if (!gROOT)
00126       ::Fatal("TApplication::TApplication", "ROOT system not initialized");
00127 
00128    if (!gSystem)
00129       ::Fatal("TApplication::TApplication", "gSystem not initialized");
00130 
00131    gApplication = this;
00132    gROOT->SetApplication(this);
00133    gROOT->SetName(appClassName);
00134 
00135    // Create the list of applications the first time
00136    if (!fgApplications)
00137       fgApplications = new TList;
00138    fgApplications->Add(this);
00139 
00140    if (options) { }  // use unused argument
00141 
00142    // copy command line arguments, can be later accessed via Argc() and Argv()
00143    if (argc && *argc > 0) {
00144       fArgc = *argc;
00145       fArgv = (char **)new char*[fArgc];
00146    } else {
00147       fArgc = 0;
00148       fArgv = 0;
00149    }
00150 
00151    for (int i = 0; i < fArgc; i++)
00152       fArgv[i] = StrDup(argv[i]);
00153 
00154    fNoLog           = kFALSE;
00155    fNoLogo          = kFALSE;
00156    fQuit            = kFALSE;
00157    fUseMemstat      = kFALSE;
00158    fExitOnException = kDontExit;
00159    fAppImp          = 0;
00160 
00161    if (numOptions >= 0)
00162       GetOptions(argc, argv);
00163 
00164    if (fArgv)
00165       gSystem->SetProgname(fArgv[0]);
00166 
00167    // Tell TSystem the TApplication has been created
00168    gSystem->NotifyApplicationCreated();
00169 
00170    fIdleTimer     = 0;
00171    fSigHandler    = 0;
00172    fIsRunning     = kFALSE;
00173    fReturnFromRun = kFALSE;
00174    fAppImp        = gGuiFactory->CreateApplicationImp(appClassName, argc, argv);
00175    fAppRemote     = 0;
00176    ResetBit(kProcessRemotely);
00177 
00178    // Enable autoloading
00179    gInterpreter->EnableAutoLoading();
00180 
00181    // Initialize the graphics environment
00182    if (gClassTable->GetDict("TPad")) {
00183       fgGraphNeeded = kTRUE;
00184       InitializeGraphics();
00185    }
00186 
00187    // Make sure all registered dictionaries have been initialized
00188    // and that all types have been loaded
00189    gInterpreter->InitializeDictionaries();
00190    gInterpreter->UpdateListOfTypes();
00191 
00192    // Save current interpreter context
00193    gInterpreter->SaveContext();
00194    gInterpreter->SaveGlobalsContext();
00195 
00196    // to allow user to interact with TCanvas's under WIN32
00197    gROOT->SetLineHasBeenProcessed();
00198 
00199    // activate TMemStat
00200    if (fUseMemstat || gEnv->GetValue("Root.TMemStat", 0)) {
00201       fUseMemstat = kTRUE;
00202       Int_t buffersize = gEnv->GetValue("Root.TMemStat.buffersize", 100000);
00203       Int_t maxcalls   = gEnv->GetValue("Root.TMemStat.maxcalls", 5000000);
00204       const char *ssystem = gEnv->GetValue("Root.TMemStat.system","gnubuiltin");
00205       if (maxcalls > 0) {
00206          gROOT->ProcessLine(Form("new TMemStat(\"%s\",%d,%d);",ssystem,buffersize,maxcalls));
00207       }
00208    }
00209 }
00210 
00211 //______________________________________________________________________________
00212 TApplication::~TApplication()
00213 {
00214    // TApplication dtor.
00215 
00216    for (int i = 0; i < fArgc; i++)
00217       if (fArgv[i]) delete [] fArgv[i];
00218    delete [] fArgv;
00219    SafeDelete(fAppImp);
00220    if (fgApplications)
00221       fgApplications->Remove(this);
00222 
00223    //close TMemStat
00224    if (fUseMemstat) {
00225       ProcessLine("TMemStat::Close()");
00226       fUseMemstat = kFALSE;
00227    }
00228 }
00229 
00230 //______________________________________________________________________________
00231 void TApplication::NeedGraphicsLibs()
00232 {
00233    // Static method. This method should be called from static library
00234    // initializers if the library needs the low level graphics system.
00235 
00236    fgGraphNeeded = kTRUE;
00237 }
00238 
00239 //______________________________________________________________________________
00240 void TApplication::InitializeGraphics()
00241 {
00242    // Initialize the graphics environment.
00243 
00244    if (fgGraphInit || !fgGraphNeeded)
00245       return;
00246 
00247    fgGraphInit = kTRUE;
00248 
00249    // Load the graphics related libraries
00250    LoadGraphicsLibs();
00251 
00252    // Try to load TrueType font renderer. Only try to load if not in batch
00253    // mode and Root.UseTTFonts is true and Root.TTFontPath exists. Abort silently
00254    // if libttf or libGX11TTF are not found in $ROOTSYS/lib or $ROOTSYS/ttf/lib.
00255    const char *ttpath = gEnv->GetValue("Root.TTFontPath",
00256 #ifdef TTFFONTDIR
00257                                        TTFFONTDIR);
00258 #else
00259                                        "$(ROOTSYS)/fonts");
00260 #endif
00261    char *ttfont = gSystem->Which(ttpath, "arialbd.ttf", kReadPermission);
00262    // Check for use of DFSG - fonts
00263    if (!ttfont)
00264       ttfont = gSystem->Which(ttpath, "FreeSansBold.ttf", kReadPermission);
00265 
00266 #if !defined(R__WIN32)
00267    if (!gROOT->IsBatch() && !strcmp(gVirtualX->GetName(), "X11") &&
00268        ttfont && gEnv->GetValue("Root.UseTTFonts", 1)) {
00269       if (gClassTable->GetDict("TGX11TTF")) {
00270          // in principle we should not have linked anything against libGX11TTF
00271          // but with ACLiC this can happen, initialize TGX11TTF by hand
00272          // (normally this is done by the static library initializer)
00273          ProcessLine("TGX11TTF::Activate();");
00274       } else {
00275          TPluginHandler *h;
00276          if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualX", "x11ttf")))
00277             if (h->LoadPlugin() == -1)
00278                Info("InitializeGraphics", "no TTF support");
00279       }
00280    }
00281 #endif
00282    delete [] ttfont;
00283 
00284    // Create WM dependent application environment
00285    if (fAppImp)
00286       delete fAppImp;
00287    fAppImp = gGuiFactory->CreateApplicationImp(gROOT->GetName(), &fArgc, fArgv);
00288    if (!fAppImp) {
00289       MakeBatch();
00290       fAppImp = gGuiFactory->CreateApplicationImp(gROOT->GetName(), &fArgc, fArgv);
00291    }
00292 
00293    // Create the canvas colors early so they are allocated before
00294    // any color table expensive bitmaps get allocated in GUI routines (like
00295    // creation of XPM bitmaps).
00296    TColor::InitializeColors();
00297 
00298    // Hook for further initializing the WM dependent application environment
00299    Init();
00300 
00301    // Set default screen factor (if not disabled in rc file)
00302    if (gEnv->GetValue("Canvas.UseScreenFactor", 1)) {
00303       Int_t  x, y;
00304       UInt_t w, h;
00305       if (gVirtualX) {
00306          gVirtualX->GetGeometry(-1, x, y, w, h);
00307          if (h > 0 && h < 1000) gStyle->SetScreenFactor(0.0011*h);
00308       }
00309    }
00310 }
00311 
00312 //______________________________________________________________________________
00313 void TApplication::ClearInputFiles()
00314 {
00315    // Clear list containing macro files passed as program arguments.
00316    // This method is called from TRint::Run() to ensure that the macro
00317    // files are only executed the first time Run() is called.
00318 
00319    if (fFiles) {
00320       fFiles->Delete();
00321       SafeDelete(fFiles);
00322    }
00323 }
00324 
00325 //______________________________________________________________________________
00326 char *TApplication::Argv(Int_t index) const
00327 {
00328    // Return specified argument.
00329 
00330    if (fArgv) {
00331       if (index >= fArgc) {
00332          Error("Argv", "index (%d) >= number of arguments (%d)", index, fArgc);
00333          return 0;
00334       }
00335       return fArgv[index];
00336    }
00337    return 0;
00338 }
00339 
00340 //______________________________________________________________________________
00341 void TApplication::GetOptions(Int_t *argc, char **argv)
00342 {
00343    // Get and handle command line options. Arguments handled are removed
00344    // from the argument array. The following arguments are handled:
00345    //    -b : run in batch mode without graphics
00346    //    -x : exit on exception
00347    //    -n : do not execute logon and logoff macros as specified in .rootrc
00348    //    -q : exit after processing command line macro files
00349    //    -l : do not show splash screen
00350    // The last three options are only relevant in conjunction with TRint.
00351    // The following help and info arguments are supported:
00352    //    -?       : print usage
00353    //    -h       : print usage
00354    //    --help   : print usage
00355    //    -config  : print ./configure options
00356    //    -memstat : run with memory usage monitoring
00357    // In addition to the above options the arguments that are not options,
00358    // i.e. they don't start with - or + are treated as follows (and also removed
00359    // from the argument array):
00360    //   <dir>       is considered the desired working directory and available
00361    //               via WorkingDirectory(), if more than one dir is specified the
00362    //               first one will prevail
00363    //   <file>      if the file exists its added to the InputFiles() list
00364    //   <file>.root are considered ROOT files and added to the InputFiles() list,
00365    //               the file may be a remote file url
00366    //   <macro>.C   are considered ROOT macros and also added to the InputFiles() list
00367    // In TRint we set the working directory to the <dir>, the ROOT files are
00368    // connected, and the macros are executed. If your main TApplication is not
00369    // TRint you have to decide yourself what to do whith these options.
00370    // All specified arguments (also the ones removed) can always be retrieved
00371    // via the TApplication::Argv() method.
00372 
00373    static char null[1] = { "" };
00374 
00375    fNoLog = kFALSE;
00376    fQuit  = kFALSE;
00377    fFiles = 0;
00378 
00379    if (!argc)
00380       return;
00381 
00382    int i, j;
00383    TString pwd;
00384 
00385    for (i = 1; i < *argc; i++) {
00386       if (!strcmp(argv[i], "-?") || !strncmp(argv[i], "-h", 2) ||
00387           !strncmp(argv[i], "--help", 6)) {
00388          fprintf(stderr, "Usage: %s [-l] [-b] [-n] [-q] [dir] [[file:]data.root] [file1.C ... fileN.C]\n", argv[0]);
00389          fprintf(stderr, "Options:\n");
00390          fprintf(stderr, "  -b : run in batch mode without graphics\n");
00391          fprintf(stderr, "  -x : exit on exception\n");
00392          fprintf(stderr, "  -n : do not execute logon and logoff macros as specified in .rootrc\n");
00393          fprintf(stderr, "  -q : exit after processing command line macro files\n");
00394          fprintf(stderr, "  -l : do not show splash screen\n");
00395          fprintf(stderr, " dir : if dir is a valid directory cd to it before executing\n");
00396          fprintf(stderr, "\n");
00397          fprintf(stderr, "  -?      : print usage\n");
00398          fprintf(stderr, "  -h      : print usage\n");
00399          fprintf(stderr, "  --help  : print usage\n");
00400          fprintf(stderr, "  -config : print ./configure options\n");
00401          fprintf(stderr, "  -memstat : run with memory usage monitoring\n");
00402          fprintf(stderr, "\n");
00403          Terminate(0);
00404       } else if (!strcmp(argv[i], "-config")) {
00405          fprintf(stderr, "ROOT ./configure options:\n%s\n", gROOT->GetConfigOptions());
00406          Terminate(0);
00407       } else if (!strcmp(argv[i], "-memstat")) {
00408          fUseMemstat = kTRUE;
00409          argv[i] = null;
00410       } else if (!strcmp(argv[i], "-b")) {
00411          MakeBatch();
00412          argv[i] = null;
00413       } else if (!strcmp(argv[i], "-n")) {
00414          fNoLog = kTRUE;
00415          argv[i] = null;
00416       } else if (!strcmp(argv[i], "-q")) {
00417          fQuit = kTRUE;
00418          argv[i] = null;
00419       } else if (!strcmp(argv[i], "-l")) {
00420          // used by front-end program to not display splash screen
00421          fNoLogo = kTRUE;
00422          argv[i] = null;
00423       } else if (!strcmp(argv[i], "-x")) {
00424          fExitOnException = kExit;
00425          argv[i] = null;
00426       } else if (!strcmp(argv[i], "-splash")) {
00427          // used when started by front-end program to signal that
00428          // splash screen can be popped down (TRint::PrintLogo())
00429          argv[i] = null;
00430       } else if (argv[i][0] != '-' && argv[i][0] != '+') {
00431          Long64_t size;
00432          Long_t id, flags, modtime;
00433          char *arg = strchr(argv[i], '(');
00434          if (arg) *arg = '\0';
00435          char *dir = gSystem->ExpandPathName(argv[i]);
00436          TUrl udir(dir, kTRUE);
00437          if (arg) *arg = '(';
00438          if (!gSystem->GetPathInfo(dir, &id, &size, &flags, &modtime)) {
00439             if ((flags & 2)) {
00440                // if directory set it in fWorkDir
00441                if (pwd == "") {
00442                   pwd = gSystem->WorkingDirectory();
00443                   fWorkDir = dir;
00444                   gSystem->ChangeDirectory(dir);
00445                   argv[i] = null;
00446                } else if (!strcmp(gROOT->GetName(), "Rint")) {
00447                   Warning("GetOptions", "only one directory argument can be specified (%s)", dir);
00448                }
00449             } else if (size > 0) {
00450                // if file add to list of files to be processed
00451                if (!fFiles) fFiles = new TObjArray;
00452                fFiles->Add(new TObjString(argv[i]));
00453                argv[i] = null;
00454             } else {
00455                Warning("GetOptions", "file %s has size 0, skipping", dir);
00456             }
00457          } else {
00458             if (TString(udir.GetFile()).EndsWith(".root")) {
00459                if (!strcmp(udir.GetProtocol(), "file")) {
00460                   // file ending on .root but does not exist, likely a typo
00461                   // warn user if plain root...
00462                   if (!strcmp(gROOT->GetName(), "Rint"))
00463                      Warning("GetOptions", "file %s not found", dir);
00464                } else {
00465                   // remote file, give it the benefit of the doubt and add it to list of files
00466                   if (!fFiles) fFiles = new TObjArray;
00467                   fFiles->Add(new TObjString(argv[i]));
00468                   argv[i] = null;
00469                }
00470             } else {
00471                TString mode,fargs,io;
00472                TString fname = gSystem->SplitAclicMode(dir,mode,fargs,io);
00473                char *mac;
00474                if ((mac = gSystem->Which(TROOT::GetMacroPath(), fname,
00475                                          kReadPermission))) {
00476                   // if file add to list of files to be processed
00477                   if (!fFiles) fFiles = new TObjArray;
00478                   fFiles->Add(new TObjString(argv[i]));
00479                   argv[i] = null;
00480                   delete [] mac;
00481                } else {
00482                   // only warn if we're plain root,
00483                   // other progs might have their own params
00484                   if (!strcmp(gROOT->GetName(), "Rint"))
00485                      Warning("GetOptions", "macro %s not found", fname.Data());
00486                }
00487             }
00488          }
00489          delete [] dir;
00490       }
00491       // ignore unknown options
00492    }
00493 
00494    // go back to startup directory
00495    if (pwd != "")
00496       gSystem->ChangeDirectory(pwd);
00497 
00498    // remove handled arguments from argument array
00499    j = 0;
00500    for (i = 0; i < *argc; i++) {
00501       if (strcmp(argv[i], "")) {
00502          argv[j] = argv[i];
00503          j++;
00504       }
00505    }
00506 
00507    *argc = j;
00508 }
00509 
00510 //______________________________________________________________________________
00511 void TApplication::HandleIdleTimer()
00512 {
00513    // Handle idle timeout. When this timer expires the registered idle command
00514    // will be executed by this routine and a signal will be emitted.
00515 
00516    if (!fIdleCommand.IsNull())
00517       ProcessLine(GetIdleCommand());
00518 
00519    Emit("HandleIdleTimer()");
00520 }
00521 
00522 //______________________________________________________________________________
00523 void TApplication::HandleException(Int_t sig)
00524 {
00525    // Handle exceptions (kSigBus, kSigSegmentationViolation,
00526    // kSigIllegalInstruction and kSigFloatingException) trapped in TSystem.
00527    // Specific TApplication implementations may want something different here.
00528 
00529    if (TROOT::Initialized()) {
00530       if (gException) {
00531          gInterpreter->RewindDictionary();
00532          gInterpreter->ClearFileBusy();
00533       }
00534       if (fExitOnException == kExit)
00535          gSystem->Exit(sig);
00536       else if (fExitOnException == kAbort)
00537          gSystem->Abort();
00538       else
00539          Throw(sig);
00540    }
00541    gSystem->Exit(sig);
00542 }
00543 
00544 //______________________________________________________________________________
00545 TApplication::EExitOnException TApplication::ExitOnException(TApplication::EExitOnException opt)
00546 {
00547    // Set the exit on exception option. Setting this option determines what
00548    // happens in HandleException() in case an exception (kSigBus,
00549    // kSigSegmentationViolation, kSigIllegalInstruction or kSigFloatingException)
00550    // is trapped. Choices are: kDontExit (default), kExit or kAbort.
00551    // Returns the previous value.
00552 
00553    EExitOnException old = fExitOnException;
00554    fExitOnException = opt;
00555    return old;
00556 }
00557 
00558 //______________________________________________________________________________
00559 void TApplication::Help(const char *line)
00560 {
00561    // Print help on interpreter.
00562 
00563    gInterpreter->ProcessLine(line);
00564 
00565    Printf("\nROOT special commands.");
00566    Printf("===========================================================================");
00567    Printf("             pwd          : show current directory, pad and style");
00568    Printf("             ls           : list contents of current directory");
00569    Printf("             which [file] : shows path of macro file");
00570 }
00571 
00572 //______________________________________________________________________________
00573 void TApplication::LoadGraphicsLibs()
00574 {
00575    // Load shared libs neccesary for graphics. These libraries are only
00576    // loaded when gROOT->IsBatch() is kFALSE.
00577 
00578    if (gROOT->IsBatch()) return;
00579 
00580    TPluginHandler *h;
00581    if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualPad")))
00582       if (h->LoadPlugin() == -1)
00583          return;
00584 
00585    TString name;
00586    TString title1 = "ROOT interface to ";
00587    TString nativex, title;
00588    TString nativeg = "root";
00589 #ifndef R__WIN32
00590    nativex = "x11";
00591    name    = "X11";
00592    title   = title1 + "X11";
00593 #else
00594    nativex = "win32gdk";
00595    name    = "Win32gdk";
00596    title   = title1 + "Win32gdk";
00597 #endif
00598 
00599    TString guiBackend(gEnv->GetValue("Gui.Backend", "native"));
00600    guiBackend.ToLower();
00601    if (guiBackend == "native") {
00602       guiBackend = nativex;
00603    } else {
00604       name  = guiBackend;
00605       title = title1 + guiBackend;
00606    }
00607    TString guiFactory(gEnv->GetValue("Gui.Factory", "native"));
00608    guiFactory.ToLower();
00609    if (guiFactory == "native")
00610       guiFactory = nativeg;
00611 
00612    if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualX", guiBackend))) {
00613       if (h->LoadPlugin() == -1) {
00614          gROOT->SetBatch(kTRUE);
00615          return;
00616       }
00617       gVirtualX = (TVirtualX *) h->ExecPlugin(2, name.Data(), title.Data());
00618    }
00619    if ((h = gROOT->GetPluginManager()->FindHandler("TGuiFactory", guiFactory))) {
00620       if (h->LoadPlugin() == -1) {
00621          gROOT->SetBatch(kTRUE);
00622          return;
00623       }
00624       gGuiFactory = (TGuiFactory *) h->ExecPlugin(0);
00625    }
00626 }
00627 
00628 //______________________________________________________________________________
00629 void TApplication::MakeBatch()
00630 {
00631    // Switch to batch mode.
00632 
00633    gROOT->SetBatch();
00634    if (gGuiFactory != gBatchGuiFactory) delete gGuiFactory;
00635    gGuiFactory = gBatchGuiFactory;
00636 #ifndef R__WIN32
00637    if (gVirtualX != gGXBatch) delete gVirtualX;
00638 #endif
00639    gVirtualX = gGXBatch;
00640 }
00641 
00642 //______________________________________________________________________________
00643 Int_t TApplication::ParseRemoteLine(const char *ln,
00644                                    TString &hostdir, TString &user,
00645                                    Int_t &dbg, TString &script)
00646 {
00647    // Parse the content of a line starting with ".R" (already stripped-off)
00648    // The format is
00649    //      [user@]host[:dir] [-l user] [-d dbg] [script]
00650    // The variable 'dir' is the remote directory to be used as working dir.
00651    // The username can be specified in two ways, "-l" having the priority
00652    // (as in ssh).
00653    // A 'dbg' value > 0 gives increasing verbosity.
00654    // The last argument 'script' allows to specify an alternative script to
00655    // be executed remotely to startup the session.
00656 
00657    if (!ln || strlen(ln) <= 0)
00658       return 0;
00659 
00660    Int_t rc = 0;
00661    Bool_t isHostDir = kTRUE;
00662    Bool_t isScript = kFALSE;
00663    Bool_t isUser = kFALSE;
00664    Bool_t isDbg = kFALSE;
00665 
00666    TString line(ln);
00667    TString tkn;
00668    Int_t from = 0;
00669    while (line.Tokenize(tkn, from, " ")) {
00670       if (tkn == "-l") {
00671          // Next is a user name
00672          isUser = kTRUE;
00673       } else if (tkn == "-d") {
00674          isDbg = kTRUE;
00675       } else if (tkn == "-close") {
00676          rc = 1;
00677       } else if (tkn.BeginsWith("-")) {
00678          ::Warning("TApplication::ParseRemoteLine","unknown option: %s", tkn.Data());
00679       } else {
00680          if (isUser) {
00681             user = tkn;
00682             isUser = kFALSE;
00683          } else if (isDbg) {
00684             dbg = tkn.Atoi();
00685             isDbg = kFALSE;
00686          } else if (isHostDir) {
00687             hostdir = tkn;
00688             hostdir.ReplaceAll(":","/");
00689             isHostDir = kFALSE;
00690             isScript = kTRUE;
00691          } else if (isScript) {
00692             // Add everything left
00693             script = tkn;
00694             script.Insert(0, "\"");
00695             script += "\"";
00696             isScript = kFALSE;
00697             break;
00698          }
00699       }
00700    }
00701 
00702    // Done
00703    return rc;
00704 }
00705 
00706 //______________________________________________________________________________
00707 Long_t TApplication::ProcessRemote(const char *line, Int_t *)
00708 {
00709    // Process the content of a line starting with ".R" (already stripped-off)
00710    // The format is
00711    //      [user@]host[:dir] [-l user] [-d dbg] [script] | [host] -close
00712    // The variable 'dir' is the remote directory to be used as working dir.
00713    // The username can be specified in two ways, "-l" having the priority
00714    // (as in ssh).
00715    // A 'dbg' value > 0 gives increasing verbosity.
00716    // The last argument 'script' allows to specify an alternative script to
00717    // be executed remotely to startup the session.
00718 
00719    if (!line) return 0;
00720 
00721    if (!strncmp(line, "-?", 2) || !strncmp(line, "-h", 2) ||
00722        !strncmp(line, "--help", 6)) {
00723       Info("ProcessRemote", "remote session help:");
00724       Printf(".R [user@]host[:dir] [-l user] [-d dbg] [[<]script] | [host] -close");
00725       Printf("Create a ROOT session on the specified remote host.");
00726       Printf("The variable \"dir\" is the remote directory to be used as working dir.");
00727       Printf("The username can be specified in two ways, \"-l\" having the priority");
00728       Printf("(as in ssh). A \"dbg\" value > 0 gives increasing verbosity.");
00729       Printf("The last argument \"script\" allows to specify an alternative script to");
00730       Printf("be executed remotely to startup the session, \"roots\" being");
00731       Printf("the default. If the script is preceeded by a \"<\" the script will be");
00732       Printf("sourced, after which \"roots\" is executed. The sourced script can be ");
00733       Printf("used to change the PATH and other variables, allowing an alternative");
00734       Printf("\"roots\" script to be found.");
00735       Printf("To close down a session do \".R host -close\".");
00736       Printf("To switch between sessions do \".R host\", to switch to the local");
00737       Printf("session do \".R\".");
00738       Printf("To list all open sessions do \"gApplication->GetApplications()->Print()\".");
00739       return 0;
00740    }
00741 
00742    TString hostdir, user, script;
00743    Int_t dbg = 0;
00744    Int_t rc = ParseRemoteLine(line, hostdir, user, dbg, script);
00745    if (hostdir.Length() <= 0) {
00746       // Close the remote application if required
00747       if (rc == 1) {
00748          TApplication::Close(fAppRemote);
00749          delete fAppRemote;
00750       }
00751       // Return to local run
00752       fAppRemote = 0;
00753       // Done
00754       return 1;
00755    } else if (rc == 1) {
00756       // close an existing remote application
00757       TApplication *ap = TApplication::Open(hostdir, 0, 0);
00758       if (ap) {
00759          TApplication::Close(ap);
00760          delete ap;
00761       }
00762    }
00763    // Attach or start a remote application
00764    if (user.Length() > 0)
00765       hostdir.Insert(0,Form("%s@", user.Data()));
00766    const char *sc = (script.Length() > 0) ? script.Data() : 0;
00767    TApplication *ap = TApplication::Open(hostdir, dbg, sc);
00768    if (ap) {
00769       fAppRemote = ap;
00770    }
00771 
00772    // Done
00773    return 1;
00774 }
00775 
00776 //______________________________________________________________________________
00777 Long_t TApplication::ProcessLine(const char *line, Bool_t sync, Int_t *err)
00778 {
00779    // Process a single command line, either a C++ statement or an interpreter
00780    // command starting with a ".".
00781    // Return the return value of the command casted to a long.
00782 
00783    if (!line || !*line) return 0;
00784 
00785    // If we are asked to go remote do it
00786    if (!strncmp(line, ".R", 2)) {
00787       Int_t n = 2;
00788       while (*(line+n) == ' ')
00789          n++;
00790       return ProcessRemote(line+n, err);
00791    }
00792 
00793    // Redirect, if requested
00794    if (fAppRemote && TestBit(kProcessRemotely)) {
00795       ResetBit(kProcessRemotely);
00796       return fAppRemote->ProcessLine(line, err);
00797    }
00798 
00799    if (!strncasecmp(line, ".qqqqqqq", 7)) {
00800       gSystem->Abort();
00801    } else if (!strncasecmp(line, ".qqqqq", 5)) {
00802       Info("ProcessLine", "Bye... (try '.qqqqqqq' if still running)");
00803       gSystem->Exit(1);
00804    } else if (!strncasecmp(line, ".exit", 4) || !strncasecmp(line, ".quit", 2)) {
00805       gInterpreter->ResetGlobals();
00806       Terminate(0);
00807       return 0;
00808    }
00809 
00810    if (!strncmp(line, "?", 1)) {
00811       Help(line);
00812       return 1;
00813    }
00814 
00815    if (!strncmp(line, ".pwd", 4)) {
00816       if (gDirectory)
00817          Printf("Current directory: %s", gDirectory->GetPath());
00818       if (gPad)
00819          Printf("Current pad:       %s", gPad->GetName());
00820       if (gStyle)
00821          Printf("Current style:     %s", gStyle->GetName());
00822       return 1;
00823    }
00824 
00825    if (!strncmp(line, ".ls", 3)) {
00826       const char *opt = 0;
00827       if (line[3]) opt = &line[3];
00828       if (gDirectory) gDirectory->ls(opt);
00829       return 1;
00830    }
00831 
00832    if (!strncmp(line, ".which", 6)) {
00833       char *fn  = Strip(line+7);
00834       char *s   = strtok(fn, "+(");
00835       char *mac = gSystem->Which(TROOT::GetMacroPath(), s, kReadPermission);
00836       if (!mac)
00837          Printf("No macro %s in path %s", s, TROOT::GetMacroPath());
00838       else
00839          Printf("%s", mac);
00840       delete [] fn;
00841       delete [] mac;
00842       return mac ? 1 : 0;
00843    }
00844 
00845    if (!strncmp(line, ".L", 2) || !strncmp(line, ".U", 2)) {
00846       TString aclicMode;
00847       TString arguments;
00848       TString io;
00849       TString fname = gSystem->SplitAclicMode(line+3, aclicMode, arguments, io);
00850 
00851       char *mac = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
00852       if (arguments.Length()) {
00853          Warning("ProcessLine", "argument(s) \"%s\" ignored with .%c", arguments.Data(),
00854                  line[1]);
00855       }
00856       Long_t retval = 0;
00857       if (!mac)
00858          Error("ProcessLine", "macro %s not found in path %s", fname.Data(),
00859                TROOT::GetMacroPath());
00860       else {
00861          TString cmd(line+1);
00862          Ssiz_t posSpace = cmd.Index(' ');
00863          if (posSpace == -1) cmd.Remove(1);
00864          else cmd.Remove(posSpace);
00865          static TString tempbuf;
00866          if (sync) {
00867             tempbuf.Form(".%s %s%s%s", cmd.Data(), mac, aclicMode.Data(),io.Data());
00868             retval = gInterpreter->ProcessLineSynch(tempbuf,
00869                                                    (TInterpreter::EErrorCode*)err);
00870          } else {
00871             tempbuf.Form(".%s %s%s%s", cmd.Data(), mac, aclicMode.Data(),io.Data());
00872             retval = gInterpreter->ProcessLine(tempbuf,
00873                                               (TInterpreter::EErrorCode*)err);
00874          }
00875       }
00876 
00877       delete [] mac;
00878 
00879       InitializeGraphics();
00880 
00881       return retval;
00882    }
00883 
00884    if (!strncmp(line, ".X", 2) || !strncmp(line, ".x", 2)) {
00885       return ProcessFile(line+3, err, line[2] == 'k');
00886    }
00887 
00888    if (!strcmp(line, ".reset")) {
00889       // Do nothing, .reset disabled in CINT because too many side effects
00890       Printf("*** .reset not allowed, please use gROOT->Reset() ***");
00891       return 0;
00892 
00893 #if 0
00894       // delete the ROOT dictionary since CINT will destroy all objects
00895       // referenced by the dictionary classes (TClass et. al.)
00896       gROOT->GetListOfClasses()->Delete();
00897       // fall through
00898 #endif
00899    }
00900 
00901    if (sync)
00902       return gInterpreter->ProcessLineSynch(line, (TInterpreter::EErrorCode*)err);
00903    else
00904       return gInterpreter->ProcessLine(line, (TInterpreter::EErrorCode*)err);
00905 }
00906 
00907 //______________________________________________________________________________
00908 Long_t TApplication::ProcessFile(const char *file, Int_t *error, Bool_t keep)
00909 {
00910    // Process a file containing a C++ macro.
00911 
00912    return ExecuteFile(file, error, keep);
00913 }
00914 
00915 //______________________________________________________________________________
00916 Long_t TApplication::ExecuteFile(const char *file, Int_t *error, Bool_t keep)
00917 {
00918    // Execute a file containing a C++ macro (static method). Can be used
00919    // while TApplication is not yet created.
00920 
00921    static const Int_t kBufSize = 1024;
00922 
00923    if (!file || !*file) return 0;
00924 
00925    TString aclicMode;
00926    TString arguments;
00927    TString io;
00928    TString fname = gSystem->SplitAclicMode(file, aclicMode, arguments, io);
00929 
00930    char *exnam = gSystem->Which(TROOT::GetMacroPath(), fname, kReadPermission);
00931    if (!exnam) {
00932       ::Error("TApplication::ExecuteFile", "macro %s not found in path %s", fname.Data(),
00933               TROOT::GetMacroPath());
00934       delete [] exnam;
00935       return 0;
00936    }
00937 
00938    ::ifstream macro(exnam, ios::in);
00939    if (!macro.good()) {
00940       ::Error("TApplication::ExecuteFile", "%s no such file", exnam);
00941       delete [] exnam;
00942       return 0;
00943    }
00944 
00945    char currentline[kBufSize];
00946    char dummyline[kBufSize];
00947    int tempfile = 0;
00948    int comment  = 0;
00949    int ifndefc  = 0;
00950    int ifdef    = 0;
00951    char *s      = 0;
00952    Bool_t execute = kFALSE;
00953    Long_t retval = 0;
00954 
00955    while (1) {
00956       bool res = macro.getline(currentline, kBufSize);
00957       if (macro.eof()) break;
00958       if (!res) {
00959          // Probably only read kBufSize, let's ignore the remainder of
00960          // the line.
00961          macro.clear();
00962          while (!macro.getline(dummyline, kBufSize) && !macro.eof()) {
00963             macro.clear();
00964          }
00965       }
00966       s = currentline;
00967       while (s && (*s == ' ' || *s == '\t')) s++;   // strip-off leading blanks
00968 
00969       // very simple minded pre-processor parsing, only works in case macro file
00970       // starts with "#ifndef __CINT__". In that case everything till next
00971       // "#else" or "#endif" will be skipped.
00972       if (*s == '#') {
00973          char *cs = Compress(currentline);
00974          if (strstr(cs, "#ifndef__CINT__") ||
00975              strstr(cs, "#if!defined(__CINT__)"))
00976             ifndefc = 1;
00977          else if (ifndefc && (strstr(cs, "#ifdef") || strstr(cs, "#ifndef") ||
00978                   strstr(cs, "#ifdefined") || strstr(cs, "#if!defined")))
00979             ifdef++;
00980          else if (ifndefc && strstr(cs, "#endif")) {
00981             if (ifdef)
00982                ifdef--;
00983             else
00984                ifndefc = 0;
00985          } else if (ifndefc && !ifdef && strstr(cs, "#else"))
00986             ifndefc = 0;
00987          delete [] cs;
00988       }
00989       if (!*s || *s == '#' || ifndefc || !strncmp(s, "//", 2)) continue;
00990 
00991       if (!comment && (!strncmp(s, ".X", 2) || !strncmp(s, ".x", 2))) {
00992          retval = ExecuteFile(s+3);
00993          execute = kTRUE;
00994          continue;
00995       }
00996 
00997       if (!strncmp(s, "/*", 2)) comment = 1;
00998       if (comment) {
00999          // handle slightly more complex cases like: /*  */  /*
01000 again:
01001          s = strstr(s, "*/");
01002          if (s) {
01003             comment = 0;
01004             s += 2;
01005 
01006             while (s && (*s == ' ' || *s == '\t')) s++; // strip-off leading blanks
01007             if (!*s) continue;
01008             if (!strncmp(s, "//", 2)) continue;
01009             if (!strncmp(s, "/*", 2)) {
01010                comment = 1;
01011                goto again;
01012             }
01013          }
01014       }
01015       if (!comment && *s == '{') tempfile = 1;
01016       if (!comment) break;
01017    }
01018    macro.close();
01019 
01020    if (!execute) {
01021       TString exname = exnam;
01022       if (!tempfile) {
01023          // We have a script that does NOT contain an unamed macro,
01024          // so we can call the script compiler on it.
01025          exname += aclicMode;
01026       }
01027       exname += arguments;
01028       exname += io;
01029 
01030       static TString tempbuf;
01031       if (tempfile) {
01032          tempbuf.Form(".x %s", exname.Data());
01033       } else {
01034          tempbuf.Form(".X%s %s", keep ? "k" : " ", exname.Data());
01035       }
01036       retval = gInterpreter->ProcessLineSynch(tempbuf,(TInterpreter::EErrorCode*)error);
01037    }
01038 
01039    delete [] exnam;
01040    return retval;
01041 }
01042 
01043 //______________________________________________________________________________
01044 void TApplication::Run(Bool_t retrn)
01045 {
01046    // Main application eventloop. Calls system dependent eventloop via gSystem.
01047 
01048    SetReturnFromRun(retrn);
01049 
01050    fIsRunning = kTRUE;
01051 
01052    gSystem->Run();
01053    fIsRunning = kFALSE;
01054 }
01055 
01056 //______________________________________________________________________________
01057 void TApplication::SetIdleTimer(UInt_t idleTimeInSec, const char *command)
01058 {
01059    // Set the command to be executed after the system has been idle for
01060    // idleTimeInSec seconds. Normally called via TROOT::Idle(...).
01061 
01062    if (fIdleTimer) RemoveIdleTimer();
01063    fIdleCommand = command;
01064    fIdleTimer = new TIdleTimer(idleTimeInSec*1000);
01065    gSystem->AddTimer(fIdleTimer);
01066 }
01067 
01068 //______________________________________________________________________________
01069 void TApplication::RemoveIdleTimer()
01070 {
01071    // Remove idle timer. Normally called via TROOT::Idle(0).
01072 
01073    if (fIdleTimer) {
01074       // timers are removed from the gSystem timer list by their dtor
01075       SafeDelete(fIdleTimer);
01076    }
01077 }
01078 
01079 //______________________________________________________________________________
01080 void TApplication::StartIdleing()
01081 {
01082    // Called when system starts idleing.
01083 
01084    if (fIdleTimer) {
01085       fIdleTimer->Reset();
01086       gSystem->AddTimer(fIdleTimer);
01087    }
01088 }
01089 
01090 //______________________________________________________________________________
01091 void TApplication::StopIdleing()
01092 {
01093    // Called when system stops idleing.
01094 
01095    if (fIdleTimer)
01096       gSystem->RemoveTimer(fIdleTimer);
01097 }
01098 
01099 //______________________________________________________________________________
01100 void TApplication::Terminate(Int_t status)
01101 {
01102    // Terminate the application by call TSystem::Exit() unless application has
01103    // been told to return from Run(), by a call to SetReturnFromRun().
01104 
01105    //close TMemStat
01106    if (fUseMemstat) {
01107       ProcessLine("TMemStat::Close()");
01108       fUseMemstat = kFALSE;
01109    }
01110 
01111    Emit("Terminate(Int_t)", status);
01112 
01113    if (fReturnFromRun)
01114       gSystem->ExitLoop();
01115    else
01116       gSystem->Exit(status);
01117 }
01118 
01119 //______________________________________________________________________________
01120 void TApplication::LineProcessed(const char *line)
01121 {
01122    // Emit signal when a line has been processed.
01123 
01124    Emit("LineProcessed(const char*)", line);
01125 }
01126 
01127 //______________________________________________________________________________
01128 void TApplication::KeyPressed(Int_t key)
01129 {
01130    // Emit signal when console keyboard key was pressed.
01131 
01132    Emit("KeyPressed(Int_t)", key);
01133 }
01134 
01135 //______________________________________________________________________________
01136 void TApplication::ReturnPressed(char *text )
01137 {
01138    // Emit signal when return key was pressed.
01139 
01140    Emit("ReturnPressed(char*)", text);
01141 }
01142 
01143 //______________________________________________________________________________
01144 void TApplication::SetEchoMode(Bool_t)
01145 {
01146    // Set console echo mode:
01147    //
01148    //  mode = kTRUE  - echo input symbols
01149    //  mode = kFALSE - noecho input symbols
01150 }
01151 
01152 //______________________________________________________________________________
01153 void TApplication::CreateApplication()
01154 {
01155    // Static function used to create a default application environment.
01156 
01157    if (!gApplication) {
01158       char *a = StrDup("RootApp");
01159       char *b = StrDup("-b");
01160       char *argv[2];
01161       Int_t argc = 2;
01162       argv[0] = a;
01163       argv[1] = b;
01164       new TApplication("RootApp", &argc, argv, 0, 0);
01165       if (gDebug > 0)
01166          Printf("<TApplication::CreateApplication>: "
01167                 "created default TApplication");
01168       delete [] a; delete [] b;
01169       gApplication->SetBit(kDefaultApplication);
01170    }
01171 }
01172 
01173 //______________________________________________________________________________
01174 TApplication *TApplication::Open(const char *url,
01175                                   Int_t debug, const char *script)
01176 {
01177    // Static function used to attach to an existing remote application
01178    // or to start one.
01179 
01180    TApplication *ap = 0;
01181    TUrl nu(url);
01182    Int_t nnew = 0;
01183 
01184    // Look among the existing ones
01185    if (fgApplications) {
01186       TIter nxa(fgApplications);
01187       while ((ap = (TApplication *) nxa())) {
01188          TString apn(ap->ApplicationName());
01189          if (apn == url) {
01190             // Found matching application
01191             return ap;
01192          } else {
01193             // Check if same machine and user
01194             TUrl au(apn);
01195             if (strlen(au.GetUser()) > 0 && strlen(nu.GetUser()) > 0 &&
01196                 !strcmp(au.GetUser(), nu.GetUser())) {
01197                if (!strncmp(au.GetHost(), nu.GetHost(), strlen(nu.GetHost())))
01198                   // New session on a known machine
01199                   nnew++;
01200             }
01201          }
01202       }
01203    } else {
01204       ::Error("TApplication::Open", "list of applications undefined - protocol error");
01205       return ap;
01206    }
01207 
01208    // If new session on a known machine pass the number as option
01209    if (nnew > 0) {
01210       nnew++;
01211       nu.SetOptions(Form("%d", nnew));
01212    }
01213 
01214    // Instantiate the TApplication object to be run
01215    TPluginHandler *h = 0;
01216    if ((h = gROOT->GetPluginManager()->FindHandler("TApplication","remote"))) {
01217       if (h->LoadPlugin() == 0) {
01218          ap = (TApplication *) h->ExecPlugin(3, nu.GetUrl(), debug, script);
01219       } else {
01220          ::Error("TApplication::Open", "failed to load plugin for TApplicationRemote");
01221       }
01222    } else {
01223       ::Error("TApplication::Open", "failed to find plugin for TApplicationRemote");
01224    }
01225 
01226    // Add to the list
01227    if (ap && !(ap->TestBit(kInvalidObject))) {
01228       fgApplications->Add(ap);
01229       gROOT->GetListOfBrowsables()->Add(ap, ap->ApplicationName());
01230       TIter next(gROOT->GetListOfBrowsers());
01231       TBrowser *b;
01232       while ((b = (TBrowser*) next()))
01233          b->Add(ap, ap->ApplicationName());
01234       gROOT->RefreshBrowsers();
01235    } else {
01236       SafeDelete(ap);
01237       ::Error("TApplication::Open",
01238               "TApplicationRemote for %s could not be instantiated", url);
01239    }
01240 
01241    // Done
01242    return ap;
01243 }
01244 
01245 //______________________________________________________________________________
01246 void TApplication::Close(TApplication *app)
01247 {
01248    // Static function used to close a remote application
01249 
01250    if (app) {
01251       app->Terminate(0);
01252       fgApplications->Remove(app);
01253       gROOT->GetListOfBrowsables()->RecursiveRemove(app);
01254       TIter next(gROOT->GetListOfBrowsers());
01255       TBrowser *b;
01256       while ((b = (TBrowser*) next()))
01257          b->RecursiveRemove(app);
01258       gROOT->RefreshBrowsers();
01259    }
01260 }
01261 
01262 //______________________________________________________________________________
01263 void TApplication::ls(Option_t *opt) const
01264 {
01265    // Show available sessions
01266 
01267    if (fgApplications) {
01268       TIter nxa(fgApplications);
01269       TApplication *a = 0;
01270       while ((a = (TApplication *) nxa())) {
01271          a->Print(opt);
01272       }
01273    } else {
01274       Print(opt);
01275    }
01276 }
01277 
01278 //______________________________________________________________________________
01279 TList *TApplication::GetApplications()
01280 {
01281    // Static method returning the list of available applications
01282 
01283    return fgApplications;
01284 }

Generated on Tue Jul 5 14:11:18 2011 for ROOT_528-00b_version by  doxygen 1.5.1