// @(#)root/base:$Name:  $:$Id: TROOT.cxx,v 1.126 2004/06/22 18:47:16 brun Exp $
// Author: Rene Brun   08/12/94

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

////////////////////////////////////////////////////////////////////////////////
//                R O O T top level object description
//
//    The TROOT object is the entry point to the ROOT system.
//    The single instance of TROOT is accessible via the global gROOT.
//    Using the gROOT pointer one has access to basically every object
//    created in a ROOT based program. The TROOT object is essentially a
//    container of several lists pointing to the main ROOT objects.
//
//    The following lists are accessible from gROOT object:
//       gROOT->GetListOfClasses
//       gROOT->GetListOfColors
//       gROOT->GetListOfTypes
//       gROOT->GetListOfGlobals
//       gROOT->GetListOfGlobalFunctions
//       gROOT->GetListOfFiles
//       gROOT->GetListOfMappedFiles
//       gROOT->GetListOfSockets
//       gROOT->GetListOfSecContexts
//       gROOT->GetListOfCanvases
//       gROOT->GetListOfStyles
//       gROOT->GetListOfFunctions
//       gROOT->GetListOfSpecials (for example graphical cuts)
//       gROOT->GetListOfGeometries
//       gROOT->GetListOfBrowsers
//       gROOT->GetListOfCleanups
//       gROOT->GetListOfMessageHandlers
//
//   The TROOT class provides also many useful services:
//     - Get pointer to an object in any of the lists above
//     - Time utilities TROOT::Time
//
//   The ROOT object must be created as a static object. An example
//   of a main program creating an interactive version is shown below:
//
//---------------------Example of a main program--------------------------------
//
//       #include "TRint.h"
//
//       int main(int argc, char **argv)
//       {
//          TRint *theApp = new TRint("ROOT example", &argc, argv);
//
//          // Init Intrinsics, build all windows, and enter event loop
//          theApp->Run();
//
//          return(0);
//       }
//-----------------------End of Main program--------------------------------
////////////////////////////////////////////////////////////////////////////////

#include "config.h"

#include <string>
#include <map>
#include <stdlib.h>
#ifdef WIN32
#include <io.h>
#endif

#include "Riostream.h"
#include "Gtypes.h"
#include "TROOT.h"
#include "TClass.h"
#include "TClassEdit.h"
#include "TClassGenerator.h"
#include "TDataType.h"
#include "TFile.h"
#include "TMapFile.h"
#include "TDatime.h"
#include "TStyle.h"
#include "TObjectTable.h"
#include "TClassTable.h"
#include "TSystem.h"
#include "THashList.h"
#include "TObjArray.h"
#include "TEnv.h"
#include "TColor.h"
#include "TGlobal.h"
#include "TFunction.h"
#include "TVirtualPad.h"
#include "TBrowser.h"
#include "TSystemDirectory.h"
#include "TApplication.h"
#include "TCint.h"
#include "TGuiFactory.h"
#include "TRandom.h"
#include "TMessageHandler.h"
#include "TVirtualGL.h"
#include "TFolder.h"
#include "TQObject.h"
#include "TProcessUUID.h"
#include "TPluginManager.h"
#include "TMap.h"
#include "TObjString.h"
#include "TVirtualUtilHist.h"
#include "TAuthenticate.h"

#include <string>
namespace std {} using namespace std;

#if defined(R__UNIX)
#include "TUnixSystem.h"
#elif defined(R__MAC)
#include "TMacSystem.h"
#elif defined(R__WIN32)
#include "TWinNTSystem.h"
#elif defined(R__VMS)
#include "TVmsSystem.h"
#endif

//-------- Names of next three routines are a small homage to CMZ --------------
//______________________________________________________________________________
static Int_t IVERSQ()
{
   // Return version id as an integer, i.e. "2.22/04" -> 22204.

   Int_t maj, min, cycle;
   sscanf(ROOT_RELEASE, "%d.%d/%d", &maj, &min, &cycle);
   return 10000*maj + 100*min + cycle;
}

//______________________________________________________________________________
static Int_t IDATQQ()
{
   // Return built date as integer, i.e. "Apr 28 2000" -> 20000428.

   static const char *months[] = {"Jan","Feb","Mar","Apr","May",
                                  "Jun","Jul","Aug","Sep","Oct",
                                  "Nov","Dec"};

   char  sm[12];
   Int_t yy, mm=0, dd;
   sscanf(__DATE__, "%s %d %d", sm, &dd, &yy);
   for (int i = 0; i < 12; i++)
      if (!strncmp(sm, months[i], 3)) {
         mm = i+1;
         break;
      }
   return 10000*yy + 100*mm + dd;
}

//______________________________________________________________________________
static Int_t ITIMQQ()
{
   // Return built time as integer (with min precision), i.e.
   // "17:32:37" -> 1732.

   Int_t hh, mm, ss;
   sscanf(__TIME__, "%d:%d:%d", &hh, &mm, &ss);
   return 100*hh + mm;
}
//------------------------------------------------------------------------------


//______________________________________________________________________________
static void CleanUpROOTAtExit()
{
   // Clean up at program termination before global objects go out of scope.

   if (gROOT) {
      if (gROOT->GetListOfFiles())
         gROOT->GetListOfFiles()->Delete();
      if (gROOT->GetListOfSockets())
         gROOT->GetListOfSockets()->Delete();
      if (gROOT->GetListOfMappedFiles())
         gROOT->GetListOfMappedFiles()->Delete("slow");
   }
}

//______________________________________________________________________________
namespace ROOT {
#define R__USE_STD_MAP
   class TMapTypeToTClass {
#if defined R__USE_STD_MAP
     // This wrapper class allow to avoid putting #include <map> in the
     // TROOT.h header file.
   public:
#ifdef R__GLOBALSTL
      typedef map<string,TClass*>                 IdMap_t;
#else
      typedef std::map<std::string,TClass*>       IdMap_t;
#endif
      typedef IdMap_t::key_type                   key_type;
      typedef IdMap_t::const_iterator             const_iterator;
      typedef IdMap_t::size_type                  size_type;
#ifdef R__WIN32
     // Window's std::map does NOT defined mapped_type
      typedef TClass*                             mapped_type;
#else
      typedef IdMap_t::mapped_type                mapped_type;
#endif

   private:
      IdMap_t fMap;

   public:
      void Add(const key_type &key, mapped_type &obj) {
         fMap[key] = obj;
      }
      mapped_type Find(const key_type &key) const {
         IdMap_t::const_iterator iter = fMap.find(key);
         mapped_type cl = 0;
         if (iter != fMap.end()) cl = iter->second;
         return cl;
      }
      void Remove(const key_type &key) { fMap.erase(key); }
#else
   private:
      TMap fMap;

   public:
      void Add(const char *key, TClass *&obj) {
         TObjString *realkey = new TObjString(key);
         fMap.Add(realkey, obj);
      }
      TClass* Find(const char *key) const {
         const TPair *a = (const TPair *)fMap.FindObject(key);
         if (a) return (TClass*) a->Value();
         return 0;
      }
      void Remove(const char *key) {
         TObjString realkey(key);
         TObject *actual = fMap.Remove(&realkey);
         delete actual;
      }
#endif
   };
}


Int_t         TROOT::fgDirLevel = 0;
Bool_t        TROOT::fgRootInit = kFALSE;
Bool_t        TROOT::fgMemCheck = kFALSE;
VoidFuncPtr_t TROOT::fgMakeDefCanvas = 0;

// This local static object initializes the ROOT system
namespace ROOT {
   TROOT *GetROOT() {
      static TROOT root("root", "The ROOT of EVERYTHING");
      return &root;
   }
   TString &GetMacroPath() {
      static TString macroPath;
      return macroPath;
   }
}

