//*CMZ :  2.23/08 01/11/99  10.41.09  by  Rene Brun
//*CMZ :  2.23/05 17/10/99  15.03.23  by  Rene Brun
//*CMZ :  2.23/04 17/10/99  14.59.43  by  Fons Rademakers
//*CMZ :  2.23/03 27/09/99  15.15.12  by  Rene Brun
//*CMZ :  2.23/02 07/09/99  12.55.20  by  Rene Brun
//*CMZ :  2.23/01 26/08/99  11.58.16  by  Rene Brun
//*CMZ :  2.23/00 03/08/99  12.04.05  by  Rene Brun
//*-- Author :    Rene Brun   12/12/94

//*KEEP,CopyRight,T=C.
/*************************************************************************
 * Copyright(c) 1995-1999, The ROOT System, All rights reserved.         *
 * Authors: Rene Brun and Fons Rademakers.                               *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/AA_LICENSE.                      *
 * For the list of contributors see $ROOTSYS/AA_CREDITS.                 *
 *************************************************************************/
//*KEND.

#include <string.h>
#include <stdlib.h>
#include <fstream.h>

//*KEEP,TROOT.
#include "TROOT.h"
//*KEEP,TSystem.
#include "TSystem.h"
//*KEEP,TCanvas.
#include "TCanvas.h"
//*KEEP,TFile.
#include "TFile.h"
//*KEEP,TStyle.
#include "TStyle.h"
//*KEEP,TDirectory.
#include "TDirectory.h"
//*KEEP,TH1.
#include "TH1.h"
//*KEEP,TClass.
#include "TClass.h"
//*KEEP,TBaseClass.
#include "TBaseClass.h"
//*KEEP,TClassTable.
#include "TClassTable.h"
//*KEEP,TVirtualPS,T=C++.
#include "TVirtualPS.h"
//*KEEP,TVirtualX.
#include "TVirtualX.h"
//*KEEP,TView.
#include "TView.h"
//*KEEP,TPoint.
#include "TPoint.h"
//*KEEP,TGraph.
#include "TGraph.h"
//*KEEP,TArrow.
#include "TArrow.h"
//*KEEP,TPaveText.
#include "TPaveText.h"
//*KEEP,TPavesText,T=C++.
#include "TPavesText.h"
//*KEEP,TPaveLabel.
#include "TPaveLabel.h"
//*KEEP,TArc.
#include "TArc.h"
//*KEEP,TLatex,T=C++.
#include "TLatex.h"
//*KEEP,TDiamond.
#include "TDiamond.h"
//*KEEP,TGroupButton,T=C++.
#include "TGroupButton.h"
//*KEEP,TBrowser.
#include "TBrowser.h"
//*KEEP,TPadView3D,T=C++.
#include "TPadView3D.h"
//*KEEP,TVirtualGL,T=C++.
#include "TVirtualGL.h"
//*KEEP,TString.
#include "TString.h"
//*KEEP,TLine.
#include "TLine.h"
//*KEEP,TLink.
#include "TLink.h"
//*KEEP,TDataMember.
#include "TDataMember.h"
//*KEEP,TMethod.
#include "TMethod.h"
//*KEEP,TDataType.
#include "TDataType.h"
//*KEEP,TRealData.
#include "TRealData.h"
//*KEEP,TFrame,T=C++.
#include "TFrame.h"
//*KEEP,TGaxis.
#include "TGaxis.h"
//*KEND.


const Int_t kFraming    = BIT(6);  // check also definition in TButton
const Int_t kNoStats    = BIT(9);
const Int_t kClipFrame  = BIT(10);
const Int_t kPrintingPS = BIT(11);
const Int_t kDistanceMaximum = 5;

// Local scratch buffer for screen points, faster than allocating buffer on heap
const Int_t kPXY    = 1002;
const Int_t kButton = 101;
const Int_t kCutG   = 100;

static TPoint gPXY[kPXY];
static Int_t readLevel = 0;

ClassImp(TPad)

//______________________________________________________________________________
//  The Pad class is the most important graphics class in the ROOT system.
//
/*

*/
//
//  A Pad is contained in a Canvas.
//  A Pad may contain other pads (unlimited pad hierarchy).
//  A pad is a linked list of primitives of any type (graphics objects,
//  histograms, detectors, tracks, etc.).
//  Adding a new element into a pad is in general performed by the Draw
//  member function of the object classes.
//  It is important to realize that the pad is a linked list of references
//  to the original object.
//  For example, in case of an histogram, the histogram.Draw() operation
//  only stores a reference to the histogram object and not a graphical
//  representation of this histogram.
//  When the mouse is used to change (say the bin content), the bin content
//  of the original histogram is changed !!
//
//  The convention used in ROOT is that a Draw operation only adds
//  a reference to the object. The effective drawing is performed when
//  when the canvas receives a signal to be painted.
//  This signal is generally sent when typing carriage return in the
//  command input or when a graphical operation has been performed on one
//  of the pads of this canvas.
//  When a Canvas/Pad is repainted, the member function Paint for all
//  objects in the Pad linked list is invoked.
//
//  When the mouse is moved on the Pad, The member function DistancetoPrimitive
//  is called for all the elements in the pad. DistancetoPrimitive returns
//  the distance in pixels to this object.
//  when the object is within the distance window, the member function
//  ExecuteEvent is called for this object.
//  in ExecuteEvent, move, changes can be performed on the object.
//  For examples of DistancetoPrimitive and ExecuteEvent functions,
//  see classes TLine::DistancetoPrimitive, TLine::ExecuteEvent
//              TBox::DistancetoPrimitive,  TBox::ExecuteEvent
//              TH1::DistancetoPrimitive,   TH1::ExecuteEvent
//
//  A Pad supports linear and log scales coordinate systems.
//  The transformation coefficients are explained in TPad::ResizePad.
//  An example of pads hierarchy is shown below:
//
/*

*/
//
//

//______________________________________________________________________________
 TPad::TPad(): TVirtualPad()
{
//*-*-*-*-*-*-*-*-*-*-*Pad default constructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =======================

   fTip        = 0;
   fPadPointer = 0;
   fPrimitives = 0;
   fCanvas     = 0;
   fMother     = 0;
   fPadPaint   = 0;
   fPixmapID   = -1;
   fTheta      = 30;
   fPhi        = 30;
   fNumber     = 0;
   fAbsCoord   = kFALSE;
   fIsEditable = kTRUE;
   fPadView3D  = 0;

   fLogx  = 0;
   fLogy  = 0;
   fLogz  = 0;
   fGridx = 0;
   fGridy = 0;
   fTickx = 0;
   fTicky = 0;
   fFrame = 0;
   fView  = 0;

   fUxmin = fUymin = fUxmax = fUymax = 0;

//*-*- Set default world coordinates to NDC [0,1]
   fX1 = 0;
   fX2 = 1;
   fY1 = 0;
   fY2 = 1;

//*-*- Set default pad range
   fXlowNDC = 0;
   fYlowNDC = 0;
   fWNDC    = 1;
   fHNDC    = 1;
}

//______________________________________________________________________________
 TPad::TPad(const Text_t *name, const Text_t *title, Float_t xlow,
           Float_t ylow, Float_t xup, Float_t yup,
           Color_t color, Short_t bordersize, Short_t bordermode)
          : TVirtualPad(name,title,xlow,ylow,xup,yup,color,bordersize,bordermode)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*Pad constructor-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                          ===============
//  A pad is a linked list of primitives.
//  A pad is contained in a canvas. It may contain other pads.
//  A pad has attributes. When a pad is created, the attributes
//  defined in the current style are copied to the pad attributes.
//
//  xlow [0,1] is the position of the bottom left point of the pad
//             expressed in the mother pad reference system
//  ylow [0,1] is the Y position of this point.
//  xup  [0,1] is the x position of the top right point of the pad
//             expressed in the mother pad reference system
//  yup  [0,1] is the Y position of this point.
//
//  the bordersize is in pixels
//  bordermode = -1 box looks as it is behind the screen
//  bordermode = 0  no special effects
//  bordermode = 1  box looks as it is in front of the screen
//

   fTip        = 0;
   fBorderSize = bordersize;
   fBorderMode = bordermode;
   if (gPad)   fCanvas = gPad->GetCanvas();
   else        fCanvas = (TCanvas*)this;
   fMother     = (TPad*)gPad;
   fPrimitives = new TList(this);
   fPadPointer = 0;
   fTheta      = 30;
   fPhi        = 30;
   fGridx      = gStyle->GetPadGridX();
   fGridy      = gStyle->GetPadGridY();
   fTickx      = gStyle->GetPadTickX();
   fTicky      = gStyle->GetPadTickY();
   fFrame      = 0;
   fView       = 0;
   fPadPaint   = 0;
   fPixmapID   = -1;      // -1 means pixmap will be created by ResizePad()
   fNumber     = 0;
   fAbsCoord   = kFALSE;
   fIsEditable = kTRUE;
   fPadView3D  = 0;

//*-*- Set default world coordinates to NDC [0,1]
   fX1 = 0;
   fX2 = 1;
   fY1 = 0;
   fY2 = 1;

   if (!gPad) return;
   TPad *padsav = (TPad*)gPad;

   if ((xlow < 0) || (xlow > 1) || (ylow <0) || (ylow > 1)) {
      Error("TPad", "illegal bottom left position: x=%f, y=%f", xlow, ylow);
      goto zombie;
   }
   if ((xup < 0) || (xup > 1) || (yup <0) || (yup > 1)) {
      Error("TPad", "illegal top right position: x=%f, y=%f", xup, yup);
      goto zombie;
   }

   fLogx = gStyle->GetOptLogx();
   fLogy = gStyle->GetOptLogy();
   fLogz = gStyle->GetOptLogz();

   fUxmin = fUymin = fUxmax = fUymax = 0;

//*-*- Set pad parameters and Compute conversion coeeficients
   SetPad(name, title, xlow, ylow, xup, yup, color, bordersize, bordermode);
   Range(0, 0, 1, 1);
   SetBit(kCanDelete);

   padsav->cd();
   return;

zombie:
   // error in creating pad occured, make this pad a zombie
   MakeZombie();
   padsav->cd();
}

//______________________________________________________________________________
 TPad::~TPad()
{
//*-*-*-*-*-*-*-*-*-*-*Pad destructor*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ==============

   if (!TestBit(kNotDeleted)) return;
   Close();
   CloseToolTip(fTip);
   DeleteToolTip(fTip);
   SafeDelete(fPrimitives);
   if (fPadView3D) { fPadView3D->SetPad(); fPadView3D = 0; }
}

//______________________________________________________________________________
 void TPad::Browse(TBrowser *b)
{
    cd();
    fPrimitives->Browse(b);
}


//______________________________________________________________________________
 void TPad::cd(Int_t subpadnumber)
{
//*-*-*-*-*-*-*-*-*Set Current Pad*-*-*-*-*-**-*-*-*-*-*-*-*
//*-*              ====================
//  When a canvas/pad is divided via TPad::Divide, one can directly
//  set the current path to one of the subdivisions.
//  See TPad::Divide for the convention to number subpads.
//  For example:
//    c1.Divide(2,3); // create 6 pads (2 divisions along x, 3 along y).
//    To set the current pad to the bottom right pad, do
//    c1.cd(6);
//  Note1:  c1.cd() is equivalent to c1.cd(0) and sets the current pad
//          to c1 itself.
//  Note2:  after a statement like c1.cd(6), the global variable gPad
//          points to the current pad. One can use gPad to set attributes
//          of the current pad.

   if (!subpadnumber) {
      gPad = this;
      if (!gPad->IsBatch()) gVirtualX->SelectWindow(fPixmapID);
      return;
   }

   TObject *obj;
   TIter    next(GetListOfPrimitives());
   while ((obj = next())) {
      if (obj->InheritsFrom(TPad::Class())) {
         Int_t n = ((TPad*)obj)->GetNumber();
         if (n == subpadnumber) {
            ((TPad*)obj)->cd();
            return;
         }
      }
   }
}

//______________________________________________________________________________
 void TPad::Clear(Option_t *option)
{
//*-*-*-*-*-*-*-*-*Delete all pad primitives*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*              =========================


//*-*- Do not delete editor pads when in editor mode

   SafeDelete(fView);

   if (!fPadPaint) {
      if (fPrimitives) fPrimitives->Clear(option);
      delete fFrame; fFrame = 0;
   }

   cd();

   if (!gPad->IsBatch()) gVirtualX->ClearWindow();
   if (gVirtualPS && gPad == gPad->GetCanvas()) gVirtualPS->NewPage();

   PaintBorder(GetFillColor(), kTRUE);
}

//___________________________________________________________
 Int_t TPad::Clip(Float_t *x, Float_t *y, Float_t xclipl, Float_t yclipb, Float_t xclipr, Float_t yclipt)
{
//   Clipping routine: Cohen Sutherland algorithm.
// If Clip ==0 the segment is outside the boundary.
//
// _Input parameters:
//
//  x[2], y[2] : Segment coordinates
//  xclipl, yclipb, xclipr, yclipt : Clipping boundary
//
// _Output parameters:
//
//  x[2], y[2] : New segment coordinates
//
// If clipped != 0 after a call to this function, the
// line has been clipped.
//
   const Float_t P=10000;
   Int_t clip = 0;

   for (Int_t i=0;i<2;i++) {
      if (TMath::Abs(xclipl-x[i]) <= TMath::Abs(xclipr-xclipl)/P) x[i] = xclipl;
      if (TMath::Abs(xclipr-x[i]) <= TMath::Abs(xclipr-xclipl)/P) x[i] = xclipr;
      if (TMath::Abs(yclipb-y[i]) <= TMath::Abs(yclipt-yclipb)/P) y[i] = yclipb;
      if (TMath::Abs(yclipt-y[i]) <= TMath::Abs(yclipt-yclipb)/P) y[i] = yclipt;
   }

//Compute the first endpoint codes.
   Int_t code1 = ClippingCode(x[0],y[0],xclipl,yclipb,xclipr,yclipt);
   Int_t code2 = ClippingCode(x[1],y[1],xclipl,yclipb,xclipr,yclipt);

   Float_t xt=0, yt=0;
//   Int_t clipped = 0; //this variable could be used in a future version
   while(code1 + code2) {
//      clipped = 1;

//The line lies entirely outside the clipping boundary

      if (code1&code2) {
         clip = 0;
         return clip;
      }
//The line is subdivided into several parts

      Int_t ic = code1;
      if (ic == 0) ic = code2;
      if (ic & 0x1) {
         yt = y[0] + (y[1]-y[0])*(xclipl-x[0])/(x[1]-x[0]);
         xt = xclipl;
      }
      if (ic & 0x2) {
         yt = y[0] + (y[1]-y[0])*(xclipr-x[0])/(x[1]-x[0]);
         xt = xclipr;
      }
      if (ic & 0x4) {
         xt = x[0] + (x[1]-x[0])*(yclipb-y[0])/(y[1]-y[0]);
         yt = yclipb;
      }
      if (ic & 0x8) {
         xt = x[0] + (x[1]-x[0])*(yclipt-y[0])/(y[1]-y[0]);
         yt = yclipt;
      }
      if (ic == code1) {
         x[0]  = xt;
         y[0]  = yt;
         code1 = ClippingCode(xt,yt,xclipl,yclipb,xclipr,yclipt);
      } else {
         x[1]  = xt;
         y[1]  = yt;
         code2 = ClippingCode(xt,yt,xclipl,yclipb,xclipr,yclipt);
      }
   }
   clip = 1;
   return clip;
}


//___________________________________________________________
 Int_t TPad::ClippingCode(Float_t x, Float_t y, Float_t xcl1, Float_t ycl1, Float_t xcl2, Float_t ycl2)
{
//   Compute the endpoint codes for TPad::Clip.

   Int_t code = 0;
   if (x < xcl1) code = code | 0x1;
   if (x > xcl2) code = code | 0x2;
   if (y < ycl1) code = code | 0x4;
   if (y > ycl2) code = code | 0x8;
   return code;
}


//______________________________________________________________________________
 void TPad::Close(Option_t *)
{
//*-*-*-*-*-*-*-*-*Delete all primitives in pad and pad itself*-*-*-*-*-*-*
//*-*              ============================
//   NB. Pad cannot be used anymore after this call
//
   if (!TestBit(kNotDeleted)) return;
   if (!fMother) return;

   if (fPrimitives)
      fPrimitives->Clear();
   if (fView) {
      if (fView->TestBit(kNotDeleted)) delete fView;
      fView = 0;
   }
   if (fFrame) {
      if (fFrame->TestBit(kNotDeleted)) delete fFrame;
      fFrame = 0;
   }

   if (fPixmapID != -1) {
      if (gPad) {
         if (!gPad->IsBatch()) {
            gVirtualX->SelectWindow(fPixmapID);
            gVirtualX->ClosePixmap();
         }
      }
      fPixmapID = -1;

      if (!gROOT->GetListOfCanvases()) return;
      if (fMother == this) {
         gROOT->GetListOfCanvases()->Remove(this);
         return;   // in case of TCanvas
      }

      // remove from the mother's list of primitives
      if (fMother->GetListOfPrimitives()) fMother->GetListOfPrimitives()->Remove(this);

      if (gPad == this) fMother->cd();
      if (gROOT->GetSelectedPad() == this) gROOT->SetSelectedPad(0);
   }
   fMother = 0;
}

//______________________________________________________________________________
 void TPad::CopyPixmap()
{
//*-*-*-*-*-*-*-*-*Copy the pixmap of the pad to the canvas*-*-*-*-*-*-*
//*-*              ========================================

   int px, py;
   XYtoAbsPixel(GetX1(), GetY2(), px, py);
   gVirtualX->CopyPixmap(fPixmapID, px, py);
   if (this == gPad) HighLight(gPad->GetHighLightColor());
}