TROOT      *gROOT = ROOT::GetROOT();     // The ROOT of EVERYTHING
TRandom    *gRandom;                     // Global pointer to random generator

// Global debug flag (set to > 0 to get debug output).
// Can be set either via the interpreter (gDebug is exported to CINT),
// via the rootrc resouce "Root.Debug", via the shell environment variable
// ROOTDEBUG, or via the debugger.
Int_t       gDebug;





ClassImp(TROOT)

//______________________________________________________________________________
TROOT::TROOT() : TDirectory()
{
   // Default ctor.
}

//______________________________________________________________________________
TROOT::TROOT(const char *name, const char *title, VoidFuncPtr_t *initfunc)
           : TDirectory()
{
   // Initialize the ROOT system. The creation of the TROOT object initializes
   // the ROOT system. It must be the first ROOT related action that is
   // performed by a program. The TROOT object must be created on the stack
   // (can not be called via new since "operator new" is protected). The
   // TROOT object is either created as a global object (outside the main()
   // program), or it is one of the first objects created in main().
   // Make sure that the TROOT object stays in scope for as long as ROOT
   // related actions are performed. TROOT is a so called singleton so
   // only one instance of it can be created. The single TROOT object can
   // always be accessed via the global pointer gROOT.
   // The name and title arguments can be used to identify the running
   // application. The initfunc argument can contain an array of
   // function pointers (last element must be 0). These functions are
   // executed at the end of the constructor. This way one can easily
   // extend the ROOT system without adding permanent dependencies
   // (e.g. the graphics system is initialized via such a function).

   if (fgRootInit) {
      //Warning("TROOT", "only one instance of TROOT allowed");
      return;
   }

   gROOT      = this;
   gDirectory = 0;
   SetName(name);
   SetTitle(title);
   TDirectory::Build();

   // will be used by global "operator delete" so make sure it is set
   // before anything is deleted
   fMappedFiles = 0;

   // create already here, but only initialize it after gEnv has been created
   fPluginManager = new TPluginManager;

   // Initialize Operating System interface
   InitSystem();

   // Initialize interface to CINT C++ interpreter
   fVersionInt      = 0;  // check in TROOT dtor in case TCint fails
   fClasses         = 0;  // might be checked via TCint ctor
   fInterpreter     = new TCint("C/C++", "CINT C/C++ Interpreter");

   fConfigOptions   = R__CONFIGUREOPTIONS;
   fVersion         = ROOT_RELEASE;
   fVersionInt      = IVERSQ();
   fVersionDate     = IDATQQ();
   fVersionTime     = ITIMQQ();

   fClasses         = new THashList(800,3);
   fIdMap           = new IdMap_t;
   fStreamerInfo    = new TObjArray(100);
   fClassGenerators = new TList;

   // initialize plugin manager early
   fPluginManager->LoadHandlersFromEnv(gEnv);

   // Add the root include directory to list searched by default by
   // the interpreter (should this be here or somewhere else?)
#ifndef ROOTINCDIR
   TString include = gSystem->Getenv("ROOTSYS");
   include.Append("/include");
   fInterpreter->AddIncludePath(include);
#else
   fInterpreter->AddIncludePath(ROOTINCDIR);
#endif

   TSystemDirectory *workdir = new TSystemDirectory("workdir",gSystem->WorkingDirectory());

   fTimer       = 0;
   fApplication = 0;
   fColors      = new TObjArray(1000);
   fTypes       = 0;
   fGlobals     = 0;
   fGlobalFunctions = 0;
   fList        = new THashList(1000,3);
   fFiles       = new TList;
   fMappedFiles = new TList;
   fSockets     = new TList;
   fCanvases    = new TList;
   fStyles      = new TList;
   fFunctions   = new TList;
   fTasks       = new TList;
   fGeometries  = new TList;
   fBrowsers    = new TList;
   fSpecials    = new TList;
   fBrowsables  = new TList;
   fCleanups    = new TList;
   fMessageHandlers = new TList;
   fSecContexts = new TList;

   TProcessID::AddProcessID();
   fUUIDs = new TProcessUUID();

   fRootFolder = new TFolder();
   fRootFolder->SetName("root");
   fRootFolder->SetTitle("root of all folders");
   fRootFolder->AddFolder("Classes",   "List of Active Classes",fClasses);
   fRootFolder->AddFolder("Colors",    "List of Active Colors",fColors);
   fRootFolder->AddFolder("MapFiles",  "List of MapFiles",fMappedFiles);
   fRootFolder->AddFolder("Sockets",   "List of Socket Connections",fSockets);
   fRootFolder->AddFolder("Canvases",  "List of Canvases",fCanvases);
   fRootFolder->AddFolder("Styles",    "List of Styles",fStyles);
   fRootFolder->AddFolder("Functions", "List of Functions",fFunctions);
   fRootFolder->AddFolder("Tasks",     "List of Tasks",fTasks);
   fRootFolder->AddFolder("Geometries","List of Geometries",fGeometries);
   fRootFolder->AddFolder("Browsers",  "List of Browsers",fBrowsers);
   fRootFolder->AddFolder("Specials",  "List of Special Objects",fSpecials);
   fRootFolder->AddFolder("Handlers",  "List of Message Handlers",fMessageHandlers);
   fRootFolder->AddFolder("Cleanups",  "List of RecursiveRemove Collections",fCleanups);
   fRootFolder->AddFolder("StreamerInfo","List of Active StreamerInfo Classes",fStreamerInfo);
   fRootFolder->AddFolder("SecContexts","List of Security Contexts",fSecContexts);
   fRootFolder->AddFolder("ROOT Memory","List of Objects in the gROOT Directory",fList);
   fRootFolder->AddFolder("ROOT Files","List of Connected ROOT Files",fFiles);

   // by default, add the list of files, tasks, canvases and browsers in the Cleanups list
   fCleanups->Add(fCanvases); fCanvases->SetBit(kMustCleanup);
   fCleanups->Add(fBrowsers); fBrowsers->SetBit(kMustCleanup);
   fCleanups->Add(fTasks);    fTasks->SetBit(kMustCleanup);
   fCleanups->Add(fFiles);    fFiles->SetBit(kMustCleanup);

   fForceStyle    = kFALSE;
   fFromPopUp     = kFALSE;
   fReadingObject = kFALSE;
   fInterrupt     = kFALSE;
   fMustClean     = kTRUE;
   fPrimitive     = 0;
   fSelectPad     = 0;
   fEditorMode    = 0;
   fDefCanvasName = "c1";
   fEditHistograms= kFALSE;
   fLineIsProcessing = 1;   // This prevents WIN32 "Windows" thread to pick ROOT objects with mouse
   gDirectory     = this;
   gPad           = 0;
   gRandom        = new TRandom;

   //set name of graphical cut class for the graphics editor
   //cannot call SetCutClassName at this point because the TClass of TCutG
   //is not yet build
   fCutClassName = "TCutG";

   // Create a default MessageHandler
   new TMessageHandler((TClass*)0);

   // Create some styles
   gStyle = 0;
   TStyle::BuildStyles();
   SetStyle("Default");

   // Setup default (batch) graphics and GUI environment
   gBatchGuiFactory = new TGuiFactory;
   gGuiFactory      = gBatchGuiFactory;
   gGXBatch         = new TVirtualX("Batch", "ROOT Interface to batch graphics");
   gVirtualX        = gGXBatch;
   gVirtualGL       = new TVirtualGL;

#ifdef R__WIN32
   fBatch = kFALSE;
#else
   if (gSystem->Getenv("DISPLAY"))
      fBatch = kFALSE;
   else
      fBatch = kTRUE;
#endif

   int i = 0;
   while (initfunc && initfunc[i]) {
      (initfunc[i])();
      fBatch = kFALSE;  // put system in graphics mode (backward compatible)
      i++;
   }

   // Load and init threads library
   InitThreads();

   // Load RQ_OBJECT.h in interpreter (allows signal/slot programming, like Qt)
   TQObject::LoadRQ_OBJECT();

   // Set initial/default list of browsable objects
   fBrowsables->Add(fRootFolder, "root");
   fBrowsables->Add(workdir, gSystem->WorkingDirectory());
   fBrowsables->Add(fFiles, "ROOT Files");

   atexit(CleanUpROOTAtExit);

   fgRootInit = kTRUE;
}