//______________________________________________________________________________
 void TPad::CopyPixmaps()
{
//*-*-*-*-*-*-*-*-*Copy the sub-pixmaps of the pad to the canvas*-*-*-*-*-*-*
//*-*              =============================================

   TObject *obj;
   TIter    next(GetListOfPrimitives());
   while ((obj = next())) {
      if (obj->InheritsFrom(TPad::Class())) {
         ((TPad*)obj)->CopyPixmap();
         ((TPad*)obj)->CopyPixmaps();
      }
   }
}

//______________________________________________________________________________
 void TPad::CreateNewArrow(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Create a new arrow in this pad*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ==============================
//
//  Function called by TPad::ExecuteEvent when the action "Create NewArrow"
//  has been selected in the Canvas pulldown menu.
//
//  Click left button to indicate arrow starting position.
//  Release left button to terminate the arrow.
//
//

   static Float_t x0, y0, x1, y1;

   static Int_t pxold, pyold;
   static Int_t px0, py0;
   static Int_t linedrawn;
   TArrow *arrow;

   switch (event) {

   case kButton1Down:
      gVirtualX->SetLineColor(-1);
      x0 = gPad->AbsPixeltoX(px);
      y0 = gPad->AbsPixeltoY(py);
      px0   = px; py0   = py;
      pxold = px; pyold = py;
      linedrawn = 0;
      break;

   case kButton1Motion:
      if (linedrawn) gVirtualX->DrawLine(px0, py0, pxold, pyold);
      pxold = px;
      pyold = py;
      linedrawn = 1;
      gVirtualX->DrawLine(px0, py0, pxold, pyold);
      break;

   case kButton1Up:
      x1 = gPad->AbsPixeltoX(px);
      y1 = gPad->AbsPixeltoY(py);
      gPad->Modified(kTRUE);

      arrow = new TArrow(x0,y0,x1,y1,0.03,"|>");
      arrow->SetFillColor(1);
      arrow->Draw();
      gROOT->SetEditorMode();
      break;
   }
}


//______________________________________________________________________________
 void TPad::CreateNewEllipse(Int_t event, Int_t px, Int_t py, Int_t mode)
{
//*-*-*-*-*-*-*-*-*-*-*Create a new arc/ellipse in this pad*-*-*-*-*-*-*-*-*-*
//*-*                  ====================================
//
//  Function called by TPad::ExecuteEvent when the action "Create NewEllipse"
//  has been selected in the Canvas pulldown menu.
//
//  Click left button to indicate arrow starting position.
//  Release left button to terminate the arrow.
//


   static Float_t x0, y0, x1, y1;

   static Int_t pxold, pyold;
   static Int_t px0, py0;
   static Int_t linedrawn;
   Float_t xc,yc,r1,r2;
   TEllipse *el = 0;

   switch (event) {

   case kButton1Down:
      gVirtualX->SetLineColor(-1);
      x0 = gPad->AbsPixeltoX(px);
      y0 = gPad->AbsPixeltoY(py);
      px0   = px; py0   = py;
      pxold = px; pyold = py;
      linedrawn = 0;
      break;

   case kButton1Motion:
      if (linedrawn) gVirtualX->DrawBox(px0, py0, pxold, pyold, TVirtualX::kHollow);
      pxold = px;
      pyold = py;
      linedrawn = 1;
      gVirtualX->DrawBox(px0, py0, pxold, pyold, TVirtualX::kHollow);
      break;

   case kButton1Up:
      x1 = gPad->AbsPixeltoX(px);
      y1 = gPad->AbsPixeltoY(py);
      xc = 0.5*(x0+x1);
      yc = 0.5*(y0+y1);

      if (mode == kArc) {
         r1 = 0.5*TMath::Abs(x1-x0);
         el = new TArc(xc, yc, r1);
      }
      if (mode == kEllipse) {
         r1 = 0.5*TMath::Abs(x1-x0);
         r2 = 0.5*TMath::Abs(y1-y0);
         el = new TEllipse(xc, yc, r1, r2);
      }
      gPad->GetCanvas()->FeedbackMode(kFALSE);
      gPad->Modified(kTRUE);
      el->Draw();
      gROOT->SetEditorMode();
      break;
   }
}

//______________________________________________________________________________
 void TPad::CreateNewPad(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Create a new pad in this pad*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ============================
//
//  Function called by TPad::ExecuteEvent when the action "Create NewPad"
//  has been selected in the Canvas pulldown menu.
//
//  Click left button to indicate one corner of the pad
//  Click left button to indicate the opposite corner
//
//  The new pad is inserted in the pad where the first point is selected.
//
   static Int_t px1old, py1old, px2old, py2old;
   static Int_t px1, py1, px2, py2, pxl, pyl, pxt, pyt;
   static Bool_t boxdrawn;
   static TPad *padsav;
   Float_t xlow, ylow, xup, yup;
   TPad * newpad;

   switch (event) {

   case kButton1Down:
      padsav = (TPad*)gPad;
      cd();
      gVirtualX->SetLineColor(-1);
      px1 = gPad->XtoAbsPixel(gPad->GetX1());
      py1 = gPad->YtoAbsPixel(gPad->GetY1());
      px2 = gPad->XtoAbsPixel(gPad->GetX2());
      py2 = gPad->YtoAbsPixel(gPad->GetY2());
      px1old = px; py1old = py;
      boxdrawn = 0;
      break;

   case kButton1Motion:
      if (boxdrawn) gVirtualX->DrawBox(pxl, pyl, pxt, pyt, TVirtualX::kHollow);
      px2old = px;
      px2old = TMath::Max(px2old, px1);
      px2old = TMath::Min(px2old, px2);
      py2old = py;
      py2old = TMath::Max(py2old, py2);
      py2old = TMath::Min(py2old, py1);
      pxl = TMath::Min(px1old, px2old);
      pxt = TMath::Max(px1old, px2old);
      pyl = TMath::Max(py1old, py2old);
      pyt = TMath::Min(py1old, py2old);
      boxdrawn = 1;
      gVirtualX->DrawBox(pxl, pyl, pxt, pyt, TVirtualX::kHollow);
      break;

   case kButton1Up:
      gPad->Modified(kTRUE);
      gPad->SetDoubleBuffer(1);   // Turn on double buffer mode
      gVirtualX->SetDrawMode(TVirtualX::kCopy);       // set drawing mode back to normal (copy) mode
      xlow = (Float_t(pxl) - Float_t(px1))/(Float_t(px2) - Float_t(px1));
      ylow = (Float_t(py1) - Float_t(pyl))/(Float_t(py1) - Float_t(py2));
      xup  = (Float_t(pxt) - Float_t(px1))/(Float_t(px2) - Float_t(px1));
      yup  = (Float_t(py1) - Float_t(pyt))/(Float_t(py1) - Float_t(py2));
      gROOT->SetEditorMode();
      boxdrawn = 0;
      if (xup <= xlow || yup <= ylow) return;
      newpad = new TPad("newpad","newpad",xlow, ylow, xup, yup);
      if (newpad->IsZombie()) break;
      newpad->SetFillColor(gStyle->GetPadColor());
      newpad->Draw();
      padsav->cd();
      break;
   }
}

//______________________________________________________________________________
 void TPad::CreateNewPave(Int_t event, Int_t px, Int_t py, Int_t mode)
{
//*-*-*-*-*-*-*-*-*-*Create a new pavetext in this pad*-*-*-*-*-*-*-*-*-*-*
//*-*                =================================
//
//  Function called by TPad::ExecuteEvent when the action "Create NewPaveText"
//  has been selected in the Canvas pulldown menu.
//
//  Click left button to indicate one corner of the pavelabel.
//  Release left button at the opposite corner.
//


   static Float_t x0, y0, x1, y1;

   static Int_t pxold, pyold;
   static Int_t px0, py0;
   static Int_t linedrawn;
   const Int_t kTMAX=100;
   Int_t i,pxl,pyl;
   Float_t temp;
   Float_t xp0,xp1,yp0,yp1;
   static char atext[kTMAX];
   TObject *pave = 0;

   switch (event) {

   case kButton1Down:
      gVirtualX->SetLineColor(-1);
      x0 = gPad->AbsPixeltoX(px);
      y0 = gPad->AbsPixeltoY(py);
      px0   = px; py0   = py;
      pxold = px; pyold = py;
      linedrawn = 0;
      break;

   case kButton1Motion:
      if (linedrawn) gVirtualX->DrawBox(px0, py0, pxold, pyold, TVirtualX::kHollow);
      pxold = px;
      pyold = py;
      linedrawn = 1;
      gVirtualX->DrawBox(px0, py0, pxold, pyold, TVirtualX::kHollow);
      break;

   case kButton1Up:
      if (px == px0) px = px0+10;
      if (py == py0) py = py0-10;
      x1 = gPad->AbsPixeltoX(px);
      y1 = gPad->AbsPixeltoY(py);

      if (x1 < x0) {temp = x0; x0 = x1; x1 = temp;}
      if (y1 < y0) {temp = y0; y0 = y1; y1 = temp;}
      xp0 = PadtoX(x0);
      xp1 = PadtoX(x1);
      yp0 = PadtoY(y0);
      yp1 = PadtoY(y1);
      if (mode == kPave)       pave = new TPave(xp0,yp0,xp1,yp1);
      if (mode == kPaveText )  pave = new TPaveText(xp0,yp0,xp1,yp1);
      if (mode == kPavesText)  pave = new TPavesText(xp0,yp0,xp1,yp1);
      if (mode == kDiamond)    pave = new TDiamond(x0,y0,x1,y1);
      if (mode == kPaveLabel || mode == kButton) {
         pxl = (px0 + px)/2;
         pyl = (py0 + py)/2;
         for (i=0;i<kTMAX;i++) atext[i] = ' ';
         atext[kTMAX-1] = 0;
         gVirtualX->RequestString(pxl, pyl, atext);
         for (i=kTMAX-2;i>=0;i--) {
            if (atext[i] != ' ') {
               atext[i+1] = 0;
               break;
            }
         }
         if (mode == kPaveLabel) pave = new TPaveLabel(xp0,yp0,xp1,yp1,atext);
         if (mode == kButton)    pave = new TButton(atext,"",
                              (x0-gPad->GetX1())/(gPad->GetX2() - gPad->GetX1()),
                              (y0-gPad->GetY1())/(gPad->GetY2() - gPad->GetY1()),
                              (x1-gPad->GetX1())/(gPad->GetX2() - gPad->GetX1()),
                              (y1-gPad->GetY1())/(gPad->GetY2() -
                              gPad->GetY1()));
      }
      gPad->GetCanvas()->FeedbackMode(kFALSE);
      gPad->Modified(kTRUE);
      pave->Draw();
      gROOT->SetEditorMode();
      break;
   }
}

//______________________________________________________________________________
 void TPad::CreateNewPolyLine(Int_t event, Int_t px, Int_t py, Int_t mode)
{
//*-*-*-*-*-*-*-*-*-*Create a new PolyLine*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                ======================
//  Click left button to indicate a new point
//  Click right button to close the polyline
//  mode = 0 normal polyline
//  mode = 0 smooth polyline
// This function is called when the item NewPolyLine is selected in the
// canvas pulldown menu.
//
   const Int_t kMAX=100;
   static Float_t xline[kMAX], yline[kMAX];

   static Int_t pxold, pyold, px1old, py1old;
   static Int_t npoints = 0;
   static Int_t linedrawn;
   Int_t dp;
   TGraph *gr;

   switch (event) {

   case kButton1Down:
      if (npoints == 0) {
         gVirtualX->SetLineColor(-1);
      } else {
         gPad->GetCanvas()->FeedbackMode(kFALSE);
         gVirtualX->DrawLine(px1old, py1old, pxold, pyold);
      }
      // stop collecting new points if new point is close ( < 5 pixels) of previous point
      dp = TMath::Abs(px-px1old) +TMath::Abs(py-py1old);
      if (npoints && dp < 5) {
         gPad->Modified(kTRUE);
         if      (mode == kPolyLine) {
            gr = new TGraph(npoints,xline,yline);
            gr->ResetBit(kClipFrame);
            gr->Draw("L");
         } else {
            xline[npoints] = xline[0];
            yline[npoints] = yline[0];
            npoints++;
            gr = (TGraph*)gROOT->ProcessLineFast(
                 Form("new TCutG("CUTG",%d,(Float_t*)0x%lx,(Float_t*)0x%lx)",
                      npoints,(Long_t)xline,(Long_t)yline));
            if (gr) gr->Draw("L");
         }
         npoints = 0;
         linedrawn = 0;
         gROOT->SetEditorMode();
         break;
      }
      xline[npoints] = gPad->PadtoX(gPad->AbsPixeltoX(px));
      yline[npoints] = gPad->PadtoY(gPad->AbsPixeltoY(py));
      px1old = px; py1old = py;
      pxold  = px; pyold  = py;
      linedrawn = 0;
      npoints++;

      if (npoints >= kMAX) {
         Error("CreateNewPolyLine", "too many points (more than %d)", kMAX);
         npoints = kMAX;
      }
      break;

   case kMouseMotion:
   case kButton1Motion:
   case kButton1Up:
      if (npoints == 0) return;
      gPad->GetCanvas()->FeedbackMode(kTRUE);
      if (linedrawn) gVirtualX->DrawLine(px1old, py1old, pxold, pyold);
      pxold = px;
      pyold = py;
      linedrawn = 1;
      gVirtualX->DrawLine(px1old, py1old, pxold, pyold);
      break;
   }
}

//______________________________________________________________________________
 void TPad::CreateNewText(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*Create a new TLatex at the cursor position*-*-*-*-*-*-*-*
//*-*                ==========================================
//  Click left button to indicate the text position
// This function is called when the item NewText is selected in the
// canvas pulldown menu.
//

   const Int_t kTMAX=100;
   static char atext[kTMAX];
   Int_t i, lentext;
   TLatex *newtext;
   Float_t x, y;

   switch (event) {

   case kButton1Down:
      for (i=0;i<kTMAX;i++) atext[i] = ' ';
      atext[kTMAX-1] = 0;
      lentext = kTMAX;
      newtext = new TLatex();
      gVirtualX->SetLineColor(-1);
      newtext->TAttText::Modify();
      gVirtualX->RequestString(px, py, atext);
      lentext = strlen(atext);
      for (i=lentext-1;i>=0;i--) {
         if (atext[i] != ' ') {
            atext[lentext] = 0;
            break;
         }
         lentext--;
      }
      if (!lentext) break;
      x = gPad->AbsPixeltoX(px);
      y = gPad->AbsPixeltoY(py);
      newtext->DrawLatex(x, y, atext);
      gPad->Modified(kTRUE);
      gROOT->SetEditorMode();
      break;
   }
}

//______________________________________________________________________________
 Int_t TPad::DistancetoPrimitive(Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Compute distance from point px,py to a box*-*-*-*-*-*
//*-*                  ==========================================
//  Compute the closest distance of approach from point px,py to the
//  edges of this pad.
//  The distance is computed in pixels units.
//

   Int_t pxl, pyl, pxt, pyt;
   Int_t px1 = gPad->XtoAbsPixel(fX1);
   Int_t py1 = gPad->YtoAbsPixel(fY1);
   Int_t px2 = gPad->XtoAbsPixel(fX2);
   Int_t py2 = gPad->YtoAbsPixel(fY2);
   if (px1 < px2) {pxl = px1; pxt = px2;}
   else           {pxl = px2; pxt = px1;}
   if (py1 < py2) {pyl = py1; pyt = py2;}
   else           {pyl = py2; pyt = py1;}

//*-*- Are we inside the box?
//*-*  ======================
   if ( (px > pxl && px < pxt) && (py > pyl && py < pyt) ) {
      if (GetFillStyle()) return 0;  //*-* if pad is filled
   }

//*-*- Are we on the edges?
//*-*  ====================
   Int_t dxl = TMath::Abs(px - pxl);
   if (py < pyl) dxl += pyl - py; if (py > pyt) dxl += py - pyt;
   Int_t dxt = TMath::Abs(px - pxt);
   if (py < pyl) dxt += pyl - py; if (py > pyt) dxt += py - pyt;
   Int_t dyl = TMath::Abs(py - pyl);
   if (px < pxl) dyl += pxl - px; if (px > pxt) dyl += px - pxt;
   Int_t dyt = TMath::Abs(py - pyt);
   if (px < pxl) dyt += pxl - px; if (px > pxt) dyt += px - pxt;

   Int_t distance = dxl;
   if (dxt < distance) distance = dxt;
   if (dyl < distance) distance = dyl;
   if (dyt < distance) distance = dyt;

   return distance - Int_t(0.5*fLineWidth);
}

//______________________________________________________________________________
 void TPad::Divide(Int_t nx, Int_t ny, Float_t xmargin, Float_t ymargin, Int_t color)
{
//*-*-*-*-*-*-*-*-*Automatic pad generation by division*-*-*-*-*-*-*-*-*-*-*
//*-*              ====================================
//  The current canvas is divided in nx by ny equal divisions(pads).
//  xmargin is the space along x between pads in percent of canvas.
//  ymargin is the space along y between pads in percent of canvas.
//  color is the color of the new pads. If 0, color is the canvas color.
//  Pads are automatically named canvasname_n where n is the division number
//  starting from top left pad.
//       Example if canvasname=c1 , nx=2, ny=3
//
//    ...............................................................
//    .                               .                             .
//    .                               .                             .
//    .                               .                             .
//    .           c1_1                .           c1_2              .
//    .                               .                             .
//    .                               .                             .
//    .                               .                             .
//    ...............................................................
//    .                               .                             .
//    .                               .                             .
//    .                               .                             .
//    .           c1_3                .           c1_4              .
//    .                               .                             .
//    .                               .                             .
//    .                               .                             .
//    ...............................................................
//    .                               .                             .
//    .                               .                             .
//    .                               .                             .
//    .           c1_5                .           c1_6              .
//    .                               .                             .
//    .                               .                             .
//    ...............................................................
//
//
//    Once a pad is divided into subpads, one can set the current pad
//    to a subpad with a given division number as illustrated above
//    with TPad::cd(subpad_number).
//    For example, to set the current pad to c1_4, one can do:
//    c1->cd(4)
//
//  Note1:  c1.cd() is equivalent to c1.cd(0) and sets the current pad
//          to c1 itself.
//  Note2:  after a statement like c1.cd(6), the global variable gPad
//          points to the current pad. One can use gPad to set attributes
//          of the current pad.
//

   TPad *padsav = (TPad*)gPad;
   cd();
   if (nx <= 0) nx = 1;
   if (ny <= 0) ny = 1;
   Int_t ix,iy;
   Float_t x1,y1,x2,y2;
   Float_t dy = 1/Float_t(ny);
   Float_t dx = 1/Float_t(nx);
   TPad *pad;
   char *name = new char [strlen(GetName())+6];
   Int_t n = 0;
   if (color == 0) color = GetFillColor();
   for (iy=0;iy<ny;iy++) {
      y2 = 1 - iy*dy - ymargin;
      y1 = y2 - dy + 2*ymargin;
      if (y1 < 0) y1 = 0;
      if (y1 > y2) continue;
      for (ix=0;ix<nx;ix++) {
         x1 = ix*dx + xmargin;
         x2 = x1 +dx -2*xmargin;
         if (x1 > x2) continue;
         n++;
         sprintf(name,"%s_%d",GetName(),n);
         pad = new TPad(name,name,x1,y1,x2,y2,color);
         pad->SetNumber(n);
         pad->Draw();
      }
   }
   delete [] name;
   Modified();
   padsav->cd();
}