//______________________________________________________________________________
TROOT::~TROOT()
{
   // Clean up and free resources used by ROOT (files, network sockets,
   // shared memory segments, etc.).

   if (gROOT == this) {

      fgRootInit = kFALSE;

      // Return when error occured in TCint, i.e. when setup file(s) are
      // out of date
      if (!fVersionInt) return;

      // Remote cleanup of authentication stuff
      TAuthenticate::CleanupSecContextAll();

      // ATTENTION!!! Order is important!

//      fSpecials->Delete();   SafeDelete(fSpecials);    // delete special objects : PostScript, Minuit, Html
#if defined(WIN32) && !defined(GDK_WIN32)
      // Under Windows, one has to restore the color palettes created
      // by individual canvases
      fCanvases->Delete();    SafeDelete(fCanvases);    // first close canvases
#endif
      fFiles->Delete("slow"); SafeDelete(fFiles);       // and files
      fSockets->Delete();     SafeDelete(fSockets);     // and sockets
      fSecContexts->Delete(); SafeDelete(fSecContexts); // and security contexts
      fMappedFiles->Delete("slow");                     // and mapped files
      delete fUUIDs;
      TProcessID::Cleanup();                            // and list of ProcessIDs
      TSeqCollection *tl = fMappedFiles; fMappedFiles = 0; delete tl;

//      fProcesses->Delete();  SafeDelete(fProcesses);   // then terminate processes
//      fFunctions->Delete();  SafeDelete(fFunctions);   // etc..
//      fListHead->Delete();   SafeDelete(fListHead);    // delete objects in current directory
//      fColors->Delete();     SafeDelete(fColors);
//      fStyles->Delete();     SafeDelete(fStyles);
//      fGeometries->Delete(); SafeDelete(fGeometries);
//      fBrowsers->Delete();   SafeDelete(fBrowsers);
//      fBrowsables->Delete(); SafeDelete(fBrowsables);
//      fMessageHandlers->Delete(); SafeDelete(fMessageHandlers);
//      if (fTypes) fTypes->Delete();
//      SafeDelete(fTypes);
//      if (fGlobals) fGlobals->Delete();
//      SafeDelete(fGlobals);
//      if (fGlobalFunctions) fGlobalFunctions->Delete();
//      SafeDelete(fGlobalFunctions);
//      fClasses->Delete();    SafeDelete(fClasses);     // TClass'es must be deleted last

      // Remove shared libraries produced by the TSystem::CompileMacro() call
      gSystem->CleanCompiledMacros();

      // Cleanup system class
      delete gSystem;

      // Problem deleting the interpreter. Want's to delete objects already
      // deleted in the dtor's above. Crash.
      // It should only close the files and NOT delete.
      SafeDelete(fInterpreter);

      // Prints memory stats
      TStorage::PrintStatistics();

      gROOT = 0;
   }
}

//______________________________________________________________________________
void TROOT::AddClass(TClass *cl)
{
   // Add a class to the list and map of classes.

   if (!cl) return;
   GetListOfClasses()->Add(cl);
   if (cl->GetTypeInfo()) {
      fIdMap->Add(cl->GetTypeInfo()->name(),cl);
   }
}

//______________________________________________________________________________
void TROOT::AddClassGenerator(TClassGenerator *generator)
{
   // Add a class generator.  This generator will be called by TROOT::GetClass
   // in case its does not find a loaded rootcint dictionary to request the
   // creation of a TClass object.

   if (!generator) return;
   fClassGenerators->Add(generator);
}

//______________________________________________________________________________
void TROOT::Browse(TBrowser *b)
{
   // Add browsable objects to TBrowser.

   TObject *obj;
   TIter next(fBrowsables);

   while ((obj = (TObject *) next())) {
      const char *opt = next.GetOption();
      if (opt && strlen(opt))
         b->Add(obj, opt);
      else
         b->Add(obj, obj->GetName());
   }
}

//______________________________________________________________________________
Bool_t TROOT::ClassSaved(TClass *cl)
{
// return class status bit kClassSaved for class cl
// This function is called by the SavePrimitive functions writing
// the C++ code for an object.

   if (cl == 0) return kFALSE;
   if (cl->TestBit(TClass::kClassSaved)) return kTRUE;
   cl->SetBit(TClass::kClassSaved);
   return kFALSE;
}

//______________________________________________________________________________
TObject *TROOT::FindObject(const TObject *) const
{
// Find an object in one Root folder

   Error("FindObject","Not yet implemented");
   return 0;
}

//______________________________________________________________________________
TObject *TROOT::FindObject(const char *name) const
{
   // Returns address of a ROOT object if it exists
   //
   // This function looks in the following order in the ROOT lists:
   //     - List of files
   //     - List of memory mapped files
   //     - List of functions
   //     - List of geometries
   //     - List of canvases
   //     - List of styles
   //     - List of specials
   //     - List of materials in current geometry
   //     - List of shapes in current geometry
   //     - List of matrices in current geometry
   //     - List of Nodes in current geometry
   //     - Current Directory in memory
   //     - Current Directory on file

   TObject *temp = 0;

   temp   = fFiles->FindObject(name);       if (temp) return temp;
   temp   = fMappedFiles->FindObject(name); if (temp) return temp;
   temp   = fFunctions->FindObject(name);   if (temp) return temp;
   temp   = fGeometries->FindObject(name);  if (temp) return temp;
   temp   = fCanvases->FindObject(name);    if (temp) return temp;
   temp   = fStyles->FindObject(name);      if (temp) return temp;
   temp   = fSpecials->FindObject(name);    if (temp) return temp;
   TIter next(fGeometries);
   TObject *obj;
   while ((obj=next())) {
      temp = obj->FindObject(name);         if (temp) return temp;
   }
   if (gDirectory) temp = gDirectory->Get(name); if (temp) return temp;
   if (gPad) {
      TVirtualPad *canvas = gPad->GetVirtCanvas();
      if (fCanvases->FindObject(canvas)) {  //this check in case call from TCanvas ctor
         temp = canvas->FindObject(name);
         if (!temp && canvas != gPad) temp  = gPad->FindObject(name);
      }
   }
   return temp;
}

//______________________________________________________________________________
TObject *TROOT::FindSpecialObject(const char *name, void *&where)
{
   // Returns address and folder of a ROOT object if it exists
   //
   // This function looks in the following order in the ROOT lists:
   //     - List of files
   //     - List of memory mapped files
   //     - List of functions
   //     - List of geometries
   //     - List of canvases
   //     - List of styles
   //     - List of specials
   //     - List of materials in current geometry
   //     - List of shapes in current geometry
   //     - List of matrices in current geometry
   //     - List of Nodes in current geometry
   //     - Current Directory in memory
   //     - Current Directory on file

   TObject *temp = 0;
   where = 0;

   if (!temp && !strcmp(name, "gPad")) {
      temp = gPad;
      if (gPad) {
         TVirtualPad *canvas = gPad->GetVirtCanvas();
         //this check in case call from TCanvas ctor
         if (fCanvases->FindObject(canvas))
            where = canvas;
      }
   }
   if (!temp && !strcmp(name, "gVirtualX")) {
      return gVirtualX;
   }
   if (!temp && !strcmp(name, "gInterpreter")) {
      return gInterpreter;
   }
   if (!temp) {
      temp  = fFiles->FindObject(name);
      where = fFiles;
   }
   if (!temp) {
      temp  = fMappedFiles->FindObject(name);
      where = fMappedFiles;
   }
   if (!temp) {
      temp  = fFunctions->FindObject(name);
      where = fFunctions;
   }
   if (!temp) {
      temp  = fCanvases->FindObject(name);
      where = fCanvases;
   }
   if (!temp) {
      temp  = fStyles->FindObject(name);
      where = fStyles;
   }
   if (!temp) {
      temp  = fSpecials->FindObject(name);
      where = fSpecials;
   }
   if (!temp) {
      TObject *glast = fGeometries->Last();
      if (glast) {where = glast; temp = glast->FindObject(name);}
   }
   if (!temp && gDirectory) {
      temp  = gDirectory->Get(name);
      where = gDirectory;
   }
   if (!temp && gPad) {
      TVirtualPad *canvas = gPad->GetVirtCanvas();
      if (fCanvases->FindObject(canvas)) {  //this check in case call from TCanvas ctor
         temp  = canvas->FindObject(name);
         where = canvas;
         if (!temp && canvas != gPad) {
            temp  = gPad->FindObject(name);
            where = gPad;
         }
      }
   }
   if (!temp) return 0;
   if (temp->TestBit(kNotDeleted)) return temp;
   return 0;
}

//______________________________________________________________________________
TObject *TROOT::FindObjectAny(const char *name) const
{
   // Return a pointer to the first object with name starting at //root.
   // This function scans the list of all folders.
   // if no object found in folders, it scans the memory list of all files.

   TObject *obj = fRootFolder->FindObjectAny(name);
   if (obj) return obj;
   TFile *f;
   TIter next(fFiles);
   while ((f = (TFile*)next())) {
      obj = f->GetList()->FindObject(name);
      if (obj) return obj;
   }
   return 0;
}

//______________________________________________________________________________
const char *TROOT::FindObjectClassName(const char *name) const
{
   // Returns class name of a ROOT object including CINT globals.

   // Search first in the list of "standard" objects
   TObject *obj = FindObject(name);
   if (obj) return obj->ClassName();

   // Is it a global variable?
   TGlobal *g = GetGlobal(name);
   if (g) return g->GetTypeName();

   return 0;
}

//______________________________________________________________________________
const char *TROOT::FindObjectPathName(const TObject *) const
{
   // Return path name of obj somewhere in the //root/... path.
   // The function returns the first occurence of the object in the list
   // of folders. The returned string points to a static char array in TROOT.
   // If this function is called in a loop or recursively, it is the
   // user's responsability to copy this string in his area.

   Error("FindObjectPathName","Not yet implemented");
   return "??";
}

TClass *TROOT::FindSTLClass(const char *name, Bool_t load) const
{
   // return a TClass object corresponding to 'name' assuming it is an STL container.
   // In particular we looking for possible alternative name (default template
   // parameter, typedefs template arguments, typedefed name).

   TClass *cl = 0;

   // We have not found the STL container yet.
   // First we are going to look for a similar name but different 'default' template
   // parameter (differences due to different STL implementation)

   string defaultname( TClassEdit::ShortType( name, TClassEdit::kDropStlDefault )) ;

   if (defaultname != name) {
      cl = (TClass*)gROOT->GetListOfClasses()->FindObject(defaultname.c_str());
      if (load && !cl) cl = gROOT->LoadClass(defaultname.c_str());
   }

   if (cl==0) {

      // now look for a typedef
      // well for now the typedefing in CINT has some issues
      // for examples if we generated the dictionary for
      //    set<string,someclass> then set<string> is typedef to it (instead of set<string,less<string> >)

      TDataType *objType = gROOT->GetType(name, load);
      if (objType) {
         const char *typedfName = objType->GetTypeName();
         string defaultTypedefName(  TClassEdit::ShortType( typedfName, TClassEdit::kDropStlDefault ) );

         if (typedfName && strcmp(typedfName, name) && defaultTypedefName==name) {
            cl = (TClass*)gROOT->GetListOfClasses()->FindObject(typedfName);
            if (load && !cl) cl = gROOT->LoadClass(typedfName);
         }
      }
   }
   if (cl==0) {
      // Try the alternate name where all the typedefs are resolved:

      const char *altname = gInterpreter->GetInterpreterTypeName(name);
      if (altname && strcmp(altname,name)!=0) {
         cl = gROOT->GetClass(altname,load);
      }
   }
   if (cl==0) {
      // Try with Long64_t instead of long long
      string long64name = TClassEdit::GetLong64_Name( name );
      if ( long64name != name ) return FindSTLClass( long64name.c_str(), load);
   }

   if (load && cl==0) {
      // Create an Emulated class for this container.
      cl = new TClass(name, GetClass("TStreamerInfo")->GetClassVersion(), 0, 0, -1, -1 );
      cl->SetBit(TClass::kIsEmulation);
   }

   return cl;
}

//______________________________________________________________________________
TClass *TROOT::GetClass(const char *name, Bool_t load) const
{
   // Return pointer to class with name.

   if (!name || !strlen(name)) return 0;
   if (!GetListOfClasses())    return 0;

   TString resolvedName;

   TClass *cl = (TClass*)GetListOfClasses()->FindObject(name);

   if (!cl) {
      resolvedName = TClassEdit::ResolveTypedef(name,kTRUE).c_str();
      cl = (TClass*)GetListOfClasses()->FindObject(resolvedName);
   }

   if (cl) {

      if (cl->IsLoaded()) return cl;
      //we may pass here in case of a dummy class created by TStreamerInfo
      load = kTRUE;

      if (TClassEdit::IsSTLCont(name)) {

         const char *altname = gInterpreter->GetInterpreterTypeName(name);
         if (altname && strcmp(altname,name)!=0) {

            TClass *newcl = GetClass(altname,load);

            // since the name are different but we got a TClass, we assume
            // we need to replace and delete this class.
            assert(newcl!=cl);
            cl->ReplaceWith(newcl);
            delete cl;
            return newcl;
         }
      }

   } else {

      if (!TClassEdit::IsSTLCont(name)) {

         // If the name is actually an STL container we prefer the
         // short name rather than the true name (at least) in
         // a first try!

         TDataType *objType = GetType(name, load);
         if (objType) {
            const char *typdfName = objType->GetTypeName();
            if (typdfName && strcmp(typdfName, name)) {
               cl = GetClass(typdfName, load);
               return cl;
            }
         }

      } else {

         cl = FindSTLClass(name,kFALSE);

         if (cl) {
            if (cl->IsLoaded()) return cl;

            //we may pass here in case of a dummy class created by TStreamerInfo
            return gROOT->GetClass(cl->GetName(),kTRUE);
         }

      }

   }

   if (!load) return 0;

   TClass *loadedcl = 0;
   if (cl) loadedcl = LoadClass(cl->GetName());
   else    loadedcl = LoadClass(name);

   if (loadedcl) return loadedcl;

   if (cl) return cl;  // If we found the class but we already have a dummy class use it.

   static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
   if (strcmp(name,full_string_name)==0) { return gROOT->GetClass("string"); }

   if (TClassEdit::IsSTLCont(name)) {

      return FindSTLClass(name,kTRUE);

   }

   if (!strcmp(name, "long long")||!strcmp(name,"unsigned long long"))
      return 0; // reject long longs

   //last attempt. Look in CINT list of all (compiled+interpreted) classes
   if (gInterpreter->CheckClassInfo(name)) {
      TClass *ncl = new TClass(name, 1, 0, 0, -1, -1);
      if (!ncl->IsZombie()) return ncl;
      delete ncl;
   }
   return 0;
}