//______________________________________________________________________________
 void TPad::Draw(Option_t *option)
{
//*-*-*-*-*-*-*-*-*Draw Pad in Current pad (re-parent pad if necessary)*-*-*-*
//*-*              ====================================================

   // if no canvas opened yet create a default canvas
   if (!gPad) {
      if (!gROOT->GetMakeDefCanvas()) return;
      (gROOT->GetMakeDefCanvas())();
   }

   // pad cannot be in itself and it can only be in one other pad at a time
   if (gPad != this) {
      if (fMother) fMother->GetListOfPrimitives()->Remove(this);
      TPad *oldMother = fMother;
      fCanvas = gPad->GetCanvas();
      fMother = (TPad*)gPad;
      if (oldMother != fMother || fPixmapID == -1) ResizePad();
   }

   Paint();

   if (gPad->IsRetained() && gPad != this && fMother)
      fMother->GetListOfPrimitives()->Add(this, option);
}

//______________________________________________________________________________
 void TPad::DrawClassObject(TObject *classobj, Option_t *option)
{
   // Draw class inheritance tree of the class to which obj belongs.
   // If a class B inherits from a class A, description of B is drawn
   // on the right side of description of A.
   // Member functions overridden by B are shown in class A with a blue line
   // crossing-out the corresponding member function.
   // The following picture is the class inheritance tree of class TPaveLabel:
   //
   /*
   
   */
   //

   char dname[256];
   const Int_t MAXLEVELS = 10;
   TClass *clevel[MAXLEVELS], *cl, *cll;
   TBaseClass *base, *cinherit;
   TText *ptext = 0;
   TString opt=option;
   Float_t x,y,dy,y1,v1,v2,dv;
   Int_t nd,nf,nc,nkd,nkf,i,j;
   TPaveText *pt;
   Int_t maxlev = 4;
   if (opt.Contains("2")) maxlev = 2;
   if (opt.Contains("3")) maxlev = 3;
   if (opt.Contains("5")) maxlev = 5;
   if (opt.Contains("6")) maxlev = 6;
   if (opt.Contains("7")) maxlev = 7;

      // Clear and Set Pad range
   Float_t xpad = 20.5;
   Float_t ypad = 27.5;
   Clear();
   Range(0,0,xpad,ypad);

   // Find number of levels
   Int_t nlevel = 0;
   TClass *obj = (TClass*)classobj;
   clevel[nlevel] = obj;
   TList *lbase = obj->GetListOfBases();
   while(lbase) {
      base = (TBaseClass*)lbase->First();
      if (!base) break;
      if ( base->GetClassPointer() == 0) break;
      nlevel++;
      clevel[nlevel] = base->GetClassPointer();
      lbase = clevel[nlevel]->GetListOfBases();
      if (nlevel >= maxlev-1) break;
   }
   Int_t maxelem = 0;
   Int_t ncdraw  = 0;
   Int_t ilevel, nelem;
   for (ilevel=nlevel;ilevel>=0;ilevel--) {
      cl = clevel[ilevel];
      nelem = cl->GetNdata() + cl->GetNmethods();
      if (nelem > maxelem) maxelem = nelem;
      nc = (nelem/50) + 1;
      ncdraw += nc;
   }

   Float_t tsizcm = 0.40;
   Float_t x1 = 0.25;
   Float_t x2 = 0;
   Float_t dx = 3.5;
   if (ncdraw > 4) {
      dx = dx - 0.42*Float_t(ncdraw-5);
      tsizcm = tsizcm - 0.03*Float_t(ncdraw-5);
   }
   Float_t tsiz = 1.2*tsizcm/ypad;

   // Now loop on levels
   for (ilevel=nlevel;ilevel>=0;ilevel--) {
      cl    = clevel[ilevel];
      nelem = cl->GetNdata() + cl->GetNmethods();
      if (nelem > maxelem) maxelem = nelem;
      nc    = (nelem/50) + 1;
      dy    = 0.45;
      if (ilevel < nlevel) x1 = x2 + 0.5;
      x2    = x1 + nc*dx;
      v2    = ypad - 0.5;
      lbase = cl->GetListOfBases();
      cinherit = 0;
      if (lbase) cinherit = (TBaseClass*)lbase->First();

      do {
         nd = cl->GetNdata();
         nf = cl->GetNmethods() - 2; //do not show default constructor and destructor
         if (cl->GetListOfMethods()->FindObject("Dictionary")) {
            nf -= 6;  // do not count the Dictionary/ClassDef functions
         }
         nkf= nf/nc +1;
         nkd= nd/nc +1;
         if (nd == 0) nkd=0;
         if (nf == 0) nkf=0;
         y1 = v2 - 0.7;
         v1 = y1 - Float_t(nkf+nkd+nc-1)*dy;
         dv = v2 - v1;

         // Create a new PaveText
         pt = new TPaveText(x1,v1,x2,v2);
         pt->SetBit(kCanDelete);
         pt->SetFillColor(19);
         pt->Draw();
         pt->SetTextColor(4);
         pt->SetTextFont(61);
         pt->SetTextAlign(12);
         pt->SetTextSize(tsiz);
         TBox *box = pt->AddBox(0,(y1+0.01-v1)/dv,0,(v2-0.01-v1)/dv);
         box->SetFillColor(17);
         pt->AddLine(0,(y1-v1)/dv,0,(y1-v1)/dv);
         TText *title = pt->AddText(0.5,(0.5*(y1+v2)-v1)/dv,(char*)cl->GetName());
         title->SetTextAlign(22);
         title->SetTextSize(0.6*(v2-y1)/ypad);

         // Draw data Members
         i = 0;
         x = 0.03;
         y = y1 + 0.5*dy;
         TDataMember *d;
         TIter        nextd(cl->GetListOfDataMembers());
         while ((d = (TDataMember *) nextd())) {
            if (i >= nkd) { i = 1; y = y1 - 0.5*dy; x += 1/Float_t(nc); }
            else { i++; y -= dy; }

            // Take in account the room the array index will occupy

            Int_t dim = d->GetArrayDim();
            Int_t indx = 0;
            sprintf(dname,"%s",obj->EscapeChars((char*)d->GetName()));
            Int_t ldname = 0;
            while (indx < dim ){
               ldname = strlen(dname);
               sprintf(&dname[ldname],"[%d]",d->GetMaxIndex(indx));
               indx++;
            }
            ptext = pt->AddText(x,(y-v1)/dv,dname);
         }

         // Draw a separator line
         Float_t ysep;
         if (nd) {
            ysep = y1 - Float_t(nkd)*dy;
            pt->AddLine(0,(ysep-v1)/dv,0,(ysep-v1)/dv);
            ysep -= 0.5*dy;
         } else  ysep = y1;

         // Draw Member Functions
         Int_t fcount = 0;
         i = 0;
         x = 0.03;
         y = ysep + 0.5*dy;
         TMethod *m;
         TIter        nextm(cl->GetListOfMethods());
         while ((m = (TMethod *) nextm())) {
            if (
               !strcmp( m->GetName(), "Dictionary"    ) ||
               !strcmp( m->GetName(), "Class_Version" ) ||
               !strcmp( m->GetName(), "DeclFileName"  ) ||
               !strcmp( m->GetName(), "DeclFileLine"  ) ||
               !strcmp( m->GetName(), "ImplFileName"  ) ||
               !strcmp( m->GetName(), "ImplFileLine"  )
            ) continue;
            fcount++;
            if (fcount > nf) break;
            if (i >= nkf) { i = 1; y = ysep - 0.5*dy; x += 1/Float_t(nc); }
            else { i++; y -= dy; }
            ptext = pt->AddText(x,(y-v1)/dv,obj->EscapeChars((char*)m->GetName()));

            // Check if method is overloaded in a derived class
            // If yes, Change the color of the text to blue
            for (j=ilevel-1;j>=0;j--) {
               if (cl == clevel[ilevel]) {
                  if (clevel[j]->GetMethodAny((char*)m->GetName())) {
                     ptext->SetTextColor(15);
                     break;
                  }
               }
            }
         }

         // Draw second inheritance classes for this class
         cll = 0;
         if (cinherit) {
            cinherit = (TBaseClass*)lbase->After(cinherit);
            if (cinherit) {
               cl  = cinherit->GetClassPointer();
               cll = cl;
               v2  = v1 -0.4;
               dy  = 0.35;
            }
         }
      } while (cll);
   }
   Update();
}

//______________________________________________________________________________
 TH1F *TPad::DrawFrame(Float_t xmin, Float_t ymin, Float_t xmax, Float_t ymax, const Text_t *title)
{
//  Draw a pad frame
//  Compute real pad range taking into account all margins
//  Use services of TH1F class

   TH1F *hframe = (TH1F*)GetPrimitive("hframe");
   if (hframe) delete hframe;
   hframe = new TH1F("hframe",title,100,xmin,xmax);
   hframe->SetBit(kNoStats);
   hframe->SetMinimum(ymin);
   hframe->SetMaximum(ymax);
   hframe->SetDirectory(0);
   hframe->Draw();
   Update();
   return hframe;
}

//______________________________________________________________________________
 void TPad::DrawColorTable()
{
//*-*-*-*-static function to Display Color Table in a pad*-*-*-*-*-*-*
//*-*     ===============================================

   Int_t i, j;
   Int_t color;
   Float_t xlow, ylow, xup, yup, hs, ws;
   Float_t x1, y1, x2, y2;
   x1 = y1 = 0;
   x2 = y2 = 20;

   gPad->SetFillColor(0);
   gPad->Clear();
   gPad->Range(x1,y1,x2,y2);

   TText *text = new TText(0,0,"");
   text->SetTextFont(61);
   text->SetTextSize(0.05);
   text->SetTextAlign(22);

   TBox *box;
   char label[8];
//*-* draw colortable boxes
   hs = (y2-y1)/Float_t(5);
   ws = (x2-x1)/Float_t(10);
   for (i=0;i<10;i++) {
      xlow = x1 + ws*(Float_t(i)+0.1);
      xup  = x1 + ws*(Float_t(i)+0.9);
      for (j=0;j<5;j++) {
         ylow = y1 + hs*(Float_t(j)+0.1);
         yup  = y1 + hs*(Float_t(j)+0.9);
         color = 10*j + i + 1;
         sprintf(label,"%d",color);
         box = new TBox(xlow, ylow, xup, yup);
         box->SetFillColor(color);
         box->Draw();
         text->DrawText(0.5*(xlow+xup), 0.5*(ylow+yup),label);
      }
   }

}

//______________________________________________________________________________
 void TPad::DrawLine(Float_t x1, Float_t y1, Float_t x2, Float_t y2)
{
//*-*-*-*-*-*-*-*-*Draw line in CurrentPad World coordinates*-*-*-*-*-*-*-*
//*-*              =========================================

   Int_t px1 = gPad->XtoPixel(x1);
   Int_t px2 = gPad->XtoPixel(x2);
   Int_t py1 = gPad->YtoPixel(y1);
   Int_t py2 = gPad->YtoPixel(y2);

   gVirtualX->DrawLine(px1, py1, px2, py2);
}

//______________________________________________________________________________
 void TPad::DrawLineNDC(Float_t u1, Float_t v1, Float_t u2, Float_t v2)
{
//*-*-*-*-*-*-*-*-*Draw line in CurrentPad NDC coordinates*-*-*-*-*-*-*-*
//*-*              =======================================

   Int_t px1 = gPad->UtoPixel(u1);
   Int_t px2 = gPad->UtoPixel(u2);
   Int_t py1 = gPad->VtoPixel(v1);
   Int_t py2 = gPad->VtoPixel(v2);

   gVirtualX->DrawLine(px1, py1, px2, py2);
}

//______________________________________________________________________________
 void TPad::DrawText(Float_t x, Float_t y, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*Draw text in CurrentPad World coordinates*-*-*-*-*-*-*-*
//*-*              =========================================

   Int_t px = gPad->XtoPixel(x);
   Int_t py = gPad->YtoPixel(y);

   Float_t angle = gVirtualX->GetTextAngle();
   Float_t mgn   = gVirtualX->GetTextSize();
   gVirtualX->DrawText(px, py, angle, mgn, text, TVirtualX::kClear);
}

//______________________________________________________________________________
 void TPad::DrawTextNDC(Float_t u, Float_t v, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*Draw text in CurrentPad NDC coordinates*-*-*-*-*-*-*-*
//*-*              =======================================

   Int_t px = gPad->UtoPixel(u);
   Int_t py = gPad->VtoPixel(v);

   Float_t angle = gVirtualX->GetTextAngle();
   Float_t mgn   = gVirtualX->GetTextSize();
   gVirtualX->DrawText(px, py, angle, mgn, text, TVirtualX::kClear);
}

//______________________________________________________________________________
 void TPad::ExecuteEvent(Int_t event, Int_t px, Int_t py)
{
//*-*-*-*-*-*-*-*-*-*-*Execute action corresponding to one event*-*-*-*
//*-*                  =========================================
//  This member function is called when a TPad object is clicked.
//
//  If the mouse is clicked in one of the 4 corners of the pad (PA,PB,PC,PD)
//  the pad is resized with the rubber rectangle.
//
//  If the mouse is clicked inside the pad, the pad is moved.
//
//  If the mouse is clicked on the 4 edges (L,R,T,B), the pad is rscaled
//  parallel to this edge (same as Motif window manager).
//
//    PA                    T                       PB
//     +--------------------------------------------+
//     |                                            |
//     |                                            |
//     |                                            |
//    L|                  INSIDE                    |R
//     |                                            |
//     |                                            |
//     |                                            |
//     |                                            |
//     +--------------------------------------------+
//    PD                    B                      PC
//
//
//  Note that this function duplicates on purpose the functionality
//  already implemented in TBox::ExecuteEvent.
//  If somebody modifies this function, may be similar changes should also
//  be applied to TBox::ExecuteEvent.

   static Float_t xmin;
   static Float_t xmax;
   static Float_t ymin;
   static Float_t ymax;

   const Int_t kMaxDiff = 5;
   const Int_t kMinSize = 20;
   static Int_t pxorg, pyorg;
   static Int_t px1, px2, py1, py2, pxl, pyl, pxt, pyt, pxold, pyold;
   static Int_t px1p, px2p, py1p, py2p, pxlp, pylp, pxtp, pytp;
   static Bool_t PA, PB, PC, PD, T, L, R, B, INSIDE;
   Int_t  wx, wy;
   TVirtualPad  *parent;
   Bool_t opaque  = OpaqueMoving();
   Bool_t ropaque = OpaqueResizing();

   if (!IsEditable()) return;

   HideToolTip(event);

   parent = GetMother();
   if (GetXlowNDC() < 0 && event != kButton1Down) return;
   if (GetYlowNDC() < 0 && event != kButton1Down) return;

   // keep old range and mouse position
   if (event == kButton1Down) {
      xmin = fX1;
      xmax = fX2;
      ymin = fY1;
      ymax = fY2;

      pxorg = px;
      pyorg = py;
   }

   Int_t newcode = gROOT->GetEditorMode();
   switch (newcode) {
      case kPad:
         CreateNewPad(event,px,py);
         break;
      case kText:
#ifndef WIN32
         CreateNewText(event,px,py);
#else
        {
            if (event == kButton1Down) gROOT->SetEditorMode();
            gROOT->ProcessLine(Form("((TPad *)0x%lx)->CreateNewText(%d,%d,%d);",
                                    (Long_t)this, event, px, py));
        }
#endif
         break;
      case kPolyLine:
         CreateNewPolyLine(event,px,py,kPolyLine);
         break;
      case kCutG:
         CreateNewPolyLine(event,px,py,kCutG);
         break;
      case kArc:
         CreateNewEllipse(event,px,py,kArc);
         break;
      case kArrow:
         CreateNewArrow(event,px,py);
         break;
      case kEllipse:
         CreateNewEllipse(event,px,py,kEllipse);
         break;
      case kButton:
      case kPave:
      case kPaveLabel:
      case kPaveText:
      case kPavesText:
      case kDiamond:
#ifdef WIN32
         if (newcode == kPaveLabel || newcode == kButton) {
            if (event == kButton1Up) gROOT->SetEditorMode();
            gROOT->ProcessLine(Form("((TPad *)0x%lx)->CreateNewPave(%d,%d,%d,%d);",
                                    (Long_t)this, event, px, py,newcode));
         }
         else
#endif
           CreateNewPave(event,px,py,newcode);
         return;
      default:
         break;
      }
      if (newcode) return;

   Bool_t doing_again = kFALSE;
again:

   switch (event) {

   case kMouseEnter:
      if (fTip)
         ResetToolTip(fTip);
      break;

   case kButton1Down:

#ifdef WIN32
      Pop(); //this should be for cases where mouse has only two buttons
#endif
      gVirtualX->SetLineColor(-1);
      TAttLine::Modify();  //Change line attributes only if necessary
      if (GetFillColor())
         gVirtualX->SetLineColor(GetFillColor());
      else
         gVirtualX->SetLineColor(1);
      gVirtualX->SetLineWidth(2);

      // No break !!!

   case kMouseMotion:

      px1 = XtoAbsPixel(GetX1());
      py1 = YtoAbsPixel(GetY1());
      px2 = XtoAbsPixel(GetX2());
      py2 = YtoAbsPixel(GetY2());

      if (px1 < px2) {
         pxl = px1;
         pxt = px2;
      } else {
         pxl = px2;
         pxt = px1;
      }
      if (py1 < py2) {
         pyl = py1;
         pyt = py2;
      } else {
         pyl = py2;
         pyt = py1;
      }

      px1p = parent->XtoAbsPixel(parent->GetX1()) + parent->GetBorderSize();
      py1p = parent->YtoAbsPixel(parent->GetY1()) - parent->GetBorderSize();
      px2p = parent->XtoAbsPixel(parent->GetX2()) - parent->GetBorderSize();
      py2p = parent->YtoAbsPixel(parent->GetY2()) + parent->GetBorderSize();

      if (px1p < px2p) {
         pxlp = px1p;
         pxtp = px2p;
      } else {
         pxlp = px2p;
         pxtp = px1p;
      }
      if (py1p < py2p) {
         pylp = py1p;
         pytp = py2p;
      } else {
         pylp = py2p;
         pytp = py1p;
      }

      PA = PB = PC = PD = T = L = R = B = INSIDE = kFALSE;

                                                         // case PA
      if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
         pxold = pxl; pyold = pyl; PA = kTRUE;
         SetCursor(kTopLeft);
      }
                                                         // case PB
      if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyl) <= kMaxDiff) {
         pxold = pxt; pyold = pyl; PB = kTRUE;
         SetCursor(kTopRight);
      }
                                                         // case PC
      if (TMath::Abs(px - pxt) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
         pxold = pxt; pyold = pyt; PC = kTRUE;
         SetCursor(kBottomRight);
      }
                                                         // case PD
      if (TMath::Abs(px - pxl) <= kMaxDiff && TMath::Abs(py - pyt) <= kMaxDiff) {
         pxold = pxl; pyold = pyt; PD = kTRUE;
         SetCursor(kBottomLeft);
      }

      if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
          TMath::Abs(py - pyl) < kMaxDiff) {             // top edge
         pxold = pxl; pyold = pyl; T = kTRUE;
         SetCursor(kTopSide);
      }

      if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
          TMath::Abs(py - pyt) < kMaxDiff) {             // bottom edge
         pxold = pxt; pyold = pyt; B = kTRUE;
         SetCursor(kBottomSide);
      }

      if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
          TMath::Abs(px - pxl) < kMaxDiff) {             // left edge
         pxold = pxl; pyold = pyl; L = kTRUE;
         SetCursor(kLeftSide);
      }

      if ((py > pyl+kMaxDiff && py < pyt-kMaxDiff) &&
          TMath::Abs(px - pxt) < kMaxDiff) {             // right edge
          pxold = pxt; pyold = pyt; R = kTRUE;
          SetCursor(kRightSide);
      }

      if ((px > pxl+kMaxDiff && px < pxt-kMaxDiff) &&
          (py > pyl+kMaxDiff && py < pyt-kMaxDiff)) {    // inside box
         pxold = px; pyold = py; INSIDE = kTRUE;
         if (event == kButton1Down)
            SetCursor(kMove);
         else
            SetCursor(kCross);
      }

      fResizing = kFALSE;
      if (PA || PB || PC || PD || T || L || R || B)
         fResizing = kTRUE;

      if (!PA && !PB && !PC && !PD && !T && !L && !R && !B && !INSIDE)
         SetCursor(kCross);

      break;

   case kButton1Motion:

      wx = wy = 0;

      if (PA) {
         if (!ropaque) gVirtualX->DrawBox(pxold, pyt, pxt, pyold, TVirtualX::kHollow);  // draw the old box
         if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
         if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
         if (px < pxlp) { px = pxlp; wx = px; }
         if (py < pylp) { py = pylp; wy = py; }
         if (!ropaque) gVirtualX->DrawBox(px   , pyt, pxt, py,    TVirtualX::kHollow);  // draw the new box
      }
      if (PB) {
         if (!ropaque) gVirtualX->DrawBox(pxl  , pyt, pxold, pyold, TVirtualX::kHollow);
         if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
         if (py > pyt-kMinSize) { py = pyt-kMinSize; wy = py; }
         if (px > pxtp) { px = pxtp; wx = px; }
         if (py < pylp) { py = pylp; wy = py; }
         if (!ropaque) gVirtualX->DrawBox(pxl  , pyt, px ,  py,    TVirtualX::kHollow);
      }
      if (PC) {
         if (!ropaque) gVirtualX->DrawBox(pxl  , pyl, pxold, pyold, TVirtualX::kHollow);
         if (px < pxl+kMinSize) { px = pxl+kMinSize; wx = px; }
         if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
         if (px > pxtp) { px = pxtp; wx = px; }
         if (py > pytp) { py = pytp; wy = py; }
         if (!ropaque) gVirtualX->DrawBox(pxl  , pyl, px ,   py,    TVirtualX::kHollow);
      }
      if (PD) {
         if (!ropaque) gVirtualX->DrawBox(pxold, pyold, pxt, pyl, TVirtualX::kHollow);
         if (px > pxt-kMinSize) { px = pxt-kMinSize; wx = px; }
         if (py < pyl+kMinSize) { py = pyl+kMinSize; wy = py; }
         if (px < pxlp) { px = pxlp; wx = px; }
         if (py > pytp) { py = pytp; wy = py; }
         if (!ropaque) gVirtualX->DrawBox(px   , py ,   pxt, pyl, TVirtualX::kHollow);
      }
      if (T) {
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
         py2 += py - pyold;
         if (py2 > py1-kMinSize) { py2 = py1-kMinSize; wy = py2; }
         if (py2 < py2p) { py2 = py2p; wy = py2; }
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
      }
      if (B) {
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
         py1 += py - pyold;
         if (py1 < py2+kMinSize) { py1 = py2+kMinSize; wy = py1; }
         if (py1 > py1p) { py1 = py1p; wy = py1; }
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
      }
      if (L) {
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
         px1 += px - pxold;
         if (px1 > px2-kMinSize) { px1 = px2-kMinSize; wx = px1; }
         if (px1 < px1p) { px1 = px1p; wx = px1; }
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
      }
      if (R) {
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
         px2 += px - pxold;
         if (px2 < px1+kMinSize) { px2 = px1+kMinSize; wx = px2; }
         if (px2 > px2p) { px2 = px2p; wx = px2; }
         if (!ropaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);
      }
      if (INSIDE) {
         if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);  // draw the old box
         Int_t dx = px - pxold;
         Int_t dy = py - pyold;
         px1 += dx; py1 += dy; px2 += dx; py2 += dy;
         if (px1 < px1p) { dx = px1p - px1; px1 += dx; px2 += dx; wx = px+dx; }
         if (px2 > px2p) { dx = px2 - px2p; px1 -= dx; px2 -= dx; wx = px-dx; }
         if (py1 > py1p) { dy = py1 - py1p; py1 -= dy; py2 -= dy; wy = py-dy; }
         if (py2 < py2p) { dy = py2p - py2; py1 += dy; py2 += dy; wy = py+dy; }
         if (!opaque) gVirtualX->DrawBox(px1, py1, px2, py2, TVirtualX::kHollow);  // draw the new box
      }

      if (wx || wy) {
         if (wx) px = wx;
         if (wy) py = wy;
         gVirtualX->Warp(px, py);
      }

      pxold = px;
      pyold = py;

      if ((!fResizing && opaque) || (fResizing && ropaque)) {
         event = kButton1Up;
         doing_again = kTRUE;
         goto again;
      }

      break;

   case kButton1Up:

      if (PA) {
         fX1 = AbsPixeltoX(px);
         fY1 = AbsPixeltoY(pyt);
         fX2 = AbsPixeltoX(pxt);
         fY2 = AbsPixeltoY(py);
      }
      if (PB) {
         fX1 = AbsPixeltoX(pxl);
         fY1 = AbsPixeltoY(pyt);
         fX2 = AbsPixeltoX(px);
         fY2 = AbsPixeltoY(py);
      }
      if (PC) {
         fX1 = AbsPixeltoX(pxl);
         fY1 = AbsPixeltoY(py);
         fX2 = AbsPixeltoX(px);
         fY2 = AbsPixeltoY(pyl);
      }
      if (PD) {
         fX1 = AbsPixeltoX(px);
         fY1 = AbsPixeltoY(py);
         fX2 = AbsPixeltoX(pxt);
         fY2 = AbsPixeltoY(pyl);
      }
      if (T || B || L || R || INSIDE) {
         fX1 = AbsPixeltoX(px1);
         fY1 = AbsPixeltoY(py1);
         fX2 = AbsPixeltoX(px2);
         fY2 = AbsPixeltoY(py2);
      }

      if (INSIDE)
         if (!doing_again) gPad->SetCursor(kCross);

      if (PA || PB || PC || PD || T || L || R || B)
         Modified(kTRUE);

      gVirtualX->SetLineColor(-1);
      gVirtualX->SetLineWidth(-1);

      if (px != pxorg || py != pyorg) {

         // Get parent corners pixels coordinates
         TPad *parent = fMother;
         Int_t parentpx1 = parent->XtoAbsPixel(parent->GetX1());
         Int_t parentpx2 = parent->XtoAbsPixel(parent->GetX2());
         Int_t parentpy1 = parent->YtoAbsPixel(parent->GetY1());
         Int_t parentpy2 = parent->YtoAbsPixel(parent->GetY2());

         // Get pad new corners pixels coordinates
         Int_t px1 = XtoAbsPixel(fX1); if (px1 < parentpx1) {px1 = parentpx1; }
         Int_t px2 = XtoAbsPixel(fX2); if (px2 > parentpx2) {px2 = parentpx2; }
         Int_t py1 = YtoAbsPixel(fY1); if (py1 > parentpy1) {py1 = parentpy1; }
         Int_t py2 = YtoAbsPixel(fY2); if (py2 < parentpy2) {py2 = parentpy2; }

         // Compute new pad positions in the NDC space of parent
         fXlowNDC = Float_t(px1 - parentpx1)/Float_t(parentpx2 - parentpx1);
         fYlowNDC = Float_t(py1 - parentpy1)/Float_t(parentpy2 - parentpy1);
         fWNDC    = Float_t(px2 - px1)/Float_t(parentpx2 - parentpx1);
         fHNDC    = Float_t(py2 - py1)/Float_t(parentpy2 - parentpy1);
      }

      // Restore old range
      fX1 = xmin;
      fX2 = xmax;
      fY1 = ymin;
      fY2 = ymax;

      // Reset pad parameters and recompute conversion coefficients
      ResizePad();

      break;

   case kButton1Locate:

      ExecuteEvent(kButton1Down, px, py);

      while (1) {
         px = py = 0;
         event = gVirtualX->RequestLocator(1, 1, px, py);

         ExecuteEvent(kButton1Motion, px, py);

         if (event != -1) {                     // button is released
            ExecuteEvent(kButton1Up, px, py);
            return;
         }
      }

   case kButton2Down:

      Pop();
      break;

   }
}

//______________________________________________________________________________
 void TPad::HideToolTip(Int_t event)
{
   // Hide tool tip depending on the event type. Typically tool tips
   // are hidden when event is not a kMouseEnter and not a kMouseMotion
   // event.

   if (event != kMouseEnter && event != kMouseMotion && fTip)
      gPad->CloseToolTip(fTip);
}

//______________________________________________________________________________
 Int_t TPad::GetCanvasID() const
{
   return fCanvas->GetCanvasID();
}

//______________________________________________________________________________
 Int_t TPad::GetEvent() const
{
   return fCanvas->GetEvent();
}

//______________________________________________________________________________
 Int_t TPad::GetEventX() const
{
   return fCanvas->GetEventX();
}

//______________________________________________________________________________
 Int_t TPad::GetEventY() const
{
   return fCanvas->GetEventY();
}

//______________________________________________________________________________
 TVirtualPad *TPad::GetVirtCanvas()
{
   return (TVirtualPad*) fCanvas;
}

//______________________________________________________________________________
 Color_t TPad::GetHighLightColor() const
{
   return fCanvas->GetHighLightColor();
}

//______________________________________________________________________________
 TObject *TPad::GetSelected()
{
   return fCanvas->GetSelected();
}

//______________________________________________________________________________
 TVirtualPad *TPad::GetSelectedPad() const
{
   return fCanvas->GetSelectedPad();
}

//______________________________________________________________________________
 TVirtualPad *TPad::GetPadSave() const
{
   return fCanvas->GetPadSave();
}

//______________________________________________________________________________
 UInt_t TPad::GetWh()
{
   return fCanvas->GetWh();
}

//______________________________________________________________________________
 UInt_t TPad::GetWw()
{
   return fCanvas->GetWw();
}

//______________________________________________________________________________
 Bool_t TPad::IsBatch()
{
   return fCanvas->IsBatch();
}

//______________________________________________________________________________
 Bool_t TPad::IsRetained()
{
   return fCanvas->IsRetained();
}

//______________________________________________________________________________
 Bool_t TPad::OpaqueMoving() const
{
   return fCanvas->OpaqueMoving();
}

//______________________________________________________________________________
 Bool_t TPad::OpaqueResizing() const
{
   return fCanvas->OpaqueResizing();
}

//______________________________________________________________________________
 void TPad::SetBatch(Bool_t batch)
{
   fCanvas->SetBatch(batch);
}

//______________________________________________________________________________
 void TPad::SetCanvasSize(UInt_t ww, UInt_t wh)
{
   fCanvas->SetCanvasSize(ww,wh);
}

//______________________________________________________________________________
 void TPad::SetCursor(ECursor cursor)
{
   fCanvas->SetCursor(cursor);
}

//______________________________________________________________________________
 void TPad::SetDoubleBuffer(Int_t mode)
{
   fCanvas->SetDoubleBuffer(mode);
}

//______________________________________________________________________________
 void TPad::SetSelected(TObject *obj)
{
   fCanvas->SetSelected(obj);
}

//______________________________________________________________________________
 void TPad::Update()
{
   fCanvas->Update();
}

//______________________________________________________________________________
 TFrame *TPad::GetFrame()
{
   if (fFrame && !GetListOfPrimitives()->FindObject(fFrame)) fFrame = 0;
   if (!fFrame) {
      fFrame = new TFrame(0,0,1,1);
      Int_t framecolor = GetFrameFillColor();
      if (!framecolor) framecolor = GetFillColor();
      fFrame->SetFillColor(framecolor);
      fFrame->SetFillStyle(GetFrameFillStyle());
      fFrame->SetLineColor(GetFrameLineColor());
      fFrame->SetLineStyle(GetFrameLineStyle());
      fFrame->SetLineWidth(GetFrameLineWidth());
      fFrame->SetBorderSize(GetFrameBorderSize());
      fFrame->SetBorderMode(GetFrameBorderMode());
   }
   return fFrame;
}

//______________________________________________________________________________
 TObject *TPad::GetPrimitive(const Text_t *name)
{
   if (fPrimitives) return fPrimitives->FindObject(name);
   return 0;
}

//______________________________________________________________________________
 void TPad::GetRange(Float_t &x1, Float_t &y1, Float_t &x2, Float_t &y2)
{
//*-*-*-*-*-*-*-*Return pad world coordinates range*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*            ==================================
  x1 = fX1;
  y1 = fY1;
  x2 = fX2;
  y2 = fY2;
}

//______________________________________________________________________________
 void TPad::GetRangeAxis(Axis_t &xmin, Axis_t &ymin, Axis_t &xmax, Axis_t &ymax)
{
//*-*-*-*-*-*-*-*Return pad axis coordinates range*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*            ==================================
  xmin = fUxmin;
  ymin = fUymin;
  xmax = fUxmax;
  ymax = fUymax;
}

//______________________________________________________________________________
 void TPad::HighLight(Color_t color, Bool_t set)
{
   AbsCoordinates(kTRUE);

   // We do not want to have active(executable) buttons, etc highlighted
   // in this manner, unless we want to edit'em
   if (GetMother()->IsEditable() && !InheritsFrom(TButton::Class())) {
      gROOT->SetSelectedPad(this);
      if (set)
         PaintBorder(-color, kFALSE);
      else
         PaintBorder(-GetFillColor(), kFALSE);
   }

   AbsCoordinates(kFALSE);
}