//______________________________________________________________________________
TClass *TROOT::GetClass(const type_info& typeinfo, Bool_t load) const
{
   // Return pointer to class with name.

   if (!GetListOfClasses())    return 0;

   TClass* cl = fIdMap->Find(typeinfo.name());

   if (cl) {
      if (cl->IsLoaded()) return cl;
      //we may pass here in case of a dummy class created by TStreamerInfo
      load = kTRUE;
   } else {
     // Note we might need support for typedefs and simple types!

     //      TDataType *objType = GetType(name, load);
     //if (objType) {
     //    const char *typdfName = objType->GetTypeName();
     //    if (typdfName && strcmp(typdfName, name)) {
     //       cl = GetClass(typdfName, load);
     //       return cl;
     //    }
     // }
   }

   if (!load) return 0;

   VoidFuncPtr_t dict = TClassTable::GetDict(typeinfo);
   if (dict) {
      (dict)();
      return GetClass(typeinfo);
   }
   if (cl) return cl;

   TIter next(fClassGenerators);
   TClassGenerator *gen;
   while( (gen = (TClassGenerator*) next()) ) {
      cl = gen->GetClass(typeinfo,load);
      if (cl) return cl;
   }

   //last attempt. Look in CINT list of all (compiled+interpreted) classes
   //   if (gInterpreter->CheckClassInfo(name)) {
   //      TClass *ncl = new TClass(name, 1, 0, 0, 0, -1, -1);
   //      if (!ncl->IsZombie()) return ncl;
   //      delete ncl;
   //   }
   return 0;
}

//______________________________________________________________________________
TColor *TROOT::GetColor(Int_t color) const
{
   // Return address of color with index color.

   TObjArray *lcolors = (TObjArray*) GetListOfColors();
   if (color < 0 || color >= lcolors->GetSize()) return 0;
   TColor *col = (TColor*)lcolors->At(color);
   if (col && col->GetNumber() == color) return col;
   TIter   next(lcolors);
   while ((col = (TColor *) next()))
      if (col->GetNumber() == color) return col;

   return 0;
}

//______________________________________________________________________________
VoidFuncPtr_t TROOT::GetMakeDefCanvas() const
{
   // Return default canvas function.

   return fgMakeDefCanvas;
}


//______________________________________________________________________________
TDataType *TROOT::GetType(const char *name, Bool_t load) const
{
   // Return pointer to type with name.

   const char *tname = name + strspn(name," ");
   if (!strncmp(tname,"virtual",7)) {
      tname += 7; tname += strspn(tname," ");
   }
   if (!strncmp(tname,"const",5)) {
      tname += 5; tname += strspn(tname," ");
   }
   size_t nch = strlen(tname);
   while (tname[nch-1] == ' ') nch--;

   // First try without loading.  We can do that because nothing is
   // ever removed from the list of types. (See TCint::UpdateListOfTypes).
   TDataType* type = (TDataType*)gROOT->GetListOfTypes(kFALSE)->FindObject(name);
   if (type || !load)
      return type;
   else
      return (TDataType*)gROOT->GetListOfTypes(load)->FindObject(name);
}

//______________________________________________________________________________
TFile *TROOT::GetFile(const char *name) const
{
   // Return pointer to file with name.

   return (TFile*)GetListOfFiles()->FindObject(name);
}

//______________________________________________________________________________
TStyle *TROOT::GetStyle(const char *name) const
{
   // Return pointer to style with name

   return (TStyle*)GetListOfStyles()->FindObject(name);
}

//______________________________________________________________________________
TObject *TROOT::GetFunction(const char *name) const
{
   // Return pointer to function with name.

   TObject *f1 = fFunctions->FindObject(name);
   if (f1) return f1;

   //The hist utility manager is required (a plugin)
   TVirtualUtilHist *util = (TVirtualUtilHist*)GetListOfSpecials()->FindObject("R__TVirtualUtilHist");
   if (!util) {
      TPluginHandler *h;
      if ((h = GetPluginManager()->FindHandler("TVirtualUtilHist"))) {
         if (h->LoadPlugin() == -1)
            return 0;
         h->ExecPlugin(0);
         util = (TVirtualUtilHist*)GetListOfSpecials()->FindObject("R__TVirtualUtilHist");
      }
   }
   util->InitStandardFunctions();

   return fFunctions->FindObject(name);
}

//______________________________________________________________________________
TGlobal *TROOT::GetGlobal(const char *name, Bool_t load) const
{
   // Return pointer to global variable by name. If load is true force
   // reading of all currently defined globals from CINT (more expensive).

   return (TGlobal *)gROOT->GetListOfGlobals(load)->FindObject(name);
}

//______________________________________________________________________________
TGlobal *TROOT::GetGlobal(const TObject *addr, Bool_t load) const
{
   // Return pointer to global variable with address addr. If load is true
   // force reading of all currently defined globals from CINT (more
   // expensive).

   TIter next(gROOT->GetListOfGlobals(load));

   TGlobal *g;
   while ((g = (TGlobal*) next())) {
      const char *t = g->GetFullTypeName();
      if (!strncmp(t, "class", 5) || !strncmp(t, "struct", 6)) {
         int ptr = 0;
         if (t[strlen(t)-1] == '*') ptr = 1;
         if (ptr) {
            if (*(Long_t *)g->GetAddress() == (Long_t)addr) return g;
         } else {
            if ((Long_t)g->GetAddress() == (Long_t)addr) return g;
         }
      }
   }
   return 0;
}

//______________________________________________________________________________
TFunction *TROOT::GetGlobalFunction(const char *function, const char *params,
                                    Bool_t load)
{
   // Return pointer to global function by name. If params != 0
   // it will also resolve overloading. If load is true force reading
   // of all currently defined global functions from CINT (more expensive).
   // The param string must be of the form: "3189,\"aap\",1.3".

   if (!params)
      return (TFunction *)GetListOfGlobalFunctions(load)->FindObject(function);
   else {
      if (!fInterpreter)
         Fatal("GetGlobalFunction", "fInterpreter not initialized");

      TFunction *f;
      TIter      next(GetListOfGlobalFunctions(load));

      TString mangled = gInterpreter->GetMangledName(0, function, params);
      while ((f = (TFunction *) next())) {
         if (mangled == f->GetMangledName()) return f;
      }

      return 0;
   }
}

//______________________________________________________________________________
TFunction *TROOT::GetGlobalFunctionWithPrototype(const char *function,
                                               const char *proto, Bool_t load)
{
   // Return pointer to global function by name. If proto != 0
   // it will also resolve overloading. If load is true force reading
   // of all currently defined global functions from CINT (more expensive).
   // The proto string must be of the form: "int, char*, float".

   if (!proto)
      return (TFunction *)GetListOfGlobalFunctions(load)->FindObject(function);
   else {
      if (!fInterpreter)
         Fatal("GetGlobalFunctionWithPrototype", "fInterpreter not initialized");

      TFunction *f;
      TIter      next(GetListOfGlobalFunctions(load));

      TString mangled = gInterpreter->GetMangledNameWithPrototype(0,
                                                                     function,
                                                                     proto);
      while ((f = (TFunction *) next())) {
         if (mangled == f->GetMangledName()) return f;
      }
      return 0;
   }
}

//______________________________________________________________________________
TObject *TROOT::GetGeometry(const char *name) const
{
   // Return pointer to Geometry with name

   return GetListOfGeometries()->FindObject(name);
}

//______________________________________________________________________________
TSeqCollection *TROOT::GetListOfGlobals(Bool_t load)
{
   // Return list containing the TGlobals currently defined.
   // Since globals are created and deleted during execution of the
   // program, we need to update the list of globals every time we
   // execute this method. However, when calling this function in
   // a (tight) loop where no interpreter symbols will be created
   // you can set load=kFALSE (default).

   if (!fGlobals) {
      fGlobals = new THashList(100, 3);
      load = kTRUE;
   }

   if (!fInterpreter)
      Fatal("GetListOfGlobals", "fInterpreter not initialized");

   if (load)
      gInterpreter->UpdateListOfGlobals();

   return fGlobals;
}

//______________________________________________________________________________
TSeqCollection *TROOT::GetListOfGlobalFunctions(Bool_t load)
{
   // Return list containing the TFunctions currently defined.
   // Since functions are created and deleted during execution of the
   // program, we need to update the list of functions every time we
   // execute this method. However, when calling this function in
   // a (tight) loop where no interpreter symbols will be created
   // you can set load=kFALSE (default).

   if (!fGlobalFunctions) {
      fGlobalFunctions = new THashList(100, 3);
      load = kTRUE;
   }

   if (!fInterpreter)
      Fatal("GetListOfGlobalFunctions", "fInterpreter not initialized");

   if (load)
      gInterpreter->UpdateListOfGlobalFunctions();

   return fGlobalFunctions;
}

//______________________________________________________________________________
TSeqCollection *TROOT::GetListOfTypes(Bool_t load)
{
   // Return list containing all TDataTypes (typedefs) currently defined.
   // Since types can be added and removed during execution of the
   // program, we need to update the list of types every time we
   // execute this method. However, when calling this function in
   // a (tight) loop where no new types will be created
   // you can set load=kFALSE (default).

   if (!fTypes) {
      fTypes = new THashList(100, 3);
      load = kTRUE;

      // Add also basic types (like a identity typedef "typedef int int")
      fTypes->Add(new TDataType("char"));
      fTypes->Add(new TDataType("unsigned char"));
      fTypes->Add(new TDataType("short"));
      fTypes->Add(new TDataType("unsigned short"));
      fTypes->Add(new TDataType("int"));
      fTypes->Add(new TDataType("unsigned int"));
      fTypes->Add(new TDataType("long"));
      fTypes->Add(new TDataType("unsigned long"));
      fTypes->Add(new TDataType("long long"));
      fTypes->Add(new TDataType("unsigned long long"));
      fTypes->Add(new TDataType("float"));
      fTypes->Add(new TDataType("double"));
      fTypes->Add(new TDataType("void"));
      fTypes->Add(new TDataType("bool"));
   }

   if (!fInterpreter)
      Fatal("GetListOfTypes", "fInterpreter not initialized");

   if (load)
      gInterpreter->UpdateListOfTypes();

   return fTypes;
}


//______________________________________________________________________________
void TROOT::Idle(UInt_t idleTimeInSec, const char *command)
{
   // Execute command when system has been idle for idleTimeInSec seconds.

   if (!fApplication)
      TApplication::CreateApplication();

   if (idleTimeInSec <= 0)
      fApplication->RemoveIdleTimer();
   else {
      if (command && strlen(command))
         fApplication->SetIdleTimer(idleTimeInSec, command);
      else
         Warning("Idle", "must specify non null idle command");
   }
}

//______________________________________________________________________________
Int_t TROOT::IgnoreInclude(const char *fname, const char * /*expandedfname*/)
{
  // Return true if the given include file correspond to a class that has
  // been loaded through a compiled dictionnary.

  Int_t result = 0;

  if ( fname == 0 ) return result;

  TString className(fname);

  // Remove extension if any.
  Int_t where = className.Last('.');
  if (where != kNPOS) className.Remove( where );
  className = gSystem->BaseName(className);

  TClass *cla = GetClass(className);
  if ( cla ) {
    if (cla->GetDeclFileLine() < 0) return 0; // to a void an error with VisualC++
    const char *decfile = gSystem->BaseName(cla->GetDeclFileName());
    if(!decfile) return 0;
    result = strcmp( decfile,fname ) == 0;
  }
  return result;
}

//______________________________________________________________________________
void TROOT::InitSystem()
{
   // Initialize operating system interface.

   if (gSystem == 0) {
#if defined(R__UNIX)
      gSystem = new TUnixSystem;
#elif defined(R__MAC)
      gSystem = new TMacSystem;
#elif defined(R__WIN32)
      gSystem = new TWinNTSystem;
#elif defined(R__VMS)
      gSystem = new TVmsSystem;
#else
      gSystem = new TSystem;
#endif

      if (gSystem->Init())
         Fatal("InitSystem", "can't init operating system layer");

      // read default files
      gEnv = new TEnv(".rootrc");

      gDebug = gEnv->GetValue("Root.Debug", 0);

      const char *sdeb;
      if ((sdeb = gSystem->Getenv("ROOTDEBUG")))
         gDebug = atoi(sdeb);

      if (gDebug > 0 && isatty(2))
         fprintf(stderr, "Info in <TROOT::InitSystem>: running with gDebug = %d\n", gDebug);

      if (gEnv->GetValue("Root.MemStat", 0))
         TStorage::EnableStatistics();
      int msize = gEnv->GetValue("Root.MemStat.size", -1);
      int mcnt  = gEnv->GetValue("Root.MemStat.cnt", -1);
      if (msize != -1 || mcnt != -1)
         TStorage::EnableStatistics(msize, mcnt);

      fgMemCheck = gEnv->GetValue("Root.MemCheck", 0);

      TObject::SetObjectStat(gEnv->GetValue("Root.ObjectStat", 0));
   }
}

//______________________________________________________________________________
void TROOT::InitThreads()
{
   // Load and initialize thread library.

   if (gEnv->GetValue("Root.UseThreads", 0)) {
      char *path;
      if ((path = gSystem->DynamicPathName("libThread", kTRUE))) {
         delete [] path;
         LoadClass("TThread", "Thread");
      }
   }
}

//______________________________________________________________________________
TClass *TROOT::LoadClass(const char *classname) const
{
   // Helper function used by TROOT::GetClass().
   // This function attempts to load the dictionary for 'classname'
   // either from the TClassTable or from the list of generator.

   // This function does not (and should not) attempt to check in the
   // list of load classes or in the typedef.

   VoidFuncPtr_t dict = TClassTable::GetDict(classname);
   if (dict) {
      // The dictionary generation might change/delete classname
      TString clname(classname);
      (dict)();
      return GetClass(clname.Data());
   }

   TIter next(fClassGenerators);
   TClassGenerator *gen;
   while( (gen = (TClassGenerator*) next()) ) {
      TClass *cl = gen->GetClass(classname,kTRUE);
      if (cl) return cl;
   }
   return 0;
}