//______________________________________________________________________________
 void TPad::InspectObject(TObject *obj)
{
   // Dump contents of obj in a graphics canvas.
   // Same action as TObject::Dump but in a graphical form.
   // In addition pointers to other objects can be followed.
   //
   // The following picture is the Inspect of a histogram object:
   //
   /*
   
   */
   //

   Int_t cdate = 0;
   Int_t ctime = 0;
   UInt_t *cdatime = 0;
   Bool_t isdate = kFALSE;
   const Int_t kname  = 1;
   const Int_t kvalue = 25;
   const Int_t ktitle = 37;
   const Int_t kline  = 255;
   char line[kline];
   char *pname;

   TClass *cl = obj->IsA();
   if (cl == 0) return;
   if (!cl->GetListOfRealData()) cl->BuildRealData();

   // Count number of data members in order to resize the canvas
   TRealData *rd;
   TIter      next(cl->GetListOfRealData());
   Int_t nreal = cl->GetListOfRealData()->GetSize();

   if (nreal == 0) return;

   Int_t nrows = 33;
   if (nreal+7 > nrows) nrows = nreal+7;
   Int_t nh = nrows*15;
   Int_t nw = 700;
   TVirtualPad *canvas = GetVirtCanvas();
   canvas->Clear();                // remove primitives from canvas
   canvas->SetCanvasSize(nw, nh);  // set new size of drawing area
   canvas->Range(0,-3,20,nreal+4);

   Float_t xvalue = 5;
   Float_t xtitle = 8;
   Float_t dy     = 1;
   Float_t ytext  = Float_t(nreal) - 0.5;
   Float_t tsize  = 0.99/ytext;
   if (tsize > 0.0333) tsize = 0.033;

   // Create text objects
   TText *tname  = new TText();
   TText *tvalue = new TText();
   TText *ttitle = new TText();
   TText *tval;
   tname->SetTextFont(61);
   tname->SetTextAngle(0);
   tname->SetTextAlign(12);
   tname->SetTextColor(1);
   tname->SetTextSize(tsize);
   tvalue->SetTextFont(61);
   tvalue->SetTextAngle(0);
   tvalue->SetTextAlign(12);
   tvalue->SetTextColor(1);
   tvalue->SetTextSize(tsize);
   ttitle->SetTextFont(62);
   ttitle->SetTextAngle(0);
   ttitle->SetTextAlign(12);
   ttitle->SetTextColor(1);
   ttitle->SetTextSize(tsize);

   // Draw surrounding box and title areas
   Float_t x1 = 0.2;
   Float_t x2 = 19.8;
   Float_t y1 = 0.5;
   Float_t y2 = Float_t(nreal) + 0.5;
   Float_t y3 = y2 + 1;
   Float_t y4 = y3 + 1.5;
   TLine *frame   = new TLine();
   frame->SetLineColor(1);
   frame->SetLineStyle(1);
   frame->SetLineWidth(1);
   frame->DrawLine(x1, y1, x2, y1);
   frame->DrawLine(x2, y1, x2, y4);
   frame->DrawLine(x2, y4, x1, y4);
   frame->DrawLine(x1, y4, x1, y1);
   frame->DrawLine(x1, y2, x2, y2);
   frame->DrawLine(x1, y3, x2, y3);
   frame->DrawLine(xvalue, y1, xvalue, y3);
   frame->DrawLine(xtitle, y1, xtitle, y3);
   ttitle->SetTextSize(0.8*tsize);
   ttitle->SetTextAlign(21);
   ttitle->DrawText(0.5*(x1+xvalue), y2+0.1, "Member Name");
   ttitle->DrawText(0.5*(xvalue+xtitle), y2+0.1, "Value");
   ttitle->DrawText(0.5*(xtitle+x2), y2+0.1, "Title");
   ttitle->SetTextSize(1.2*tsize);
   ttitle->SetTextColor(2);
   ttitle->SetTextAlign(11);
   ttitle->DrawText(x1+0.2, y3+0.1, cl->GetName());
   ttitle->SetTextColor(4);
   sprintf(line,"%s:%d",obj->GetName(),obj->GetUniqueID());
   ttitle->DrawText(xvalue+0.2, y3+0.1, line);
   ttitle->SetTextColor(6);
   ttitle->DrawText(xtitle+2, y3+0.1, obj->GetTitle());
   ttitle->SetTextSize(tsize);
   ttitle->SetTextColor(1);
   ttitle->SetTextFont(11);
   ttitle->SetTextAlign(12);

   //---Now loop on data members-----------------------
   // We make 3 passes. Faster than one single pass because changing
   // font parameters is time consuming
   for (Int_t pass = 0; pass < 3; pass++) {
      ytext  = y2 - 0.5;
      next.Reset();
      while ((rd = (TRealData*) next())) {
         TDataMember *member = rd->GetDataMember();
         if (!member) continue;
         TDataType *membertype = member->GetDataType();
         isdate = kFALSE;
         if (strcmp(member->GetName(),"fDatime") == 0 && strcmp(member->GetTypeName(),"UInt_t") == 0) {
            isdate = kTRUE;
         }

         // Encode data member name
         pname = &line[kname];
         for (Int_t i=0;i<kline;i++) line[i] = ' ';
         line[kline-1] = 0;
         sprintf(pname,"%s ",rd->GetName());

         // Encode data value or pointer value
         tval = tvalue;
         Int_t offset = rd->GetThisOffset();
         char *pointer = (char*)obj + offset;
         char **ppointer = (char**)(pointer);
         TLink *tlink = 0;

         if (member->IsaPointer()) {
            char **p3pointer = (char**)(*ppointer);
            if (!p3pointer) {
               sprintf(&line[kvalue],"->0");
            } else if (!member->IsBasic()) {
               if (pass == 1) tlink = new TLink(xvalue+0.1, ytext, p3pointer);
            } else if (membertype) {
               if (!strcmp(membertype->GetTypeName(), "char"))
                  sprintf(&line[kvalue], "%s", *ppointer);
               else
                  strcpy(&line[kvalue], membertype->AsString(p3pointer));
            } else if (!strcmp(member->GetFullTypeName(), "char*") ||
                     !strcmp(member->GetFullTypeName(), "const char*")) {
               sprintf(&line[kvalue], "%s", *ppointer);
            } else {
               if (pass == 1) tlink = new TLink(xvalue+0.1, ytext, p3pointer);
            }
         } else if (membertype)
            if (isdate) {
               cdatime = (UInt_t*)pointer;
               TDatime::GetDateTime(cdatime[0],cdate,ctime);
               sprintf(&line[kvalue],"%d/%d",cdate,ctime);
            } else {
               strcpy(&line[kvalue], membertype->AsString(pointer));
            }
         else
            sprintf(&line[kvalue],"->%lx ", (Long_t)pointer);

         // Encode data member title
         Int_t ltit = 0;
         if (isdate == kFALSE && strcmp(member->GetFullTypeName(), "char*") &&
             strcmp(member->GetFullTypeName(), "const char*")) {
            Int_t lentit = strlen(member->GetTitle());
            if (lentit >= kline-ktitle) lentit = kline-ktitle-1;
            strncpy(&line[ktitle],member->GetTitle(),lentit);
            line[ktitle+lentit] = 0;
            ltit = ktitle;
         }

         // Ready to draw the name, value and title columns
         if (pass == 0)tname->DrawText( x1+0.1,  ytext, &line[kname]);
         if (pass == 1) {
            if (tlink) {
               tlink->SetTextFont(61);
               tlink->SetTextAngle(0);
               tlink->SetTextAlign(12);
               tlink->SetTextColor(2);
               tlink->SetTextSize(tsize);
               tlink->SetName((char *)member->GetTypeName());
               tlink->SetBit(kCanDelete);
               tlink->Draw();
            } else tval->DrawText(xvalue+0.1, ytext, &line[kvalue]);
         }
         if (pass == 2 && ltit) ttitle->DrawText(xtitle+0.3, ytext, &line[ltit]);
         ytext -= dy;
      }
   }
   Update();
   delete frame;
   delete tname;
   delete tvalue;
   delete ttitle;
}

//______________________________________________________________________________
 void TPad::ls(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*List all primitives in pad*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                ==========================
   IndentLevel();
   cout <<IsA()->GetName()<<" fXlowNDC=" <<fXlowNDC<<" fYlowNDC="<<fYlowNDC<<" fWNDC="<<GetWNDC()<<" fHNDC="<<GetHNDC()
        <<" Name= "<<GetName()<<" Title= "<<GetTitle()<<" Option="<<option<<endl;
   TObject::IncreaseDirLevel();
   fPrimitives->ls(option);
   TObject::DecreaseDirLevel();
}

//______________________________________________________________________________
 Float_t TPad::PadtoX(Axis_t x) const
{
   if (fLogx && x < 50) return Float_t(TMath::Exp(2.302585092994*x));
   return x;
}

//______________________________________________________________________________
 Float_t TPad::PadtoY(Axis_t y) const
{
   if (fLogy && y < 50) return Float_t(TMath::Exp(2.302585092994*y));
   return y;
}

//______________________________________________________________________________
 Float_t TPad::XtoPad(Axis_t x) const
{
   if (fLogx) {
      if (x > 0) x = TMath::Log10(x);
      else       x = fUxmin;
   }
   return x;
}

//______________________________________________________________________________
 Float_t TPad::YtoPad(Axis_t y) const
{
   if (fLogy) {
      if (y > 0) y = TMath::Log10(y);
      else       y = fUymin;
   }
   return y;
}

//______________________________________________________________________________
 void TPad::Paint(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*Paint all primitives in pad*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                ===========================

   TPad *padsav = (TPad*)gPad;

   fPadPaint = 1;
   cd();
//*-*   TView must be drawn here (is TView contains OpenGL context)

//*-*   Start OpenGL Model if present
   if (fPadView3D)
        fPadView3D->PaintBeginModel(option);
//   else
   PaintBorder(GetFillColor(), kTRUE);

   if (fPrimitives) fPrimitives->Paint(option);

   if (fPadView3D)
   {
//*-*   Finish 3D Model
       fPadView3D->PaintEnd(option);
//*-*   Start 3D scene
       fPadView3D->PaintScene(option);
   }

   padsav->cd();
   fPadPaint = 0;
   Modified(kFALSE);
}

//______________________________________________________________________________
 void TPad::PaintBorder(Color_t color, Bool_t tops)
{
//*-*-*-*-*-*-*-*-*-*Paint the pad border*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                ====================

//*-*- Draw first  a box as a normal filled box
   if(color > 0) {
         TAttLine::Modify();  //Change line attributes only if necessary
      TAttFill::Modify();  //Change fill area attributes only if necessary
      PaintBox(fX1,fY1,fX2,fY2);
   }
   if (color < 0) color = -color;
//*-*- then paint 3d frame (depending on bordermode)
   if (IsTransparent()) return;
   // Paint a 3D frame around the pad.

   if (fBorderMode == 0) return;
   Int_t bordersize = fBorderSize;
   if (bordersize <= 0) bordersize = 2;

   Short_t pxl,pyl,pxt,pyt,px1,py1,px2,py2;
   Float_t xl, xt, yl, yt;

   // GetDarkColor() and GetLightColor() use GetFillColor()
   Color_t oldcolor = GetFillColor();
   SetFillColor(color);
   TAttFill::Modify();
   Color_t light    = color + 150;
   Color_t dark     = color + 100;

//*-*- Compute real left bottom & top right of the box in pixels
   px1 = XtoPixel(fX1);   py1 = YtoPixel(fY1);
   px2 = XtoPixel(fX2);   py2 = YtoPixel(fY2);
   if (px1 < px2) {pxl = px1; pxt = px2; xl = fX1; xt = fX2; }
   else           {pxl = px2; pxt = px1; xl = fX2; xt = fX1;}
   if (py1 > py2) {pyl = py1; pyt = py2; yl = fY1; yt = fY2;}
   else           {pyl = py2; pyt = py1; yl = fY2; yt = fY1;}

   if (!IsBatch()) {
      TPoint frame[7];

//*-*- Draw top&left part of the box
      frame[0].fX = pxl;                 frame[0].fY = pyl;
      frame[1].fX = pxl + bordersize;    frame[1].fY = pyl - bordersize;
      frame[2].fX = frame[1].fX;         frame[2].fY = pyt + bordersize;
      frame[3].fX = pxt - bordersize;    frame[3].fY = frame[2].fY;
      frame[4].fX = pxt;                 frame[4].fY = pyt;
      frame[5].fX = pxl;                 frame[5].fY = pyt;
      frame[6].fX = pxl;                 frame[6].fY = pyl;

      if (fBorderMode == -1) gVirtualX->SetFillColor(dark);
      else                   gVirtualX->SetFillColor(light);
      gVirtualX->DrawFillArea(7, frame);

//*-*- Draw bottom&right part of the box
      frame[0].fX = pxl;                 frame[0].fY = pyl;
      frame[1].fX = pxl + bordersize;    frame[1].fY = pyl - bordersize;
      frame[2].fX = pxt - bordersize;    frame[2].fY = frame[1].fY;
      frame[3].fX = frame[2].fX;         frame[3].fY = pyt + bordersize;
      frame[4].fX = pxt;                 frame[4].fY = pyt;
      frame[5].fX = pxt;                 frame[5].fY = pyl;
      frame[6].fX = pxl;                 frame[6].fY = pyl;

      if (fBorderMode == -1) gVirtualX->SetFillColor(light);
      else                   gVirtualX->SetFillColor(dark);
      gVirtualX->DrawFillArea(7, frame);

//*-* If this pad is a button, highlight it
      if (InheritsFrom("TButton") && fBorderMode == -1) {
         if (TestBit(kFraming)) {  // bit set in TButton::SetFraming
            if (GetFillColor() != 2) gVirtualX->SetLineColor(2);
            else                     gVirtualX->SetLineColor(4);
            gVirtualX->DrawBox(px1+2,py1-2,px2-2,py2+2, TVirtualX::kHollow);
         }
      }
      gVirtualX->SetFillColor(-1);
      SetFillColor(oldcolor);
   }

   if (!tops) return;

//*-*- same for PostScript
//   Float_t dx   = (xt - xl) *Float_t(bordersize)/Float_t(pxt - pxl);
//   Int_t border = gVirtualPS->XtoPS(xt) - gVirtualPS->XtoPS(xt-dx);

   PaintBorderPS(xl, yl, xt, yt, fBorderMode, bordersize, dark, light);
}

//______________________________________________________________________________
 void TPad::PaintBorderPS(Float_t xl,Float_t yl,Float_t xt,Float_t yt,Int_t bmode,Int_t bsize,Int_t dark,Int_t light)
{
//*-*-*-*-*-*-*-*Paint a frame border with Postscript*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*            ====================================

   if (!gVirtualPS) return;
   gVirtualPS->DrawFrame(xl, yl, xt, yt, bmode,bsize,dark,light);
}

//______________________________________________________________________________
 void TPad::PaintPadFrame(Float_t xmin, Float_t ymin, Float_t xmax, Float_t ymax)
{
//*-*-*-*-*-*-*-*-*-*Paint histogram/graph frame*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                ===========================

   TList *glist  = GetListOfPrimitives();
   TFrame *frame = GetFrame();
   frame->SetX1(xmin);
   frame->SetX2(xmax);
   frame->SetY1(ymin);
   frame->SetY2(ymax);
   if (!glist->FindObject(fFrame)) {
      glist->AddFirst(frame);
      fFrame->SetBit(kObjInCanvas);
   }
   frame->Paint();
}

//______________________________________________________________________________
 void TPad::PaintModified()
{
//*-*-*-*-*-*-*Traverse pad hierarchy and (re)paint only modified pads*-*-*-*
//*-*          =======================================================

   TPad *padsav = (TPad*)gPad;
   TVirtualPS *saveps = gVirtualPS;
   if (gVirtualPS) {
      if (gVirtualPS->TestBit(kPrintingPS)) gVirtualPS = 0;
   }
   fPadPaint = 1;
   cd();
   if (IsModified() || IsTransparent()) {
       if (fPadView3D)
           fPadView3D->PaintBeginModel();
       PaintBorder(GetFillColor(), kTRUE);
   }

   TIter next(GetListOfPrimitives());
   TObject *obj;

   while ((obj = next())) {
      if (obj->InheritsFrom(TPad::Class())) {
         ((TPad*)obj)->PaintModified();
      } else if (IsModified() || IsTransparent()) {
         obj->Paint((Option_t *)next.GetOption());
      }
   }

   if (IsModified() && fPadView3D)
   {
       fPadView3D->PaintEnd();
       fPadView3D->PaintScene();
   }

   if (padsav) padsav->cd();
   fPadPaint = 0;
   Modified(kFALSE);
   gVirtualPS = saveps;
}

//______________________________________________________________________________
 void TPad::PaintBox(Float_t x1, Float_t y1, Float_t x2, Float_t y2, Option_t *)
{
//*-*-*-*-*-*-*-*-*Paint box in CurrentPad World coordinates*-*-*-*-*-*-*-*-*-*
//*-*              =========================================

   if (!gPad->IsBatch()) {
      Int_t px1 = XtoPixel(x1);
      Int_t px2 = XtoPixel(x2);
      Int_t py1 = YtoPixel(y1);
      Int_t py2 = YtoPixel(y2);

      Int_t style = gVirtualX->GetFillStyle();
      if (style) {
         if (style > 3000 && style < 4000) {
#ifndef WIN32
            if (style < 3020) {
               // set solid background color
               gVirtualX->SetFillStyle(1001);
               gVirtualX->DrawBox(px1,py1,px2,py2,TVirtualX::kFilled);
            }

            if (style > 3100) {
               char gifname[32];
               sprintf(gifname,"gif%d",style);
               TNamed *gifnamed = (TNamed*)gROOT->GetListOfSpecials()->FindObject(gifname);
               if (gifnamed) gVirtualX->ReadGIF(px1,py2,gifnamed->GetTitle());
            }
            if (style > 3020 && style < 3100) {
               gVirtualX->SetFillStyle(style-10);
            } else {
               gVirtualX->SetFillColor(1);
               gVirtualX->SetFillStyle(style);
            }
#endif
            // draw stipples
            gVirtualX->DrawBox(px1,py1,px2,py2,TVirtualX::kFilled);

         } else if (style >= 4000 && style <= 4100) {
            // For style >=4000 we make the window transparent.
            // From 4000 to 4100 the window is 100% transparent to 100% opaque

            //ignore this style option when this is the canvas itself
            if (this == fMother)
               gVirtualX->DrawBox(px1,py1,px2,py2,TVirtualX::kFilled);
            else {
               //draw background by blitting all bottom pads
               int px, py;
               XYtoAbsPixel(GetX1(), GetY2(), px, py);

               fMother->CopyBackgroundPixmap(px, py);
               CopyBackgroundPixmaps(fMother, this, px, py);

               gVirtualX->SetOpacity(style-4000);
            }
         } else {
            gVirtualX->DrawBox(px1,py1,px2,py2,TVirtualX::kFilled);
         }
      } else {
         gVirtualX->DrawBox(px1,py1,px2,py2,TVirtualX::kHollow);
      }
   }

   if (gVirtualPS) {
      gVirtualPS->DrawBox(x1, y1, x2, y2);
   }

   Modified();
}

//______________________________________________________________________________
 void TPad::CopyBackgroundPixmaps(TPad *start, TPad *stop, Int_t x, Int_t y)
{
   // Copy pixmaps of pads laying below pad "stop" into pad "stop". This
   // gives the effect of pad "stop" being transparent.

   TObject *obj;
   TIter next(start->GetListOfPrimitives());
   while ((obj = next())) {
      if (obj->InheritsFrom(TPad::Class())) {
         if (obj == stop) break;
         ((TPad*)obj)->CopyBackgroundPixmap(x, y);
         ((TPad*)obj)->CopyBackgroundPixmaps((TPad*)obj, stop, x, y);
      }
   }
}

//______________________________________________________________________________
 void TPad::CopyBackgroundPixmap(Int_t x, Int_t y)
{
   // Copy pixmap of this pad as background of the current pad.

   int px, py;
   XYtoAbsPixel(GetX1(), GetY2(), px, py);
   gVirtualX->CopyPixmap(GetPixmapID(), px-x, py-y);
}

//______________________________________________________________________________
 void TPad::PaintFillArea(Int_t n, Float_t *x, Float_t *y, Option_t *)
{
//*-*-*-*-*-*-*-*-*Paint fill area in CurrentPad World coordinates*-*-*-*-*-*-*
//*-*              ===============================================

   TPoint *pxy;

//*-*- Create temporary array to store array in pixel coordinates
   if (n <=0) return;

   if (!gPad->IsBatch()) {
      if (n <kPXY) pxy = &gPXY[0];
      else         pxy = new TPoint[n+1];
//*-*- convert points from world to pixel coordinates
      for (Int_t i=0;i<n;i++) {
         pxy[i].fX = gPad->XtoPixel(x[i]);
         pxy[i].fY = gPad->YtoPixel(y[i]);
      }
//*-*- invoke the graphics subsystem
      if (gVirtualX->GetFillStyle() == 0) {
         pxy[n].fX = pxy[0].fX;
         pxy[n].fY = pxy[0].fY;
         gVirtualX->DrawFillArea(n+1,pxy);
      } else {
         gVirtualX->DrawFillArea(n,pxy);
      }
      if (n > kPXY) delete [] pxy;
   }

   if (gVirtualPS) {
      gVirtualPS->DrawPS(-n, x, y);
   }

   Modified();

}

//______________________________________________________________________________
 void TPad::PaintLine(Float_t x1, Float_t y1, Float_t x2, Float_t y2)
{
//*-*-*-*-*-*-*-*-*Paint line in CurrentPad World coordinates*-*-*-*-*-*-*-*
//*-*              ==========================================

   Float_t x[2], y[2];
   x[0] = x1;   x[1] = x2;   y[0] = y1;   y[1] = y2;

   //If line is totally clipped, return
   if (TestBit(kClipFrame)) {
      if (Clip(x,y,fUxmin,fUymin,fUxmax,fUymax) == 0) return;
   } else {
      if (Clip(x,y,fX1,fY1,fX2,fY2) == 0) return;
   }
   if (!gPad->IsBatch()) {
      Int_t px1 = XtoPixel(x[0]);
      Int_t px2 = XtoPixel(x[1]);
      Int_t py1 = YtoPixel(y[0]);
      Int_t py2 = YtoPixel(y[1]);

      gVirtualX->DrawLine(px1, py1, px2, py2);
   }

   if (gVirtualPS) {
      gVirtualPS->DrawPS(2, x, y);
   }

   Modified();
}

//______________________________________________________________________________
 void TPad::PaintLineNDC(Coord_t u1, Coord_t v1,Coord_t u2, Coord_t v2)
{
//*-*-*-*-*-*-*-*Draw a line with coordinates in NDC*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*            ===================================
   static Float_t xw[2], yw[2];
   if (!gPad->IsBatch()) {
      Int_t px1 = UtoPixel(u1);
      Int_t py1 = VtoPixel(v1);
      Int_t px2 = UtoPixel(u2);
      Int_t py2 = VtoPixel(v2);

      gVirtualX->DrawLine(px1, py1, px2, py2);
   }

   if (gVirtualPS) {
      xw[0] = GetX1() + u1*(GetX2() - GetX1());
      xw[1] = GetX1() + u2*(GetX2() - GetX1());
      yw[0] = GetY1() + v1*(GetY2() - GetY1());
      yw[1] = GetY1() + v2*(GetY2() - GetY1());
      gVirtualPS->DrawPS(2, xw, yw);
      gVirtualPS->PrintFast(2," s");
   }

   Modified();
}

//______________________________________________________________________________
 void TPad::PaintLine3D(Float_t *p1, Float_t *p2)
{
//*-*-*-*-*-*-*-*-*Paint 3-D line in the CurrentPad*-*-*-*-*-*-*-*-*-*-*
//*-*              ================================

   if (!fView) return;

//*-*- convert from 3-D to 2-D pad coordinate system
   Float_t xpad[6];
   fView->WCtoNDC(p1, &xpad[0]);
   fView->WCtoNDC(p2, &xpad[3]);
   PaintLine(xpad[0],xpad[1],xpad[3],xpad[4]);
}

//______________________________________________________________________________
 void TPad::PaintPolyLine(Int_t n, Float_t *x, Float_t *y, Option_t *)
{
//*-*-*-*-*-*-*-*-*Paint polyline in CurrentPad World coordinates*-*-*-*-*-*-*
//*-*              ==============================================

   if (n < 2) return;
   TPoint *pxy = &gPXY[0];
   if (!gPad->IsBatch()) {
      if (n >= kPXY) pxy = new TPoint[n+1];
   }
   Float_t xmin,xmax,ymin,ymax;
   if (TestBit(kClipFrame)) {
      xmin = fUxmin; ymin = fUymin; xmax = fUxmax; ymax = fUymax;
   } else {
      xmin = fX1; ymin = fY1; xmax = fX2; ymax = fY2;
   }
   Int_t i,j,i1=0,np=1;
   for (i=0; i<n-1; i++) {
      if (Clip(&x[i],&y[i],xmin,ymin,xmax,ymax)) {
         np++;
         if (i < n-2) continue;
      }
      if (np == 1) {i1 ++; continue;}
      if (!gPad->IsBatch()) {
         for (j=0;j<np;j++) {
            pxy[j].fX = XtoPixel(x[i1+j]);
            pxy[j].fY = YtoPixel(y[i1+j]);
         }
         gVirtualX->DrawPolyLine(np,pxy);
      }
      if (gVirtualPS) {
         gVirtualPS->DrawPS(np, &x[i1], &y[i1]);
      }
      i1++;
      np = 1;
   }
   if (!gPad->IsBatch()) {
      if (n >= kPXY)   delete [] pxy;
   }
   Modified();
}

//______________________________________________________________________________
 void TPad::PaintPolyLineNDC(Int_t n, Float_t *x, Float_t *y, Option_t *)
{
//*-*-*-*-*-*-*-*-*Paint polyline in CurrentPad NDC coordinates*-*-*-*-*-*-*
//*-*              ============================================

   TPoint *pxy;

//*-*- Create temporary array to store array in pixel coordinates
   if (n <=0) return;

   if (!gPad->IsBatch()) {
      if (n <kPXY) pxy = &gPXY[0];
      else         pxy = new TPoint[n+1];
//*-*- convert points from world to pixel coordinates
      for (Int_t i=0;i<n;i++) {
         pxy[i].fX = UtoPixel(x[i]);
         pxy[i].fY = VtoPixel(y[i]);
      }
//*-*- invoke the graphics subsystem
      gVirtualX->DrawPolyLine(n,pxy);
      if (n > kPXY)  delete [] pxy;
   }

   if (gVirtualPS) {
      gVirtualPS->DrawPS(n, x, y);
   }

   Modified();

}


//______________________________________________________________________________
 void TPad::PaintPolyLine3D(Int_t n, Float_t *p)
{
//*-*-*-*-*-*-*-*-*Paint 3-D polyline in the CurrentPad*-*-*-*-*-*-*-*-*-*-*
//*-*              ====================================

   if (!fView) return;

//*-*- Loop on each individual line

   Int_t i=3;
   while(i<3*n) {
      PaintLine3D(&p[3*i-3], &p[3*i]);
      i += 3;
   }

   Modified();
}

//______________________________________________________________________________
 void TPad::PaintPolyMarker(Int_t n, Float_t *x, Float_t *y, Option_t *)
{
//*-*-*-*-*-*-*-*-*Paint polymarker in CurrentPad World coordinates*-*-*-*-*-*
//*-*              ================================================

   TPoint *pxy;

   if (n <=0) return;
   Int_t i;
   if (!gPad->IsBatch()) {
      if (n <kPXY) pxy = &gPXY[0];
      else         pxy = new TPoint[n+1];
//*-*- convert points from world to pixel coordinates
      for (i=0;i<n;i++) {
         pxy[i].fX = XtoPixel(x[i]);
         pxy[i].fY = YtoPixel(y[i]);
      }
//*-*- invoke the graphics subsystem
      gVirtualX->DrawPolyMarker(n, pxy);
      if (n > kPXY)  delete [] pxy;
   }

   if (gVirtualPS) {
      gVirtualPS->DrawPolyMarker(n, x, y);
   }

   Modified();

}

//______________________________________________________________________________
 void TPad::PaintText(Float_t x, Float_t y, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*Paint text in CurrentPad World coordinates*-*-*-*-*-*-*-*
//*-*              ==========================================


   Modified();

   if (!gPad->IsBatch()) {
      Int_t px = XtoPixel(x);
      Int_t py = YtoPixel(y);
      Float_t angle = gVirtualX->GetTextAngle();

      gVirtualX->DrawText(px, py, angle, gVirtualX->GetTextMagnitude(), text, TVirtualX::kClear);
   }

   if (gVirtualPS) {
      if (x < fX1) x = fX1;
      if( x > fX2) x = fX2;
      if (y < fY1) x = fY1;
      if( y > fY2) x = fY2;
      gVirtualPS->Text(x, y, text);
   }

}

//______________________________________________________________________________
 void TPad::PaintTextNDC(Float_t u, Float_t v, const Text_t *text)
{
//*-*-*-*-*-*-*-*-*Paint text in CurrentPad NDC coordinates*-*-*-*-*-*-*-*
//*-*              ========================================


   Modified();

   if (!gPad->IsBatch()) {
      Int_t px = UtoPixel(u);
      Int_t py = VtoPixel(v);
      Float_t angle = gVirtualX->GetTextAngle();

      gVirtualX->DrawText(px, py, angle, gVirtualX->GetTextMagnitude(), text, TVirtualX::kClear);
   }

   if (gVirtualPS) {
      Float_t x = GetX1() + u*(GetX2() - GetX1());
      Float_t y = GetY1() + v*(GetY2() - GetY1());
      if (x < fX1 || x > fX2) return;
      if (y < fY1 || y > fY2) return;
      gVirtualPS->Text(x, y, text);
   }

}

//______________________________________________________________________________
 TPad *TPad::Pick(Int_t px, Int_t py, TObjLink *&pickobj)
{
//*-*-*-*-*-*-*-*-*Search for an object at pixel position px,py*-*-*-*-*-*-*
//*-*              ============================================
//  Check if point is in this pad.
//  If yes, check if it is in one of the subpads
//  If found in the pad, compute closest distance of approach
//  to each primitive.
//  If one distance of approach is found to be within the limit Distancemaximum
//  the corresponding primitive is selected and the routine returns.
//

   //the two following statements are necessary under NT (multithreaded)
   //when a TCanvas object is being created and a thread calling TPad::Pick
   //before the TPad constructor has completed in the other thread
   if (gPad == 0) return 0; //Andy Haas
   if (GetListOfPrimitives() == 0) return 0; //Andy Haas

   Int_t dist;
//*-*- Search if point is in pad itself
   Float_t x = AbsPixeltoX(px);
   Float_t y = AbsPixeltoY(py);
   if (this != gPad->GetCanvas()) {
      if (!((x >= fX1 && x <= fX2) && (y >= fY1 && y <= fY2))) return 0;
   }

//*-*- search for a primitive in this pad or its subpads
   static TObjOptLink dummyLink(0,"");  //place holder for when no link available
   TPad *padsav = (TPad*)gPad;
   gPad  = this;    // since no drawing will be done, don't use cd() for efficiency reasons
   TPad *pick   = 0;
   TPad *picked = this;
   pickobj      = 0;
   if (DistancetoPrimitive(px,py) < kDistanceMaximum) {
      dummyLink.SetObject(this);
      pickobj = &dummyLink;
   }

   // Loop backwards over the list of primitives. The first non-pad primitive
   // found is the selected one. However, we have to keep going down the
   // list to see if there is maybe a pad overlaying the primitive. In that
   // case look into the pad for a possible primitive. Once a pad has been
   // found we can terminate the loop.
   Bool_t gotPrim = kFALSE;      // true if found a non pad primitive
   TObjLink *lnk = GetListOfPrimitives()->LastLink();
   while (lnk) {
      TObject *obj = lnk->GetObject();
      fPadPointer  = obj;
      if (obj->InheritsFrom(TPad::Class())) {
         pick = ((TPad*)obj)->Pick(px, py, pickobj);
         if (pick) {
            picked = pick;
            break;
         }
      } else if (!gROOT->GetEditorMode()) {
         if (!gotPrim) {
            if (!obj->TestBit(kCannotPick)) {
               dist = obj->DistancetoPrimitive(px, py);
               if (dist < kDistanceMaximum) {
                  pickobj = lnk;
                  gotPrim = kTRUE;
                  if (dist == 0) break;
               }
            }
         }
      }

      lnk = lnk->Prev();
   }

   if (picked->InheritsFrom(TButton::Class())) {
      TButton *button = (TButton*)picked;
      if (!button->GetMother()->IsEditable()) pickobj = 0;
   }

   gPad = padsav;
   return picked;
}

//___________________________________________________________________________
 void TPad::Pop()
{
//*-*-*-*-*-*-*-*-*-*-*Pop pad to the top of the stack*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ===============================
   if (this == fMother->GetListOfPrimitives()->Last()) return;

   TListIter next(fMother->GetListOfPrimitives());
   TObject *obj;
   while ((obj = next()))
      if (obj == this) {
         char *opt = StrDup(next.GetOption());
         fMother->GetListOfPrimitives()->Remove(this);
         fMother->GetListOfPrimitives()->AddLast(this, opt);
         delete [] opt;
         return;
      }
}


//______________________________________________________________________________
 void TPad::Print(const Text_t *filename)
{
//*-*-*-*-*Old interface. Use SaveAs instead*-*-*-*-*-*
//*-*      =================================
//

   SaveAs(filename);

}

//______________________________________________________________________________
 void TPad::Print(const Text_t *filename, Option_t *option)
{
//*-*-*-*-*Save Pad contents on a file in various formats*-*-*-*-*-*
//*-*      ==============================================
//
//   if option  =  0   - as "ps"
//               "ps"  - Postscript file is produced
//               "eps" - an Encapsulated Postscript file is produced
//               "gif" - a GIF file is produced
//               "cxx" - a C++ macro file is produced
//
//     filename = 0 - filename  is defined by the GetName and its
//                    extension is defined with the option
//

   char psname[264];
   Int_t lenfil =  filename ? strlen(filename) : 0;
   const char *opt = option;

//*-*   Set the default option as "Postscript" (Should be a data member of Tpad)

   const char *opt_default="ps";
   if( !opt ) opt = opt_default;

   if ( !lenfil )  sprintf(psname,"%s.%s",GetName(),opt);
   else            strcpy(psname,filename);

   // line below protected against case like c1->SaveAs( "../ps/cs.ps" );
   if ((psname[0] == '.') && (strchr(psname,'/') == 0)) sprintf(psname,"%s%s",GetName(),filename);

   if (strstr(opt,"gif")) {
      if (GetCanvas()->IsBatch()) {
         Printf("Cannot create gif file in batch mode.");
         return;
      }
      Update();
      Int_t canvasid = GetCanvas()->GetCanvasID();
      gVirtualX->SelectWindow(canvasid);
      gVirtualX->WriteGIF(psname);
      Printf("GIF file: %s has been created.",psname);
      return;
   }

   if (strstr(opt,"cxx")) {
      GetCanvas()->SaveSource(psname,"");
      return;
   }
   if (strstr(opt,"root")) {
      TDirectory *dirsav = gDirectory;
      TFile *fsave = new TFile(psname,"RECREATE");
      Write();
      fsave->Close();
      delete fsave;
      if (dirsav) dirsav->cd();
      Printf("ROOT file: %s has been created",psname);
      return;
   }

   // in case we read directly from a Root file and teh canvas
   // is not on the screen, set batch mode
   Bool_t noScreen = kFALSE;
   if (!GetCanvas()->IsBatch() && GetCanvas()->GetCanvasID() == -1) {
      noScreen = kTRUE;
      GetCanvas()->SetBatch(kTRUE);
   }
   Int_t pstype = 111;
   Float_t xcanvas = GetCanvas()->XtoPixel(GetCanvas()->GetX2());
   Float_t ycanvas = GetCanvas()->YtoPixel(GetCanvas()->GetY1());
   Float_t ratio   = ycanvas/xcanvas;
   if (ratio < 1)               pstype = 112;
   if (strstr(opt,"Portrait"))  pstype = 111;
   if (strstr(opt,"Landscape")) pstype = 112;
   if (strstr(opt,"eps")) pstype = 113;
   TPad *padsav = (TPad*)gPad;
   cd();
   TVirtualPS *psave = gVirtualPS;
   // check if Postscript class is in memory. If not, dynamic link
   if (gROOT->LoadClass("TPostScript","Postscript")) return;

   gROOT->ProcessLineFast(Form("new TPostScript("%s",%d)",psname,pstype));
   gVirtualPS->SetBit(kPrintingPS);
   Paint();
   gVirtualPS->Close();
   if (noScreen) GetCanvas()->SetBatch(kFALSE);
   Printf("PostScript file: %s has been created",psname);
   delete gVirtualPS;
   gVirtualPS = psave;
   padsav->cd();
}