//______________________________________________________________________________
Int_t TROOT::LoadClass(const char *classname, const char *libname,
                       Bool_t check)
{
   // Check if class "classname" is known to the interpreter. If
   // not it will load library "libname". If the library name does
   // not start with "lib", "lib" will be prepended and a search will
   // be made in the DynamicPath (see .rootrc). If not found a search
   // will be made on libname (without "lib" prepended) and if not found
   // a direct try of libname will be made (in case it contained an
   // absolute path).
   // If check is true it will only check if libname exists and is
   // readable.
   // Returns 0 on successful loading and -1 in case libname does not
   // exist or in case of error.

   if (TClassTable::GetDict(classname)) return 0;

   Int_t err = -1;

   char *path;
   char *lib = 0;
   if (strncmp(libname, "lib", 3))
      lib = Form("lib%s", libname);
   if (lib && (path = gSystem->DynamicPathName(lib, kTRUE))) {
      if (check)
         err = 0;
      else
         err = gSystem->Load(path, 0, kTRUE);
      delete [] path;
   } else if ((path = gSystem->DynamicPathName(libname, kTRUE))) {
      if (check)
         err = 0;
      else
         err = gSystem->Load(path, 0, kTRUE);
      delete [] path;
   } else {
      if (check) {
         if (!gSystem->AccessPathName(libname, kReadPermission))
            err = 0;
         else
            err = -1;
      } else
         err = gSystem->Load(libname, 0, kTRUE);
   }

   if (err == 0 && !check)
      GetListOfTypes(kTRUE);

   if (err == -1)
      ;  //Error("LoadClass", "library %s could not be loaded", libname);

   if (err == 1) {
      //Error("LoadClass", "library %s already loaded, but class %s unknown",
      //      libname, classname);
      err = 0;
   }

   return err;
}

//______________________________________________________________________________
void TROOT::ls(Option_t *option) const
{
   // To list all objects of the application.
   // Loop on all objects created in the ROOT linked lists.
   // Objects may be files and windows or any other object directly
   // attached to the ROOT linked list.

//   TObject::SetDirLevel();
//   GetList()->ForEach(TObject,ls)(option);
   TDirectory::ls(option);
}

//______________________________________________________________________________
Int_t TROOT::LoadMacro(const char *filename, int *error, Bool_t check)
{
   // Load a macro in the interpreter's memory. Equivalent to the command line
   // command ".L filename". If the filename has "+" or "++" appended
   // the macro will be compiled by ACLiC. The filename must have the format:
   // [path/]macro.C[+|++[g|O]].
   // The possible error codes are defined by TInterpreter::EErrorCode.
   // If check is true it will only check if filename exists and is
   // readable.
   // Returns 0 on successful loading and -1 in case filename does not
   // exist or in case of error.

   Int_t err = -1;
   Int_t lerr, *terr;
   if (error)
      terr = error;
   else
      terr = &lerr;

   if (fInterpreter) {
      TString aclicMode;
      TString arguments;
      TString io;
      TString fname = gSystem->SplitAclicMode(filename, aclicMode, arguments, io);

      if (arguments.Length()) {
         Warning("LoadMacro", "argument(s) \"%s\" ignored", arguments.Data(), GetMacroPath());
      }
      char *mac = gSystem->Which(GetMacroPath(), fname, kReadPermission);
      if (!mac) {
         if (!check)
            Error("LoadMacro", "macro %s not found in path %s", fname.Data(), GetMacroPath());
         *terr = TInterpreter::kFatal;
      } else {
         err = 0;
         if (!check) {
            fname = mac;
            fname += aclicMode;
            fname += io;
            gInterpreter->LoadMacro(fname.Data(), (TInterpreter::EErrorCode*)terr);
            if (*terr)
               err = -1;
            //else   // maybe not needed (RDM)
            //   GetListOfTypes(kTRUE);
         }
      }
      delete [] mac;
   }
   return err;
}

//______________________________________________________________________________
Int_t TROOT::Macro(const char *filename, int *error)
{
   // Execute a macro in the interpreter. Equivalent to the command line
   // command ".x filename". If the filename has "+" or "++" appended
   // the macro will be compiled by ACLiC. The filename must have the format:
   // [path/]macro.C[+|++[g|O]][(args)].
   // The possible error codes are defined by TInterpreter::EErrorCode.

   Int_t result = 0;

   if (fInterpreter) {
      TString aclicMode;
      TString arguments;
      TString io;
      TString fname = gSystem->SplitAclicMode(filename, aclicMode, arguments, io);

      char *mac = gSystem->Which(GetMacroPath(), fname, kReadPermission);
      if (!mac) {
         Error("Macro", "macro %s not found in path %s", fname.Data(), GetMacroPath());
         if (error)
            *error = TInterpreter::kFatal;
      } else {
         fname = mac;
         fname += aclicMode;
         fname += arguments;
         fname += io;
         result = gInterpreter->ExecuteMacro(fname, (TInterpreter::EErrorCode*)error);
      }
      delete [] mac;

      if (gPad) gPad->Update();
   }

   return result;
}

//______________________________________________________________________________
void  TROOT::Message(Int_t id, const TObject *obj)
{
   // Process message id called by obj

   TIter next(fMessageHandlers);
   TMessageHandler *mh;
   while ((mh = (TMessageHandler*)next())) {
      mh->HandleMessage(id,obj);
   }
}

//______________________________________________________________________________
void TROOT::ProcessLine(const char *line, Int_t *error)
{
   // Process interpreter command via TApplication::ProcessLine().
   // On Win32 the line will be processed a-synchronously by sending
   // it to the CINT interpreter thread. For explicit synchrounous processing
   // use ProcessLineSync(). On non-Win32 platforms there is not difference
   // between ProcessLine() and ProcessLineSync().
   // The possible error codes are defined by TInterpreter::EErrorCode.  In
   // particular, error will equal to TInterpreter::kProcessing until the
   // CINT interpreted thread has finished executing the line.

   if (!fApplication) {
      // circular Form() buffer will be re-used in CreateApplication() (too
      // many calls to Form()), so we need to save "line"
      char *sline = StrDup(line);
      TApplication::CreateApplication();
      line = Form("%s", sline);
      delete [] sline;
   }

   fApplication->ProcessLine(line, kFALSE, error);
}

//______________________________________________________________________________
void TROOT::ProcessLineSync(const char *line, Int_t *error)
{
   // Process interpreter command via TApplication::ProcessLine().
   // On Win32 the line will be processed synchronously (i.e. it will
   // only return when the CINT interpreter thread has finished executing
   // the line). On non-Win32 platforms there is not difference between
   // ProcessLine() and ProcessLineSync().
   // The possible error codes are defined by TInterpreter::EErrorCode.

   if (!fApplication) {
      // circular Form() buffer will be re-used in CreateApplication() (too
      // many calls to Form()), so we need to save "line"
      char *sline = StrDup(line);
      TApplication::CreateApplication();
      line = Form("%s", sline);
      delete [] sline;
   }

   fApplication->ProcessLine(line, kTRUE, error);
}

//______________________________________________________________________________
Long_t TROOT::ProcessLineFast(const char *line, Int_t *error)
{
   // Process interpreter command directly via CINT interpreter.
   // Only executable statements are allowed (no variable declarations),
   // In all other cases use TROOT::ProcessLine().
   // The possible error codes are defined by TInterpreter::EErrorCode.

   if (!fApplication) {
      // circular Form() buffer will be re-used in CreateApplication() (too
      // many calls to Form()), so we need to save "line"
      char *sline = StrDup(line);
      TApplication::CreateApplication();
      line = Form("%s", sline);
      delete [] sline;
   }

   Long_t result = 0;

   if (fInterpreter) {
      TInterpreter::EErrorCode *code = ( TInterpreter::EErrorCode*)error;
      result = gInterpreter->Calc(line, code);
   }

   return result;
}