//______________________________________________________________________________
 void TPad::Range(Float_t x1, Float_t y1, Float_t x2, Float_t y2)
{
//*-*-*-*-*-*-*-*-*-*-*Set world coordinate system for the pad*-*-*-*-*-*-*
//*-*                  =======================================

   if ((x1 >= x2) || (y1 >= y2)) {
      Error("Range", "illegal world coordinates range: x1=%f, y1=%f, x2=%f, y2=%f",x1,y1,x2,y2);
      return;
   }

   fUxmin = x1;
   fUxmax = x2;
   fUymin = y1;
   fUymax = y2;

   if (fX1 == x1 && fY1 == y1 && fX2 == x2 && fY2 == y2) return;

   fX1  = x1;
   fY1  = y1;
   fX2  = x2;
   fY2  = y2;

//*-*- Compute pad conversion coefficients
   ResizePad();
}

//______________________________________________________________________________
 void TPad::RangeAxis(Axis_t xmin, Axis_t ymin, Axis_t xmax, Axis_t ymax)
{
//*-*-*-*-*-*-*-*-*-*-*Set axis coordinate system for the pad*-*-*-*-*-*-*
//*-*                  =======================================
//  The axis coordinate system is a subset of the world coordinate system
//  xmin,ymin are the origin of the current coordinate system
//  xmax is the end of the X axis
//  ymax is the end of the Y axis
//  By default a margin of 10 per cent is left on all sides of the pad
//

   if ((xmin >= xmax) || (ymin >= ymax)) {
      Error("RangeAxis", "illegal axis coordinates range: xmin=%f, ymin=%f, xmax=%f, ymax=%f",
            xmin, ymin, xmax, ymax);
      return;
   }

   fUxmin  = xmin;
   fUymin  = ymin;
   fUxmax  = xmax;
   fUymax  = ymax;
}

//______________________________________________________________________________
 void TPad::RecursiveRemove(TObject *obj)
{
//*-*-*-*-*-*-*-*Recursively remove object from a pad and its subpads*-*-*-*-*
//*-*            ====================================================

   if (obj == fCanvas->GetSelected()) fCanvas->SetSelected(0);
   Int_t nold = fPrimitives->GetSize();
   fPrimitives->RecursiveRemove(obj);
   if (nold != fPrimitives->GetSize()) fModified = kTRUE;
}

//______________________________________________________________________________
 void TPad::RedrawAxis(Option_t *option)
{
//  Redraw the frame axis
//  Redrawing axis may be necessary in case of superimposed histograms
//  when one or more histograms have a fill color
//
   TString opt = option;
   opt.ToLower();
   TGaxis axis;
   Float_t xmin,ymin,xmax,ymax,gridl;
   gPad->GetRangeAxis(xmin,ymin,xmax,ymax);
//  redraw x axis
   axis.SetLineColor(gStyle->GetAxisColor("X"));
   axis.SetTextColor(gStyle->GetLabelColor("X"));
   axis.SetTextFont(gStyle->GetLabelFont("X"));
   axis.SetLabelFont(gStyle->GetLabelFont("X"));
   axis.SetLabelSize(gStyle->GetLabelSize("X"));
   axis.SetLabelOffset(gStyle->GetLabelOffset("X"));
   axis.SetTickSize(gStyle->GetTickLength("X"));
   Int_t ndiv =gStyle->GetNdivisions("X");
   if (opt.Contains("grid") && gPad->GetGridx()) {
      gridl = (fUymax-fUymin)/(gPad->GetY2() - gPad->GetY1());
      if (!gPad->GetLogx()) axis.DrawAxis(xmin,ymin,xmax,ymin,xmin,xmax,ndiv,"W",gridl);
      else   axis.DrawAxis(xmin,ymin,xmax,ymin,
                     TMath::Power(10,xmin),TMath::Power(10,xmax),ndiv,"GW",gridl);
   } else {
      if (!gPad->GetLogx()) axis.DrawAxis(xmin,ymin,xmax,ymin,xmin,xmax,ndiv);
      else   axis.DrawAxis(xmin,ymin,xmax,ymin,
                     TMath::Power(10,xmin),TMath::Power(10,xmax),ndiv,"G");
   }
//  redraw y axis
   axis.SetLineColor(gStyle->GetAxisColor("Y"));
   axis.SetTextColor(gStyle->GetLabelColor("Y"));
   axis.SetTextFont(gStyle->GetLabelFont("Y"));
   axis.SetLabelFont(gStyle->GetLabelFont("Y"));
   axis.SetLabelSize(gStyle->GetLabelSize("Y"));
   axis.SetLabelOffset(gStyle->GetLabelOffset("Y"));
   axis.SetTickSize(gStyle->GetTickLength("Y"));
   ndiv =gStyle->GetNdivisions("Y");
   if (opt.Contains("grid") && gPad->GetGridy()) {
      gridl = (fUxmax-fUxmin)/(gPad->GetX2() - gPad->GetX1());
      if (!gPad->GetLogy()) axis.DrawAxis(xmin,ymin,xmin,ymax,ymin,ymax,ndiv,"W",gridl);
      else   axis.DrawAxis(xmin,ymin,xmin,ymax,
                     TMath::Power(10,ymin),TMath::Power(10,ymax),ndiv,"GW",gridl);
   } else {
      if (!gPad->GetLogy()) axis.DrawAxis(xmin,ymin,xmin,ymax,ymin,ymax,ndiv);
      else   axis.DrawAxis(xmin,ymin,xmin,ymax,
                     TMath::Power(10,ymin),TMath::Power(10,ymax),ndiv,"G");
   }
}

//______________________________________________________________________________
 void TPad::ResizePad(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*Compute pad conversion coefficients*-*-*-*-*-*-*-*-*
//*-*                  ===================================
//
//   Conversion from x to px & y to py
//   =================================
//
//       x - xmin     px - pxlow              xrange  = xmax-xmin
//       --------  =  ----------      with
//        xrange        pxrange               pxrange = pxmax-pxmin
//
//               pxrange(x-xmin)
//   ==>  px =   ---------------  + pxlow   = fXtoPixelk + fXtoPixel * x
//                    xrange
//
//   ==>  fXtoPixelk = pxlow - pxrange*xmin/xrange
//        fXtoPixel  = pxrange/xrange
//           where  pxlow   = fAbsXlowNDC*fCw
//                  pxrange = fAbsWNDC*fCw
//
//
//       y - ymin     py - pylow              yrange  = ymax-ymin
//       --------  =  ----------      with
//        yrange        pyrange               pyrange = pymax-pymin
//
//               pyrange(y-ymin)
//   ==>  py =   ---------------  + pylow   = fYtoPixelk + fYtoPixel * y
//                    yrange
//
//   ==>  fYtoPixelk = pylow - pyrange*ymin/yrange
//        fYtoPixel  = pyrange/yrange
//           where  pylow   = (1-fAbsYlowNDC)*fCh
//                  pyrange = -fAbsHNDC*fCh
//
//-  Conversion from px to x & py to y
//   =================================
//
//             xrange(px-pxlow)
//   ==>  x =  ----------------  + xmin  = fPixeltoXk + fPixeltoX * px
//                 pxrange
//-
//   ==>  fPixeltoXk = xmin - pxlow*xrange/pxrange
//        fPixeltoX  = xrange/pxrange
//
//             yrange(py-pylow)
//   ==>  y =  ----------------  + ymin  = fPixeltoYk + fPixeltoY * py
//                 pyrange
//-
//   ==>  fPixeltoYk = ymin - pylow*yrange/pyrange
//        fPixeltoY  = yrange/pyrange
//
//-----------------------------------------------------------------------
//
//  Computation of the coefficients in case of LOG scales
//- =====================================================
//
//   A, Conversion from pixel coordinates to world coordinates
//
//       Log(x) - Log(xmin)      Log(x/xmin)       px - pxlow
//  u = --------------------- =  -------------  =  -----------
//      Log(xmax) - Log(xmin)    Log(xmax/xmin)     pxrange
//
//  ==> Log(x/xmin) = u*Log(xmax/xmin)
//      x = xmin*exp(u*Log(xmax/xmin)
//   Let alfa = Log(xmax/xmin)/fAbsWNDC
//
//      x = xmin*exp(-alfa*pxlow) + exp(alfa*px)
//      x = fPixeltoXk*exp(fPixeltoX*px)
//  ==> fPixeltoXk = xmin*exp(-alfa*pxlow)
//      fPixeltoX  = alfa
//
//       Log(y) - Log(ymin)      Log(y/ymin)       pylow - py
//  v = --------------------- =  -------------  =  -----------
//      Log(ymax) - Log(ymin)    Log(ymax/ymin)     pyrange
//
//   Let beta = Log(ymax/ymin)/pyrange
//      Log(y/ymin) = beta*pylow - beta*py
//      y/ymin = exp(beta*pylow - beta*py)
//      y = ymin*exp(beta*pylow)*exp(-beta*py)
//  ==> y = fPixeltoYk*exp(fPixeltoY*py)
//      fPixeltoYk = ymin*exp(beta*pylow)
//      fPixeltoY  = -beta
//
//-  B, Conversion from World coordinates to pixel coordinates
//
//  px = pxlow + u*pxrange
//     = pxlow + Log(x/xmin)/alfa
//     = pxlow -Log(xmin)/alfa  + Log(x)/alfa
//     = fXtoPixelk + fXtoPixel*Log(x)
//  ==> fXtoPixelk = pxlow -Log(xmin)/alfa
//  ==> fXtoPixel  = 1/alfa
//
//  py = pylow - Log(y/ymin)/beta
//     = fYtoPixelk + fYtoPixel*Log(y)
//  ==> fYtoPixelk = pylow - Log(ymin)/beta
//      fYtoPixel  = 1/beta
//


//*-*- Recompute subpad positions in case pad has been moved/resized
   TPad *parent = fMother;
   if (this == gPad->GetCanvas()) {
      fAbsXlowNDC  = fXlowNDC;
      fAbsYlowNDC  = fYlowNDC;
      fAbsWNDC     = fWNDC;
      fAbsHNDC     = fHNDC;
   }
   else {
      fAbsXlowNDC  = fXlowNDC*parent->GetAbsWNDC() + parent->GetAbsXlowNDC();
      fAbsYlowNDC  = fYlowNDC*parent->GetAbsHNDC() + parent->GetAbsYlowNDC();
      fAbsWNDC     = fWNDC*parent->GetAbsWNDC();
      fAbsHNDC     = fHNDC*parent->GetAbsHNDC();
   }

   Float_t ww = (Float_t)gPad->GetWw();
   Float_t wh = (Float_t)gPad->GetWh();
   Float_t pxlow   = fAbsXlowNDC*ww;
   Float_t pylow   = (1-fAbsYlowNDC)*wh;
   Float_t pxrange = fAbsWNDC*ww;
   Float_t pyrange = -fAbsHNDC*wh;

//*-*- Linear X axis
   Float_t xrange  = fX2 - fX1;
   fXtoAbsPixelk = 0.5 + pxlow - pxrange*fX1/xrange;      //origin at left
   fXtoPixelk = -pxrange*fX1/xrange;
   fXtoPixel  = pxrange/xrange;
   fAbsPixeltoXk = fX1 - pxlow*xrange/pxrange;
   fPixeltoXk = fX1;
   fPixeltoX  = xrange/pxrange;
//*-*- Linear Y axis
   Float_t yrange  = fY2 - fY1;
   fYtoAbsPixelk = 0.5 + pylow - pyrange*fY1/yrange;      //origin at top
   fYtoPixelk = -pyrange - pyrange*fY1/yrange;
   fYtoPixel  = pyrange/yrange;
   fAbsPixeltoYk = fY1 - pylow*yrange/pyrange;
   fPixeltoYk = fY1;
   fPixeltoY  = yrange/pyrange;

//*-*- Coefficients to convert from pad NDC coordinates to pixel coordinates

   fUtoAbsPixelk = 0.5 + pxlow;
   fUtoPixelk = 0.0;
   fUtoPixel  = pxrange;
   fVtoAbsPixelk = 0.5 + pylow;
   fVtoPixelk = -pyrange;
   fVtoPixel  = pyrange;

//*-*- Coefficients to convert from canvas pixels to pad world coordinates

//*-*- Resize all subpads
   TObject *obj;
   TIter    next(GetListOfPrimitives());
   while ((obj = next())) {
      if (obj->InheritsFrom(TPad::Class()))
         ((TPad*)obj)->ResizePad(option);
   }

//*-*- Reset all current sizes
   if (gPad->IsBatch())
      fPixmapID = 0;
   else {
      gVirtualX->SetLineWidth(-1);
      gVirtualX->SetTextSize(-1);

      // create or re-create off-screen pixmap
      if (fPixmapID) {
         int w = TMath::Abs(XtoPixel(fX2) - XtoPixel(fX1));
         int h = TMath::Abs(YtoPixel(fY2) - YtoPixel(fY1));
         if (fPixmapID == -1)       // this case is handled via the ctor
            fPixmapID = gVirtualX->OpenPixmap(w, h);
         else
            if (gVirtualX->ResizePixmap(fPixmapID, w, h)) Modified(kTRUE);
      }
   }
}


//______________________________________________________________________________
 void TPad::SaveAs(const Text_t *filename)
{
//*-*-*-*-*Save Pad contents on a  file in various formats*-*-*-*-*-*
//*-*      ===============================================
//
//   if filename is "", the file produced is padname.ps
//   if filename starts with a dot, the padname is added in front
//   if filename contains .eps, an Encapsulated Postscript file is produced
//   if filename contains .gif, a GIF file is produced
//   if filename contains .C or .cxx, a C++ macro file is produced
//   if filename contains .root, a Root file is produced
//

   char psname[264];
   Int_t lenfil =  filename ? strlen(filename) : 0;

   if (!lenfil)  sprintf(psname,"%s.ps",GetName());
   else          strcpy(psname,filename);

   // line below protected against case like c1->SaveAs( "../ps/cs.ps" );
   if ((psname[0] == '.') && (strchr(psname,'/') == 0)) sprintf(psname,"%s%s",GetName(),filename);

   if (strstr(psname,".gif"))
               Print(psname,"gif");
   else if (strstr(psname,".C") || strstr(psname,".cxx") || strstr(psname,".cpp"))
               Print(psname,"cxx");
   else if (strstr(psname,".root"))
               Print(psname,"root");
   else if (strstr(psname,".eps"))
               Print(psname,"eps");
   else
               Print(psname,"ps");

 }

//______________________________________________________________________________
 void TPad::SavePrimitive(ofstream &out, Option_t *)
{
//*-*-*-*-*-*Save primitives in this pad on the C++ source file out*-*-*-*-*-*
//*-*        ======================================================

   TPad *padsav = (TPad*)gPad;
   char quote='"';
//   Write pad parameters
   if (this != gPad->GetCanvas()) {
      out <<"  "<<endl;
      out <<"// ------------>Primitives in pad: "<<GetName()<<endl;

      if (gROOT->ClassSaved(TPad::Class())) {
         out<<"   ";
      } else {
         out<<"   TPad *";
      }
      out<<GetName()<<" = new TPad("<<quote<<GetName()<<quote<<", "<<quote<<GetTitle()
      <<quote
      <<","<<fXlowNDC
      <<","<<fYlowNDC
      <<","<<fXlowNDC+fWNDC
      <<","<<fYlowNDC+fHNDC
      <<");"<<endl;
      out<<"   "<<GetName()<<"->Draw();"<<endl;
      out<<"   "<<GetName()<<"->cd();"<<endl;
   }
   out<<"   "<<GetName()<<"->Range("<<fX1<<","<<fY1<<","<<fX2<<","<<fY2<<");"<<endl;
   TView *view = GetView();
   Float_t rmin[3], rmax[3];
   if (view) {
      view->GetRange(rmin, rmax);
      out<<"   TView *view = new TView(1);"<<endl;
      out<<"   view->SetRange("<<rmin[0]<<","<<rmin[1]<<","<<rmin[2]<<","
                               <<rmax[0]<<","<<rmax[1]<<","<<rmax[2]<<");"<<endl;
   }
   out<<"   "<<GetName()<<"->SetFillColor("<<GetFillColor()<<");"<<endl;
   if (GetBorderMode() != 1) {
      out<<"   "<<GetName()<<"->SetBorderMode("<<GetBorderMode()<<");"<<endl;
   }
   if (GetBorderSize() != 4) {
      out<<"   "<<GetName()<<"->SetBorderSize("<<GetBorderSize()<<");"<<endl;
   }
   if (GetLogx()) {
      out<<"   "<<GetName()<<"->SetLogx();"<<endl;
   }
   if (GetLogy()) {
      out<<"   "<<GetName()<<"->SetLogy();"<<endl;
   }
   if (GetLogz()) {
      out<<"   "<<GetName()<<"->SetLogz();"<<endl;
   }
   if (GetGridx()) {
      out<<"   "<<GetName()<<"->SetGridx();"<<endl;
   }
   if (GetGridy()) {
      out<<"   "<<GetName()<<"->SetGridy();"<<endl;
   }
   if (GetTickx()) {
      out<<"   "<<GetName()<<"->SetTickx();"<<endl;
   }
   if (GetTicky()) {
      out<<"   "<<GetName()<<"->SetTicky();"<<endl;
   }
   if (GetTheta() != 30) {
      out<<"   "<<GetName()<<"->SetTheta("<<GetTheta()<<");"<<endl;
   }
   if (GetPhi() != 30) {
      out<<"   "<<GetName()<<"->SetPhi("<<GetPhi()<<");"<<endl;
   }
   if (TMath::Abs(fLeftMargin-0.1) > 0.01) {
      out<<"   "<<GetName()<<"->SetLeftMargin("<<GetLeftMargin()<<");"<<endl;
   }
   if (TMath::Abs(fRightMargin-0.1) > 0.01) {
      out<<"   "<<GetName()<<"->SetRightMargin("<<GetRightMargin()<<");"<<endl;
   }
   if (TMath::Abs(fTopMargin-0.1) > 0.01) {
      out<<"   "<<GetName()<<"->SetTopMargin("<<GetTopMargin()<<");"<<endl;
   }
   if (TMath::Abs(fBottomMargin-0.1) > 0.01) {
      out<<"   "<<GetName()<<"->SetBottomMargin("<<GetBottomMargin()<<");"<<endl;
   }

   if (fFrame) {
      if (fFrame->GetFillColor() != GetFillColor()) {
         out<<"   "<<GetName()<<"->SetFrameFillColor("<<fFrame->GetFillColor()<<");"<<endl;
      }
      if (fFrame->GetFillStyle() != 1001) {
         out<<"   "<<GetName()<<"->SetFrameFillStyle("<<fFrame->GetFillStyle()<<");"<<endl;
      }
      if (fFrame->GetLineStyle() != 1) {
         out<<"   "<<GetName()<<"->SetFrameLineStyle("<<fFrame->GetLineStyle()<<");"<<endl;
      }
      if (fFrame->GetLineColor() != 1) {
         out<<"   "<<GetName()<<"->SetFrameLineColor("<<fFrame->GetLineColor()<<");"<<endl;
      }
      if (fFrame->GetLineWidth() != 1) {
         out<<"   "<<GetName()<<"->SetFrameLineWidth("<<fFrame->GetLineWidth()<<");"<<endl;
      }
      if (fFrame->GetBorderMode() != 1) {
         out<<"   "<<GetName()<<"->SetFrameBorderMode("<<fFrame->GetBorderMode()<<");"<<endl;
      }
      if (fFrame->GetBorderSize() != 1) {
         out<<"   "<<GetName()<<"->SetFrameBorderSize("<<fFrame->GetBorderSize()<<");"<<endl;
      }
   }

   TIter next(GetListOfPrimitives());
   TObject *obj;

   while ((obj = next()))
         obj->SavePrimitive(out, (Option_t *)next.GetOption());
   out<<"   "<<GetName()<<"->Modified();"<<endl;
   out<<"   "<<padsav->GetName()<<"->cd();"<<endl;
   if (padsav) padsav->cd();
}