//______________________________________________________________________________
TVirtualProof *TROOT::Proof(const char *cluster, const char *configfile)
{
   // Start PROOF session on a specific cluster (default is
   // "proof://localhost"). The TProof object can be accessed via
   // the gProof global. Creating a new TProof object will reset
   // the gProof global. For more on PROOF see the TProof ctor.

   // make sure libProof is loaded and TProof can be created
   TPluginHandler *h;

   // PROOF depends on TTreePlayer
   if ((h = GetPluginManager()->FindHandler("TVirtualTreePlayer")))
      h->LoadPlugin();
   else
      return 0;

   if ((h = GetPluginManager()->FindHandler("TVirtualProof"))) {
      if (h->LoadPlugin() == -1)
         return 0;
      if (!configfile)
         return (TVirtualProof *) h->ExecPlugin(1, cluster);
      return (TVirtualProof *) h->ExecPlugin(2, cluster, configfile);
   }
   return 0;
}

//______________________________________________________________________________
void TROOT::RefreshBrowsers()
{
   // Refresh all browsers. Call this method when some command line
   // command or script has changed the browser contents. Not needed
   // for objects that have the kMustCleanup bit set. Most useful to
   // update browsers that show the file system or other objects external
   // to the running ROOT session.

   TIter next(GetListOfBrowsers());
   TBrowser *b;
   while ((b = (TBrowser*) next()))
      b->SetRefreshFlag(kTRUE);
}

//______________________________________________________________________________
void TROOT::RemoveClass(TClass *oldcl)
{
   // Remove a class from the list and map of classes

   if (!oldcl) return;
   GetListOfClasses()->Remove(oldcl);
   if (oldcl->GetTypeInfo()) {
      fIdMap->Remove(oldcl->GetTypeInfo()->name());
   }
}

//______________________________________________________________________________
void TROOT::Reset(Option_t *)
{
   // Delete all global interpreter objects created since the last call to Reset
   //
   // If option="a" is set reset to startup context (i.e. unload also
   // all loaded files, classes, structs, typedefs, etc.).
   //
   // This function is typically used at the beginning (or end) of a macro
   // to clean the environment.

   if (fInterpreter) {
     // if (!strncmp(option, "a", 1)) {
     //    fInterpreter->Reset();
     //    fInterpreter->SaveContext();
     // } else
         gInterpreter->ResetGlobals();

      if (fGlobals) fGlobals->Delete();
      if (fGlobalFunctions) fGlobalFunctions->Delete();

      SaveContext();
   }
}

//______________________________________________________________________________
void TROOT::SaveContext()
{
   // Save the current interpreter context.

   if (fInterpreter)
      gInterpreter->SaveGlobalsContext();
}

//______________________________________________________________________________
void TROOT::SetCutClassName(const char *name)
{
   // Set the default graphical cut class name for the graphics editor
   // By default the graphics editor creates an instance of a class TCutG.
   // This function may be called to specify a different class that MUST
   // derive from TCutG

   if (!name) {
      Error("SetCutClassName","Invalid class name");
      return;
   }
   TClass *cl = GetClass(name);
   if (!cl) {
      Error("SetCutClassName","Unknown class:%s",name);
      return;
   }
   if (!cl->InheritsFrom("TCutG")) {
      Error("SetCutClassName","Class:%s does not derive from TCutG",name);
      return;
   }
   fCutClassName = name;
}

//______________________________________________________________________________
void TROOT::SetEditorMode(const char *mode)
{
   // Set editor mode

   fEditorMode = 0;
   if (strlen(mode) == 0) return;
   if (!strcmp(mode,"Arc"))      {fEditorMode = kArc;        return;}
   if (!strcmp(mode,"Line"))     {fEditorMode = kLine;       return;}
   if (!strcmp(mode,"Arrow"))    {fEditorMode = kArrow;      return;}
   if (!strcmp(mode,"Button"))   {fEditorMode = kButton;     return;}
   if (!strcmp(mode,"Diamond"))  {fEditorMode = kDiamond;    return;}
   if (!strcmp(mode,"Ellipse"))  {fEditorMode = kEllipse;    return;}
   if (!strcmp(mode,"Pad"))      {fEditorMode = kPad;        return;}
   if (!strcmp(mode,"Pave"))     {fEditorMode = kPave;       return;}
   if (!strcmp(mode,"PaveLabel")){fEditorMode = kPaveLabel;  return;}
   if (!strcmp(mode,"PaveText")) {fEditorMode = kPaveText;   return;}
   if (!strcmp(mode,"PavesText")){fEditorMode = kPavesText;  return;}
   if (!strcmp(mode,"PolyLine")) {fEditorMode = kPolyLine;   return;}
   if (!strcmp(mode,"CurlyLine")){fEditorMode = kCurlyLine;  return;}
   if (!strcmp(mode,"CurlyArc")) {fEditorMode = kCurlyArc;   return;}
   if (!strcmp(mode,"Text"))     {fEditorMode = kText;       return;}
   if (!strcmp(mode,"Marker"))   {fEditorMode = kMarker;     return;}
   if (!strcmp(mode,"CutG"))     {fEditorMode = kCutG;       return;}
}

//______________________________________________________________________________
void TROOT::SetStyle(const char *stylename)
{
   // Change current style to style with name stylename

   TStyle *style = GetStyle(stylename);
   if (style) style->cd();
   else       Error("SetStyle","Unknown style:%s",stylename);
}


//-------- Static Member Functions ---------------------------------------------


//______________________________________________________________________________
Int_t TROOT::DecreaseDirLevel()
{
   return --fgDirLevel;
}

//______________________________________________________________________________
Int_t TROOT::GetDirLevel()
{
   return fgDirLevel;
}

//______________________________________________________________________________
const char *TROOT::GetMacroPath()
{
   // Get macro search path. Static utility function.

   TString &macroPath = ROOT::GetMacroPath();

   if (macroPath.Length() == 0) {
      macroPath = gEnv->GetValue("Root.MacroPath", (char*)0);
      if (macroPath.Length() == 0)
#if !defined (R__VMS) && !defined(R__WIN32)
   #ifdef ROOTMACRODIR
         macroPath = ".:" ROOTMACRODIR;
   #else
         macroPath = TString(".:") + gRootDir + "/macros";
   #endif
#elif !defined(__VMS)
   #ifdef ROOTMACRODIR
         macroPath = ".;" ROOTMACRODIR;
   #else
         macroPath = TString(".;") + gRootDir + "/macros";
   #endif
#else
         macroPath = TString(gRootDir) + "MACROS]";
#endif
   }

   return macroPath;
}

//______________________________________________________________________________
void TROOT::SetMacroPath(const char *newpath)
{
   // Set or extend the macro search path. Static utility function.
   // If newpath=0 or "" reset to value specified in the rootrc file.

   TString &macroPath = ROOT::GetMacroPath();

   if (!newpath || !*newpath)
      macroPath = "";
   else
      macroPath = newpath;
}

//______________________________________________________________________________
Int_t TROOT::IncreaseDirLevel()
{
   return ++fgDirLevel;
}

//______________________________________________________________________________
void TROOT::IndentLevel()
{
   // Functions used by ls() to indent an object hierarchy.

   for (int i = 0; i < fgDirLevel; i++) cout.put(' ');
}

//______________________________________________________________________________
Bool_t TROOT::Initialized()
{
   return fgRootInit;
}

//______________________________________________________________________________
Bool_t TROOT::MemCheck()
{
   return fgMemCheck;
}

//______________________________________________________________________________
void TROOT::SetDirLevel(Int_t level)
{
   fgDirLevel = level;
}

//______________________________________________________________________________
void TROOT::SetMakeDefCanvas(VoidFuncPtr_t makecanvas)
{
   // Static function used to set the address of the default make canvas method.
   // This address is by default initialized to 0.
   // It is set as soon as the library containing the TCanvas class is loaded.

   fgMakeDefCanvas = makecanvas;
}