//______________________________________________________________________________
 void TPad::SetEditable(Bool_t mode)
{
   // Set pad editable yes/no
   // If a pad is not editable, one cannot modify the pad and its objects
   // via the mouse.

   fIsEditable = mode;

   TObject *obj;
   TIter    next(GetListOfPrimitives());
   while ((obj = next())) {
      if (obj->InheritsFrom(TPad::Class())) {
         TPad *pad = (TPad*)obj;
         pad->SetEditable(mode);
      }
   }
}

//______________________________________________________________________________
 void TPad::SetFillStyle(Style_t fstyle)
{
   // Overrride TAttFill::FillStyle for TPad because we want to handle style=0
   // as style 4000.

   if (fstyle == 0) fstyle = 4000;
   TAttFill::SetFillStyle(fstyle);
}

//______________________________________________________________________________
 void TPad::SetLogx(Int_t value)
{
//*-*-*-*-*-*-*-*-*Set Lin/Log scale for X
//*-*              ========================
   if (value) fLogx = 1;
   else       fLogx = 0;
}

//______________________________________________________________________________
 void TPad::SetLogy(Int_t value)
{
//*-*-*-*-*-*-*-*-*Set Lin/Log scale for Y
//*-*              ========================
   if (value) fLogy = 1;
   else       fLogy = 0;
}

//______________________________________________________________________________
 void TPad::SetLogz(Int_t value)
{
//*-*-*-*-*-*-*-*-*Set Lin/Log scale for Z
//*-*              ========================
   if (value) fLogz = 1;
   else       fLogz = 0;
}

//______________________________________________________________________________
 void TPad::SetPad(Float_t xlow, Float_t ylow, Float_t xup, Float_t yup)
{
//*-*-*-*-*-*-*-*-*Set canvas range for pad*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*              ========================

  fXlowNDC = xlow;
  fYlowNDC = ylow;
  fWNDC    = xup - xlow;
  fHNDC    = yup - ylow;

  ResizePad();
}

//______________________________________________________________________________
 void TPad::SetPad(const Text_t *name, const Text_t *title,
                  Float_t xlow, Float_t ylow, Float_t xup, Float_t yup,
                  Color_t color, Short_t bordersize, Short_t bordermode)
{
//*-*-*-*-*-*-*-*-*Set all pad parameters*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*              ======================
   fName  = name;
   fTitle = title;
   SetFillStyle(1001);
   SetBottomMargin(gStyle->GetPadBottomMargin());
   SetTopMargin(gStyle->GetPadTopMargin());
   SetLeftMargin(gStyle->GetPadLeftMargin());
   SetRightMargin(gStyle->GetPadRightMargin());
   if (color >= 0)   SetFillColor(color);
   else              SetFillColor(gStyle->GetPadColor());
   if (bordersize <  0) fBorderSize = gStyle->GetPadBorderSize();
   else                 fBorderSize = bordersize;
   if (bordermode < -1) fBorderMode = gStyle->GetPadBorderMode();
   else                 fBorderMode = bordermode;

   SetPad(xlow, ylow, xup, yup);
}

//______________________________________________________________________________
 void TPad::SetAttFillPS(Color_t color, Style_t style)
{
//*-*-*-*-*-*-*-*-*Set postscript fill area attributes*-*-*-*-*-*-*-*-*-*-*
//*-*              ===================================

   if (gVirtualPS) {
      gVirtualPS->SetFillColor(color);
      gVirtualPS->SetFillStyle(style);
   }
}

//______________________________________________________________________________
 void TPad::SetAttLinePS(Color_t color, Style_t style, Width_t lwidth)
{
//*-*-*-*-*-*-*-*-*Set postscript line attributes*-*-*-*-*-*-*-*-*-*-*
//*-*              ==============================

   if (gVirtualPS) {
      gVirtualPS->SetLineColor(color);
      gVirtualPS->SetLineStyle(style);
      gVirtualPS->SetLineWidth(lwidth);
   }
}

//______________________________________________________________________________
 void TPad::SetAttMarkerPS(Color_t color, Style_t style, Size_t msize)
{
//*-*-*-*-*-*-*-*-*Set postscript marker attributes*-*-*-*-*-*-*-*-*-*-*
//*-*              ================================

   if (gVirtualPS) {
      gVirtualPS->SetMarkerColor(color);
      gVirtualPS->SetMarkerStyle(style);
      gVirtualPS->SetMarkerSize(msize);
   }
}

//______________________________________________________________________________
 void TPad::SetAttTextPS(Int_t align, Float_t angle, Color_t color, Style_t font, Float_t tsize)
{
//*-*-*-*-*-*-*-*-*Set postscript text attributes*-*-*-*-*-*-*-*-*-*-*
//*-*              ==============================

   if (gVirtualPS) {
      gVirtualPS->SetTextAlign(align);
      gVirtualPS->SetTextAngle(angle);
      gVirtualPS->SetTextColor(color);
      gVirtualPS->SetTextFont(font);
      gVirtualPS->SetTextSize(tsize);
   }
}

//______________________________________________________________________________
 void TPad::SetToolTipText(const char *text, Long_t delayms)
{
   // Set tool tip text associated with this pad. The delay is in
   // milliseconds (minimum 250). To remove tool tip call method with
   // text = 0.

   if (fTip) {
      DeleteToolTip(fTip);
      fTip = 0;
   }

   if (text && strlen(text))
      fTip = CreateToolTip((TBox*)0, text, delayms);
}

//_______________________________________________________________________
 void TPad::Streamer(TBuffer &b)
{
//*-*-*-*-*-*-*-*-*Stream a class object*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*              =========================================

   Int_t nch, nobjects;
   TObject *obj;
   if (b.IsReading()) {
      Version_t v = b.ReadVersion();
      if (v < 3) {   //old TPad derived from TWbox
         b.ReadVersion();   //      TVirtualPad::Streamer(b)
         b.ReadVersion();   //      TWbox::Streamer(b)
         b.ReadVersion();   //      TBox::Streamer(b)
         TObject::Streamer(b);
         TAttLine::Streamer(b);
         TAttFill::Streamer(b);
         b >> fX1;
         b >> fY1;
         b >> fX2;
         b >> fY2;
         b >> fBorderSize;
         b >> fBorderMode;
         TAttPad::Streamer(b);
      } else {  //new TPad
         TVirtualPad::Streamer(b);
         TAttPad::Streamer(b);
         b >> fX1;
         b >> fY1;
         b >> fX2;
         b >> fY2;
         b >> fBorderSize;
         b >> fBorderMode;
      }
      b >> fLogx;
      b >> fLogy;
      b >> fLogz;
      b >> fXtoAbsPixelk;
      b >> fXtoPixelk;
      b >> fXtoPixel;
      b >> fYtoAbsPixelk;
      b >> fYtoPixelk;
      b >> fYtoPixel;
      b >> fUtoAbsPixelk;
      b >> fUtoPixelk;
      b >> fUtoPixel;
      b >> fVtoAbsPixelk;
      b >> fVtoPixelk;
      b >> fVtoPixel;
      b >> fAbsPixeltoXk;
      b >> fPixeltoXk;
      b >> fPixeltoX;
      b >> fAbsPixeltoYk;
      b >> fPixeltoYk;
      b >> fPixeltoY;
      b >> fXlowNDC;
      b >> fYlowNDC;
      b >> fWNDC;
      b >> fHNDC;
      b >> fAbsXlowNDC;
      b >> fAbsYlowNDC;
      b >> fAbsWNDC;
      b >> fAbsHNDC;
      b >> fUxmin;
      b >> fUymin;
      b >> fUxmax;
      b >> fUymax;

      if (readLevel == 0) fMother = (TPad*)gROOT->GetSelectedPad();
      else                fMother = (TPad*)gPad;
      if (!fMother) fMother = (TPad*)gPad;
      if (fMother)  fCanvas = fMother->GetCanvas();
      fPixmapID   = -1;      // -1 means pixmap will be created by ResizePad()
//-------------------------
// read objects and their drawing options
//      b >> fPrimitives;
      readLevel++;
      gROOT->SetReadingBasket(kTRUE);
      TPad *padsav = (TPad*)gPad;
      gPad = this;
      fPrimitives = new TList(this);
      b >> nobjects;
      char drawoption[64];
      for (Int_t i = 0; i < nobjects; i++) {
         b >> obj;
         b >> nch;
         b.ReadFastArray(drawoption,nch);
         fPrimitives->AddLast(obj, drawoption);
         gPad = padsav; // gPad may be modified in b >> obj if obj is a pad
      }
      readLevel--;
      gROOT->SetReadingBasket(kFALSE);
//-------------------------
      fName.Streamer(b);
      fTitle.Streamer(b);
      b >> fPadPaint;
      fModified = kTRUE;
      b >> fGridx;
      b >> fGridy;
      b >> fFrame;
      b >> fView;
      b >> fTheta;
      b >> fPhi;
      fPadPointer = 0;
      b >> fNumber;
      b >> fAbsCoord;
      if (v > 1) {
         b >> fTickx;
         b >> fTicky;
      } else {
         fTickx = fTicky = 0;
      }
      if (readLevel == 0 && IsA() == TPad::Class()) ResizePad();
   } else {
      b.WriteVersion(TPad::IsA());
      TVirtualPad::Streamer(b);
      TAttPad::Streamer(b);
      b << fX1;
      b << fY1;
      b << fX2;
      b << fY2;
      b << fBorderSize;
      b << fBorderMode;
      b << fLogx;
      b << fLogy;
      b << fLogz;
      b << fXtoAbsPixelk;
      b << fXtoPixelk;
      b << fXtoPixel;
      b << fYtoAbsPixelk;
      b << fYtoPixelk;
      b << fYtoPixel;
      b << fUtoAbsPixelk;
      b << fUtoPixelk;
      b << fUtoPixel;
      b << fVtoAbsPixelk;
      b << fVtoPixelk;
      b << fVtoPixel;
      b << fAbsPixeltoXk;
      b << fPixeltoXk;
      b << fPixeltoX;
      b << fAbsPixeltoYk;
      b << fPixeltoYk;
      b << fPixeltoY;
      b << fXlowNDC;
      b << fYlowNDC;
      b << fWNDC;
      b << fHNDC;
      b << fAbsXlowNDC;
      b << fAbsYlowNDC;
      b << fAbsWNDC;
      b << fAbsHNDC;
      b << fUxmin;
      b << fUymin;
      b << fUxmax;
      b << fUymax;
//-------------------------
// save objects in pad and their drawing option
// This should be done automatically by TList::Streamer
//      b << fPrimitives;
      nobjects = fPrimitives->GetSize();
      b << nobjects;
      TIter next(fPrimitives);
      while ((obj = next())) {
         b << obj;
         nch = 1 + strlen(next.GetOption());
         b << nch;
         if (nch) b.WriteFastArray(next.GetOption(),nch);
      }
//-------------------------
      fName.Streamer(b);
      fTitle.Streamer(b);
      b << fPadPaint;
      b << fGridx;
      b << fGridy;
      b << fFrame;
      b << fView;
      b << fTheta;
      b << fPhi;
      b << fNumber;
      b << fAbsCoord;
      b << fTickx;
      b << fTicky;
   }
}

//______________________________________________________________________________
 void TPad::UseCurrentStyle()
{
//*-*-*-*-*-*Force a copy of current style for all objects in pad*-*-*-*-*
//*-*        ====================================================

   SetFillColor(gStyle->GetCanvasColor());
   SetBottomMargin(gStyle->GetPadBottomMargin());
   SetTopMargin(gStyle->GetPadTopMargin());
   SetLeftMargin(gStyle->GetPadLeftMargin());
   SetRightMargin(gStyle->GetPadRightMargin());
   fBorderSize = gStyle->GetPadBorderSize();
   fBorderMode = gStyle->GetPadBorderMode();
   fGridx = gStyle->GetPadGridX();
   fGridy = gStyle->GetPadGridY();
   fTickx = gStyle->GetPadTickX();
   fTicky = gStyle->GetPadTickY();

   TIter next(GetListOfPrimitives());
   TObject *obj;

   while ((obj = next())) {
      obj->UseCurrentStyle();
   }

   TPaveText *stats  = (TPaveText*)GetPrimitive("stats");
   if (stats) {
      stats->SetFillColor(gStyle->GetStatColor());
      stats->SetBorderSize(gStyle->GetStatBorderSize());
   }

   TPaveText *title  = (TPaveText*)GetPrimitive("title");
   if (title) {
      title->SetFillColor(gStyle->GetTitleColor());
      title->SetBorderSize(gStyle->GetTitleBorderSize());
   }
   if (fFrame) {
      fFrame->SetFillColor(gStyle->GetFrameFillColor());
      fFrame->SetFillStyle(gStyle->GetFrameFillStyle());
      fFrame->SetLineColor(gStyle->GetFrameLineColor());
      fFrame->SetLineStyle(gStyle->GetFrameLineStyle());
      fFrame->SetLineWidth(gStyle->GetFrameLineWidth());
      fFrame->SetBorderSize(gStyle->GetFrameBorderSize());
      fFrame->SetBorderMode(gStyle->GetFrameBorderMode());
   }

   Modified();
}

//______________________________________________________________________________
 TObject *TPad::CreateToolTip(const TBox *box, const char *text, Long_t delayms)
{
   // Create a tool tip and return its pointer.

#ifndef WIN32
   if (gPad->IsBatch()) return 0;
   // return new TGToolTip(box, text, delayms);
   return (TObject*)gROOT->ProcessLineFast(Form("new TGToolTip((TBox*)0x%lx,"%s",%d)",
                                           (Long_t)box,text,(Int_t)delayms));
#else
   return 0;
#endif
}

//______________________________________________________________________________
 void TPad::DeleteToolTip(TObject *tip)
{
   // Delete tool tip object.

#ifndef WIN32
   // delete tip;
   if (!tip) return;
   gROOT->ProcessLineFast(Form("delete (TGToolTip*)0x%lx", (Long_t)tip));
#endif
}

//______________________________________________________________________________
 void TPad::ResetToolTip(TObject *tip)
{
   // Reset tool tip, i.e. within time specified in CreateToolTip the
   // tool tip will pop up.

#ifndef WIN32
   if (!tip) return;
   // tip->Reset(this);
   gROOT->ProcessLineFast(Form("((TGToolTip*)0x%lx)->Reset((TPad*)0x%lx)",
                          (Long_t)tip,(Long_t)this));
#endif
}

//______________________________________________________________________________
 void TPad::CloseToolTip(TObject *tip)
{
   // Hide tool tip.

#ifndef WIN32
   if (!tip) return;
   // tip->Hide();
   gROOT->ProcessLineFast(Form("((TGToolTip*)0x%lx)->Hide()",(Long_t)tip));
#endif
}

//______________________________________________________________________________
 void TPad::x3d(Option_t *option)
{
//*-*-*-*-*-*Invokes the x3d package to view the content of a pad*-*-*-*-*-*-*
//*-*        ====================================================

#ifndef WIN32
   if (!strcasecmp(option, "OPENGL"))
#endif
   {
      // Disconnect the previous 3D context
      if (fPadView3D) fPadView3D->SetPad(0);
      fPadView3D = gVirtualGL->CreatePadGLView(this);
      if (!fPadView3D) {
#ifdef WIN32
         Warning("x3d", "loading OpenGL viewer (gSystem->Load(\"Root_RGL.DLL\")");
         if (gSystem->Load("Root_RGL.DLL"))
            Error("x3d", "failed to load OpenGL viewer");
#else
         gROOT->Macro("GL.C");
#endif
         fPadView3D = gVirtualGL->CreatePadGLView(this);
         if (!fPadView3D)
            Error("x3d", "OpenGL shared libraries not loaded");
      }
      if (fPadView3D) {
          Modified();
          Update();
      }
      return;
   }

#ifndef WIN32
   if (gROOT->LoadClass("TViewerX3D","X3d")) return;

   gROOT->ProcessLineFast(Form("TViewerX3D::View((TVirtualPad*)0x%lx,\"%s\")",
                          (Long_t)this,option));
#endif
}


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.