// @(#)root/graf:$Name:  $:$Id: TGaxis.cxx,v 1.72 2004/06/16 08:51:25 brun Exp $
// Author: Rene Brun, Olivier Couet   12/12/94

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

#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>

#include "Riostream.h"
#include "TROOT.h"
#include "TGaxis.h"
#include "TVirtualPad.h"
#include "TVirtualX.h"
#include "TLine.h"
#include "TLatex.h"
#include "TStyle.h"
#include "TF1.h"
#include "TAxis.h"
#include "THashList.h"
#include "TObjString.h"
#include "TMath.h"
#include "THLimitsFinder.h"

Int_t TGaxis::fgMaxDigits = 5;
const Int_t kHori = BIT(9); //defined in TPad

ClassImp(TGaxis)

//______________________________________________________________________________
//
// Service class for the graphical representation of axis.
// Instances of this class are generated by the histogram classes and TGraph.
//
// The picture below has been generated by the following macro.
//{
//
//  gROOT.Reset();
//
//  c1 = new TCanvas("c1","Examples of Gaxis",10,10,700,500);
//
//  c1->Range(-10,-1,10,1);
//
//  TGaxis *axis1 = new TGaxis(-4.5,-0.2,5.5,-0.2,-6,8,510,"");
//  axis1->SetName("axis1");
//  axis1->Draw();
//
//  TGaxis *axis2 = new TGaxis(-4.5,0.2,5.5,0.2,0.001,10000,510,"G");
//  axis2->SetName("axis2");
//  axis2->Draw();
//
//  TGaxis *axis3 = new TGaxis(-9,-0.8,-9,0.8,-8,8,50510,"");
//  axis3->SetName("axis3");
//  axis3->Draw();
//
//  TGaxis *axis4 = new TGaxis(-7,-0.8,-7,0.8,1,10000,50510,"G");
//  axis4->SetName("axis4");
//  axis4->Draw();
//
//  TGaxis *axis5 = new TGaxis(-4.5,-0.6,5.5,-0.6,1.2,1.32,80506,"-+");
//  axis5->SetName("axis5");
//  axis5->SetLabelSize(0.03);
//  axis5->SetTextFont(72);
//  axis5->SetLabelOffset(0.025);
//
//  axis5->Draw();
//
//  TGaxis *axis6 = new TGaxis(-4.5,0.6,5.5,0.6,100,900,50510,"-");
//  axis6->SetName("axis6");
//  axis6->Draw();
//
//  TGaxis *axis7 = new TGaxis(8,-0.8,8,0.8,0,9000,50510,"+L");
//  axis7->SetName("axis7");
//  axis7->SetLabelOffset(0.01);
//  axis7->Draw();
//
//  //one can make axis going top->bottom. However because of a long standing
//  //problem, the two x values should not be equal
//  TGaxis *axis8 = new TGaxis(6.5,0.8,6.499,-0.8,0,90,50510,"-");
//  axis8->SetName("axis8");
//  axis8->Draw();
//}
//Begin_Html
/*
<img src="gif/gaxis.gif">
*/
//End_Html
//
//
//  See the second TGaxis constructor for examples of TGaxis
//  with a mapping function.

//______________________________________________________________________________
TGaxis::TGaxis(): TLine(), TAttText(11,0,1,62,0.040)
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis default constructor-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =========================
   fGridLength  = 0.;
   fLabelOffset = 0.005;
   fLabelSize   = 0.040;
   fLabelFont   = 62;
   fLabelColor  = 1;
   fTickSize    = 0.030;
   fTitleOffset = 1;
   fTitleSize   = fLabelSize;
   fChopt       = "";
   fName        = "";
   fTitle       = "";
   fTimeFormat  = "";
   fFunctionName= "";
   fFunction    = 0;
   fAxis        = 0;
}

//______________________________________________________________________________
TGaxis::TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
               Double_t wmin, Double_t wmax, Int_t ndiv,   Option_t *chopt,
               Double_t gridlength)
       : TLine(xmin,ymin,xmax,ymax), TAttText(11,0,1,62,0.040)
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis normal constructor-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =========================
//  See explanation of parameters in PaintAxis
//

   fWmin        = wmin;
   fWmax        = wmax;
   fNdiv        = ndiv;
   fGridLength  = gridlength;
   fLabelOffset = 0.005;
   fLabelSize   = 0.040;
   fLabelFont   = 62;
   fLabelColor  = 1;
   fTickSize    = 0.030;
   fTitleOffset = 1;
   fTitleSize   = fLabelSize;
   fChopt       = chopt;
   fName        = "";
   fTitle       = "";
   fTimeFormat  = "";
   fFunctionName= "";
   fFunction    = 0;
   fAxis        = 0;
}

//______________________________________________________________________________
TGaxis::TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
               const char *funcname, Int_t ndiv,   Option_t *chopt,
               Double_t gridlength)
       : TLine(xmin,ymin,xmax,ymax), TAttText(11,0,1,62,0.040)
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis constructor with a TF1 to map axis values-*-*-*
//*-*                  ===============================================
//  See explanation of parameters in PaintAxis
//  Instead of the wmin,wmax arguments of the normal constructor, the
//  name of a TF1 function can be specified. This function will be used
//  by TGaxis::PaintAxis to map the user coordinates to the axis values
//  and ticks.
//  Examples:
//void gaxis3a()
//{
//   gStyle->SetOptStat(0);
//
//   TH2F *h2 = new TH2F("h","Axes",100,0,10,100,-2,2);
//   h2->Draw();
//
//   TF1 *f1=new TF1("f1","-x",-10,10);
//   TGaxis *A1 = new TGaxis(0,2,10,2,"f1",510,"-");
//   A1->SetTitle("axis with decreasing values");
//   A1->Draw();
//
//   TF1 *f2=new TF1("f2","exp(x)",0,2);
//   TGaxis *A2 = new TGaxis(1,1,9,1,"f2");
//   A2->SetTitle("exponential axis");
//   A2->SetLabelSize(0.03);
//   A2->SetTitleSize(0.03);
//   A2->SetTitleOffset(1.2);
//   A2->Draw();
//
//   TF1 *f3=new TF1("f3","log10(x)",1,1000);
//   TGaxis *A3 = new TGaxis(2,-2,2,0,"f3",505,"G");
//   A3->SetTitle("logarithmic axis");
//   A3->SetLabelSize(0.03);
//   A3->SetTitleSize(0.03);
//   A3->SetTitleOffset(1.2);
//   A3->Draw();
//}
//Begin_Html
/*
<img src="gif/gaxisf1.gif">
*/
//End_Html

   fFunction = (TF1*)gROOT->GetFunction(funcname);
   if (!fFunction) {
      Error("TGaxis, calling constructor with an unknown function:%s",funcname);
      fWmin = 0;
      fWmax = 1;
   } else {
      fWmin = fFunction->GetXmin();
      fWmax = fFunction->GetXmax();
   }
   fFunctionName= funcname;
   fNdiv        = ndiv;
   fGridLength  = gridlength;
   fLabelOffset = 0.005;
   fLabelSize   = 0.040;
   fLabelFont   = 62;
   fLabelColor  = 1;
   fTickSize    = 0.030;
   fTitleOffset = 1;
   fTitleSize   = fLabelSize;
   fChopt       = chopt;
   fName        = "";
   fTitle       = "";
   fTimeFormat  = "";
   fAxis        = 0;
}

//______________________________________________________________________________
TGaxis::~TGaxis()
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis default destructor-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  =======================
}

//______________________________________________________________________________
void TGaxis::CenterLabels(Bool_t center)
{
//   if center = kTRUE axis labels are centered in the center of the bin
//   default is to center on the primary tick marks
//   This option does not make sense if there are more bins than tick marks.
   
   if (center) SetBit(TAxis::kCenterLabels);
   else        ResetBit(TAxis::kCenterLabels);
}

//______________________________________________________________________________
void TGaxis::CenterTitle(Bool_t center)
{
//   if center = kTRUE axis title will be centered
//   default is right adjusted
   if (center) SetBit(TAxis::kCenterTitle);
   else        ResetBit(TAxis::kCenterTitle);
}

//______________________________________________________________________________
void TGaxis::DrawAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
                      Double_t wmin, Double_t wmax, Int_t ndiv,   Option_t *chopt,
                      Double_t gridlength)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this axis with new attributes*-*-*-*-*-*-*-*-*-*
//*-*                  ==================================

   TGaxis *newaxis = new TGaxis(xmin,ymin,xmax,ymax,wmin,wmax,ndiv,chopt,gridlength);
   newaxis->SetLineColor(fLineColor);
   newaxis->SetLineWidth(fLineWidth);
   newaxis->SetLineStyle(fLineStyle);
   newaxis->SetTextAlign(fTextAlign);
   newaxis->SetTextAngle(fTextAngle);
   newaxis->SetTextColor(fTextColor);
   newaxis->SetTextFont(fTextFont);
   newaxis->SetTextSize(fTextSize);
   newaxis->SetTitleSize(fTitleSize);
   newaxis->SetTitleOffset(fTitleOffset);
   newaxis->SetLabelFont(fLabelFont);
   newaxis->SetLabelColor(fLabelColor);
   newaxis->SetLabelSize(fLabelSize);
   newaxis->SetLabelOffset(fLabelOffset);
   newaxis->SetTickSize(fTickSize);
   newaxis->SetBit(kCanDelete);
   newaxis->SetTitle(GetTitle());
   newaxis->SetBit(TAxis::kCenterTitle,TestBit(TAxis::kCenterTitle));
   newaxis->AppendPad();
}

//______________________________________________________________________________
Int_t TGaxis::GetMaxDigits()
{
   // static function returning fgMaxDigits (See SetMaxDigits)

   return fgMaxDigits;
}

//______________________________________________________________________________
void TGaxis::ImportAxisAttributes(TAxis *axis)
{
// Copy TAxis attributes to this TGaxis

   fAxis = axis;
   SetLineColor(axis->GetAxisColor());
   SetTextColor(axis->GetTitleColor());
   SetTextFont(axis->GetTitleFont());
   SetLabelColor(axis->GetLabelColor());
   SetLabelFont(axis->GetLabelFont());
   SetLabelSize(axis->GetLabelSize());
   SetLabelOffset(axis->GetLabelOffset());
   SetTickSize(axis->GetTickLength());
   SetTitle(axis->GetTitle());
   SetTitleOffset(axis->GetTitleOffset());
   SetTitleSize(axis->GetTitleSize());
   SetBit(TAxis::kCenterTitle,   axis->TestBit(TAxis::kCenterTitle));
   SetBit(TAxis::kCenterLabels,  axis->TestBit(TAxis::kCenterLabels));
   SetBit(TAxis::kRotateTitle,   axis->TestBit(TAxis::kRotateTitle));
   SetBit(TAxis::kNoExponent,    axis->TestBit(TAxis::kNoExponent));
   SetBit(TAxis::kTickPlus,      axis->TestBit(TAxis::kTickPlus));
   SetBit(TAxis::kTickMinus,     axis->TestBit(TAxis::kTickMinus));
   SetBit(TAxis::kMoreLogLabels, axis->TestBit(TAxis::kMoreLogLabels));
   if (axis->GetDecimals())      SetBit(TAxis::kDecimals); //the bit is in TAxis::fAxis2   
   SetTimeFormat(axis->GetTimeFormat());
}

//______________________________________________________________________________
void TGaxis::Paint(Option_t *)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this axis with its current attributes*-*-*-*-*-*-*
//*-*                  ==========================================

   Double_t wmin = fWmin;
   Double_t wmax = fWmax;
   Int_t    ndiv = fNdiv;
   
   // following code required to support toggle of lin/log scales
   Double_t x1 = gPad->XtoPad(fX1);
   Double_t y1 = gPad->YtoPad(fY1);
   Double_t x2 = gPad->XtoPad(fX2);
   Double_t y2 = gPad->YtoPad(fY2);
   TString opt = fChopt;
   opt.ToUpper();
   if (gPad->GetLogx()) {
	   if ((y1 == y2) && !opt.Contains("G")) opt += "G";
   } else {
	   if ((y1 == y2) && opt.Contains("G")) opt.ReplaceAll("G","");
   }
   if (gPad->GetLogy()) {
	   if ((x1 == x2) && !opt.Contains("G")) opt += "G";
   } else {
	   if ((x1 == x2) && opt.Contains("G")) opt.ReplaceAll("G","");
   }

	PaintAxis(x1,y1,x2,y2,wmin,wmax,ndiv,opt.Data(),fGridLength);
}
//______________________________________________________________________________
void TGaxis::PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
                       Double_t &wmin, Double_t &wmax, Int_t &ndiv,   Option_t *chopt,
                       Double_t gridlength, Bool_t drawGridOnly)
{
//*-*-*-*-*-*-*-*-*-*-*-*Control function to draw an axis*-*-*-*-*-*-*-*-*-*-*
//*-*                    ================================
//
//============> Original authors (O.Couet C.E.Vandoni N.Cremel-Somon)
//              largely modified and converted to C++ class by Rene Brun
//
// _Input parameters:
//
//  xmin      : X origin coordinate in WC space.
//  xmax      : X end axis coordinate in WC space.
//  ymin      : Y origin coordinate in WC space.
//  ymax      : Y end axis coordinate in WC space.
//  wmin      : Lowest value for the tick mark
//              labels written on the axis.
//  wmax      : Highest value for the tick mark labels
//              written on the axis.
//  ndiv      : Number of divisions.
//
//       ndiv=N1 + 100*N2 + 10000*N3
//       N1=number of 1st divisions.
//       N2=number of 2nd divisions.
//       N3=number of 3rd divisions.
//           e.g.:
//           nndi=0 --> no tick marks.
//           nndi=2 --> 2 divisions, one tick mark in the middle
//                      of the axis.
//
//  chopt :  Options (see below).
//
//       chopt='G': loGarithmic scale, default is linear.
//       chopt='B': Blank axis. Useful to superpose axis.
//
// Orientation of tick marks on axis.
// ----------------------------------
//
//   Tick marks are normally drawn on the positive side of the axis,
//   however, if X0=X1, then negative.
//
//       chopt='+': tick marks are drawn on Positive side. (default)
//       chopt='-': tick mark are drawn on the negative side.
//       i.e: '+-' --> tick marks are drawn on both sides of the axis.
//       chopt='U': Unlabeled axis, default is labeled.
//
// Size of tick marks
// ------------------
// By default, tick marks have a length equal to 3 per cent of the
// axis length.
// When the option "S" is specified, the length of the tick marks
// is equal to fTickSize*axis_length, where fTickSize may be set
// via TGaxis::SetTickSize.
//
// Position of labels on axis.
// ---------------------------
//
//   Labels are normally drawn on side opposite to tick marks.
//   However:
//
//       chopt='=': on Equal side
//
// Orientation of labels on axis.
// ------------------------------
//
//   Labels are normally drawn parallel to the axis.
//   However if X0=X1, then Orthogonal
//           if Y0=Y1, then Parallel
//
// Position of labels on tick marks.
// ---------------------------------
//
//   Labels are centered on tick marks.
//   However , if X0=X1, then they are right adjusted.
//
//       chopt='R': labels are Right adjusted on tick mark.
//                    (default is centered)
//       chopt='L': labels are Left adjusted on tick mark.
//       chopt='C': labels are Centered on tick mark.
//       chopt='M': In the Middle of the divisions.
//
// Format of labels.
// -----------------
//
//   Blank characters are stripped, and then the
//   label is correctly aligned. the dot, if last
//   character of the string, is also stripped,
//   unless the option "." (a dot, or period) is specified.
//   if SetDecimals(kTRUE) has been called (bit TAxis::kDecimals set).
//   all labels have the same number of decimals after the "."
//   The same is true if gStyle->SetStripDecimals(kFALSE) has been called.
//
//   In the following, we have some parameters, like
//   tick marks length and characters height (in percentage
//   of the length of the axis (WC))
//   The default values are as follows:
//
//   Primary tick marks: 3.0 %
//   Secondary tick marks: 1.5 %
//   Third order tick marks: .75 %
//   Characters height for labels: 4%
//
//   Labels offset: 1.0 %
//
// Optional grid.
// --------------
//
//       chopt='W': cross-Wire
//
// Axis bining optimization.
// -------------------------
//
//   By default the axis bining is optimized .
//
//       chopt='N': No bining optimization
//       chopt='I': Integer labelling
//
// Maximum Number of Digits for the axis labels
// --------------------------------------------
// See the static function TGaxis::SetMaxDigits
//
// Time representation.
// --------------------
//
//   Axis labels may be considered as times, plotted in a defined time format.
//   The format is set with SetTimeFormat().
//   wmin and wmax are considered as two time values in seconds.
//   The time axis will be spread around the time offset value (set with
//   SetTimeOffset() ). Actually it will go from TimeOffset+wmin to 
//   TimeOffset+wmax.
//   see examples in tutorials timeonaxis.C and timeonaxis2.C 
//
//       chopt='t': Plot times with a defined format instead of values
//

   const char *where = "PaintAxis";

   Double_t alfa, beta, ratio1, ratio2, grid_side;
   Double_t axis_lengthN = 0;
   Double_t axis_length0 = 0;
   Double_t axis_length1 = 0;
   Double_t axis_length;
   Double_t atick[3];
   Double_t tick_side;
   Double_t charheight;
   Double_t phil, phi, sinphi, cosphi, asinphi, acosphi;
   Double_t BinLow,  BinLow2,  BinLow3;
   Double_t BinHigh, BinHigh2, BinHigh3;
   Double_t BinWidth, BinWidth2, BinWidth3;
   Double_t xpl1, xpl2, ypl1, ypl2;
   Double_t Xtick = 0;
   Double_t Xtick0, Xtick1, DXtick=0;
   Double_t Ytick, Ytick0, Ytick1;
   Double_t Wlabel, DWlabel;
   Double_t Xfactor, Yfactor;
   Double_t Xlabel, Ylabel, DXlabel;
   Double_t Xone, Xtwo;
   Double_t rlab;
   Double_t X0, X1, Y0, Y1, XX0, XX1, YY0, YY1;
   XX0 = XX1 = YY0 = YY1 = 0;
   Double_t Xxmin, Xxmax, Yymin, Yymax;
   Xxmin = Xxmax = Yymin = Yymax = 0;
   Double_t XLside, XMside;
   Double_t WW, AF, RNE;
   Double_t XX, YY;
   Double_t XMNLOG, X00, X11, H2, H2SAV, AXMUL, Y;
   Float_t chupxvsav, chupyvsav;
   Double_t rtxw, rtyw;
   Int_t Nlabels, Nticks, Nticks0, Nticks1;
   Int_t i, j, k, l, decade, ltick;
   Int_t Mside, Lside;
   Int_t NEXE  = 0;
   Int_t LNLEN = 0;
   Int_t IEXE, IF1, IF2, NA, NF, IH1, IH2, NBININ, NCH, KMOD;
   Int_t OptionLog,OptionBlank,OptionVert,OptionPlus,OptionMinus,OptionUnlab,OptionPara;
   Int_t OptionDown,OptionRight,OptionLeft,OptionCent,OptionEqual,OptionDecimals=0,OptionDot;
   Int_t OptionY,OptionText,OptionGrid,OptionSize,OptionNoopt,OptionInt,OptionM,OptionUp,OptionX;
   Int_t OptionTime;
   Int_t first,last,labelnumber;
   Int_t Xalign, Yalign;
   Int_t NN1, NN2, NN3, N1A, N2A, N3A, NB2, NB3;
   Int_t nbins, N1Aold, NN1old;
   N1Aold = NN1old = 0;
   Int_t ndyn;
   Int_t NHILAB = 0;
   Int_t IDN;
   Bool_t FLEXE = 0;
   Bool_t FLEXPO,FLEXNE;
   char *LABEL;
   char *CHTEMP;
   char *CODED;
   char CHLABEL[256];
   char kCHTEMP[256];
   char CHCODED[8];
   TLine *linegrid;
   TString timeformat;
   time_t timelabel;
   Double_t timed, wTimeIni;
   struct tm* utctis;
   Double_t rangeOffset = 0;

   Double_t epsilon   = 1e-5;
   const Double_t kPI = TMath::Pi();
//*-*-______________________________________

   Double_t rwmi = wmin;
   Double_t rwma = wmax;
   CHTEMP = &kCHTEMP[0];
   LABEL  = &CHLABEL[0];
   linegrid  = 0;

   fFunction = (TF1*)gROOT->GetFunction(fFunctionName.Data());

   Bool_t noExponent = TestBit(TAxis::kNoExponent);

//*-*- If MoreLogLabels = kTRUE more Log Intermediate Labels are drawn.
   Bool_t MoreLogLabels = TestBit(TAxis::kMoreLogLabels);

//*-*- the following parameters correspond to the pad range in NDC
//*-*- and the WC coordinates in the pad

   Double_t padh   = gPad->GetWh()*gPad->GetAbsHNDC();
   Double_t RWxmin = gPad->GetX1();
   Double_t RWxmax = gPad->GetX2();
   Double_t RWymin = gPad->GetY1();
   Double_t RWymax = gPad->GetY2();

   if(strchr(chopt,'G')) OptionLog  = 1;  else OptionLog  = 0;
   if(strchr(chopt,'B')) OptionBlank= 1;  else OptionBlank= 0;
   if(strchr(chopt,'V')) OptionVert = 1;  else OptionVert = 0;
   if(strchr(chopt,'+')) OptionPlus = 1;  else OptionPlus = 0;
   if(strchr(chopt,'-')) OptionMinus= 1;  else OptionMinus= 0;
   if(strchr(chopt,'U')) OptionUnlab= 1;  else OptionUnlab= 0;
   if(strchr(chopt,'P')) OptionPara = 1;  else OptionPara = 0;
   if(strchr(chopt,'O')) OptionDown = 1;  else OptionDown = 0;
   if(strchr(chopt,'R')) OptionRight= 1;  else OptionRight= 0;
   if(strchr(chopt,'L')) OptionLeft = 1;  else OptionLeft = 0;
   if(strchr(chopt,'C')) OptionCent = 1;  else OptionCent = 0;
   if(strchr(chopt,'=')) OptionEqual= 1;  else OptionEqual= 0;
   if(strchr(chopt,'Y')) OptionY    = 1;  else OptionY    = 0;
   if(strchr(chopt,'T')) OptionText = 1;  else OptionText = 0;
   if(strchr(chopt,'W')) OptionGrid = 1;  else OptionGrid = 0;
   if(strchr(chopt,'S')) OptionSize = 1;  else OptionSize = 0;
   if(strchr(chopt,'N')) OptionNoopt= 1;  else OptionNoopt= 0;
   if(strchr(chopt,'I')) OptionInt  = 1;  else OptionInt  = 0;
   if(strchr(chopt,'M')) OptionM    = 1;  else OptionM    = 0;
   if(strchr(chopt,'0')) OptionUp   = 1;  else OptionUp   = 0;
   if(strchr(chopt,'X')) OptionX    = 1;  else OptionX    = 0;
   if(strchr(chopt,'t')) OptionTime = 1;  else OptionTime = 0;
   if(strchr(chopt,'.')) OptionDot  = 1;  else OptionDot  = 0;
   if (TestBit(TAxis::kTickPlus))     OptionPlus  = 2;
   if (TestBit(TAxis::kTickMinus))    OptionMinus = 2;
   if (TestBit(TAxis::kCenterLabels)) OptionM     = 1;
   if (TestBit(TAxis::kDecimals))     OptionDecimals = 1;
   if (!gStyle->GetStripDecimals())   OptionDecimals = 1;
   if (fAxis) {
      if (fAxis->GetLabels()) {
         OptionM    = 1;
         OptionText = 1;
         ndiv = fAxis->GetLast()-fAxis->GetFirst()+1;
      }
   }

//*-*-              Set the grid length

   if (OptionGrid) {
      if (gridlength == 0) gridlength = 0.8;
      linegrid = new TLine();
      linegrid->SetLineColor(gStyle->GetGridColor());
      if (linegrid->GetLineColor() == 0) linegrid->SetLineColor(GetLineColor());
      linegrid->SetLineStyle(gStyle->GetGridStyle());
      linegrid->SetLineWidth(gStyle->GetGridWidth());
   }

//*-*-              Determine time format

   Int_t IdF = fTimeFormat.Index("%F");
   if (IdF>=0) {
      timeformat = fTimeFormat(0,IdF);
   } else {
      timeformat = fTimeFormat;
   }

// determine the time offset and correct for time offset not being integer
   Double_t timeoffset =0;
   if (OptionTime) {
      if (IdF>=0) {
         Int_t LnF = fTimeFormat.Length();
         TString stringtimeoffset = fTimeFormat(IdF+2,LnF);
         Int_t yy, mm, dd, hh, mi, ss;
         if (sscanf(stringtimeoffset.Data(), "%d-%d-%d %d:%d:%d", &yy, &mm, &dd, &hh, &mi, &ss) == 6) {
            struct tm tp;
            struct tm* tptest;
            time_t timeoffsettest;
            tp.tm_year  = yy-1900;
            tp.tm_mon   = mm-1;
            tp.tm_mday  = dd;
            tp.tm_hour  = hh;
            tp.tm_min   = mi;
            tp.tm_sec   = ss;
            tp.tm_isdst = -1;
            timeoffset  = mktime(&tp);
            // have to correct this time to go back to UTC
            timeoffsettest = (time_t)((Long_t)timeoffset);
            tptest = gmtime(&timeoffsettest);
            timeoffset += timeoffsettest - mktime(tptest);
            // Add the time offset's decimal part if it is there
            Int_t Ids   = stringtimeoffset.Index("s");
            if (Ids >= 0) {
               Float_t dp;
               Int_t Lns   = stringtimeoffset.Length();
               TString sdp = stringtimeoffset(Ids+1,Lns);
               sscanf(sdp.Data(),"%g",&dp);
               timeoffset += dp;
            }
	    // if OptionTime = 2 gmtime will be used instead of localtime
            if (stringtimeoffset.Index("GMT")>=0) OptionTime =2;
         } else {
            Error(where, "Time offset has not the right format");
         }
      } else {
         timeoffset = gStyle->GetTimeOffset();
      }
      wmin += timeoffset - (int)(timeoffset);
      wmax += timeoffset - (int)(timeoffset);
    // correct for time offset at a good limit (min, hour, day, month, year)
      struct tm* tp0;
      time_t timetp = (time_t)((Long_t)(timeoffset));
      Double_t range = wmax - wmin;
      Long_t rangeBase = 60;
      if (range>60)       rangeBase = 60*20;       // minutes
      if (range>3600)     rangeBase = 3600*20;     // hours
      if (range>86400)    rangeBase = 86400*20;    // days
      if (range>2419200)  rangeBase = 31556736;    // months (average # days)
      rangeOffset = (Double_t) ((Long_t)(timeoffset)%rangeBase);
      if (range>31536000) {
         tp0 = gmtime(&timetp);
         tp0->tm_mon   = 0;
         tp0->tm_mday  = 1;
         tp0->tm_hour  = 0;
         tp0->tm_min   = 0;
         tp0->tm_sec   = 0;
         tp0->tm_isdst = -1;
         rangeBase = (timetp-mktime(tp0)); // years
         rangeOffset = (Double_t) (rangeBase);
      }
      wmax += rangeOffset;
      wmin += rangeOffset;
   }

//*-*-              Determine number of divisions 1, 2 and 3
   N1A   = ndiv%100;
   N2A   = (ndiv%10000 - N1A)/100;
   N3A   = ndiv/10000;
   NN3   = TMath::Max(N3A,1);
   NN2   = TMath::Max(N2A,1)*NN3;
   NN1   = TMath::Max(N1A,1)*NN2+1;
   Nticks= NN1;

//*-*-              Axis bining optimization is ignored if:
//*-*-                - the first and the last label are equal
//*-*-                - the number of divisions is 0
//*-*-                - less than 1 primary division is requested
//*-*-                - logarithmic scale is requested

   if (wmin == wmax || ndiv == 0 || N1A <= 1 || OptionLog) {
      OptionNoopt = 1;
      OptionInt   = 0;
   }

//*-*-              Axis bining optimization
   if ( (wmax-wmin) < 1 && OptionInt) {
      Error(where, "option I not available");
      OptionInt = 0;
   }
   if (!OptionNoopt || OptionInt ) {

//*-*- Primary divisions optimization
//*-*- When integer labelling is required, Optimize is invoked first
//*-*- and only if the result is not an integer labelling, AdjustBinSize is invoked.

      THLimitsFinder::Optimize(wmin,wmax,N1A,BinLow,BinHigh,nbins,BinWidth,fChopt.Data());
      if (OptionInt) {
         if (BinLow != Double_t(int(BinLow)) || BinWidth != Double_t(int(BinWidth))) {
            AdjustBinSize(wmin,wmax,N1A,BinLow,BinHigh,nbins,BinWidth);
         }
      }
      if ((wmin-BinLow)  > epsilon) { BinLow  += BinWidth; nbins--; }
      if ((BinHigh-wmax) > epsilon) { BinHigh -= BinWidth; nbins--; }
      if (xmax == xmin) {
         rtyw  = (ymax-ymin)/(wmax-wmin);
         Xxmin = xmin;
         Xxmax = xmax;
         Yymin = rtyw*(BinLow-wmin)  + ymin;
         Yymax = rtyw*(BinHigh-wmin) + ymin;
      }
      else {
         rtxw  = (xmax-xmin)/(wmax-wmin);
         Xxmin = rtxw*(BinLow-wmin)  + xmin;
         Xxmax = rtxw*(BinHigh-wmin) + xmin;
         if (ymax == ymin) {
            Yymin = ymin;
            Yymax = ymax;
         }
         else {
            alfa  = (ymax-ymin)/(xmax-xmin);
            beta  = (ymin*xmax-ymax*xmin)/(xmax-xmin);
            Yymin = alfa*Xxmin + beta;
            Yymax = alfa*Xxmax + beta;
         }
      }
      if (fFunction) {
         Yymin = ymin;
         Yymax = ymax;
         Xxmin = xmin;
         Xxmax = xmax;
      } else {
         wmin = BinLow;
         wmax = BinHigh;
      }

//*-*- Secondary divisions optimization
      NB2 = N2A;
      if (!OptionNoopt && N2A > 1 && BinWidth > 0) {
         THLimitsFinder::Optimize(wmin,wmin+BinWidth,N2A,BinLow2,BinHigh2,NB2,BinWidth2,fChopt.Data());
      }

//*-*- Tertiary divisions optimization
      NB3 = N3A;
      if (!OptionNoopt && N3A > 1 && BinWidth2 > 0) {
         THLimitsFinder::Optimize(BinLow2,BinLow2+BinWidth2,N3A,BinLow3,BinHigh3,NB3,BinWidth3,fChopt.Data());
      }
      N1Aold = N1A;
      NN1old = NN1;
      N1A    = nbins;
      NN3    = TMath::Max(NB3,1);
      NN2    = TMath::Max(NB2,1)*NN3;
      NN1    = TMath::Max(N1A,1)*NN2+1;
      Nticks = NN1;
   }

//*-*-              Coordinates are normalized

   ratio1 = 1/(RWxmax-RWxmin);
   ratio2 = 1/(RWymax-RWymin);
   X0     = ratio1*(xmin-RWxmin);
   X1     = ratio1*(xmax-RWxmin);
   Y0     = ratio2*(ymin-RWymin);
   Y1     = ratio2*(ymax-RWymin);
   if (!OptionNoopt || OptionInt ) {
      XX0 = ratio1*(Xxmin-RWxmin);
      XX1 = ratio1*(Xxmax-RWxmin);
      YY0 = ratio2*(Yymin-RWymin);
      YY1 = ratio2*(Yymax-RWymin);
   }

   if ((X0 == X1) && (Y0 == Y1)) {
      Error(where, "length of axis is 0");
      return;
   }

//*-*-              Return wmin, wmax and the number of primary divisions
   if (OptionX) {
      ndiv = N1A;
      return;
   }

   Int_t maxDigits = 5;
   if (fAxis) maxDigits = fgMaxDigits;
   
   TLine *lineaxis = new TLine();
   TLatex *textaxis = new TLatex();
   lineaxis->SetLineColor(GetLineColor());
   lineaxis->SetLineStyle(1);
   lineaxis->SetLineWidth(gStyle->GetLineWidth());
   textaxis->SetTextColor(GetTextColor());
   textaxis->SetTextFont(GetTextFont());

   if (!gPad->IsBatch()) {
      gVirtualX->GetCharacterUp(chupxvsav, chupyvsav);
      gVirtualX->SetClipOFF(gPad->GetCanvasID());
   }

//*-*-              Compute length of axis
   axis_length = TMath::Sqrt((X1-X0)*(X1-X0)+(Y1-Y0)*(Y1-Y0));
   if (axis_length == 0) {
      Error(where, "length of axis is 0");
      goto L210;
   }
   if (!OptionNoopt || OptionInt) {
      axis_lengthN = TMath::Sqrt((XX1-XX0)*(XX1-XX0)+(YY1-YY0)*(YY1-YY0));
      axis_length0 = TMath::Sqrt((XX0-X0)*(XX0-X0)+(YY0-Y0)*(YY0-Y0));
      axis_length1 = TMath::Sqrt((X1-XX1)*(X1-XX1)+(Y1-YY1)*(Y1-YY1));
      if (axis_lengthN < epsilon) {
         OptionNoopt = 1;
         OptionInt   = 0;
         wmin        = rwmi;
         wmax        = rwma;
         N1A         = N1Aold;
         NN1         = NN1old;
         Nticks      = NN1;
         if (OptionTime) {
            wmin        += timeoffset - (int)(timeoffset) + rangeOffset;
            wmax        += timeoffset - (int)(timeoffset) + rangeOffset;
         }
      }
   }

   if (X0 == X1) {
      phi  = 0.5*kPI;
      phil = phi;
   } else {
            phi = TMath::ATan2((Y1-Y0),(X1-X0));
      Int_t px0 = gPad->UtoPixel(X0);
      Int_t py0 = gPad->VtoPixel(Y0);
      Int_t px1 = gPad->UtoPixel(X1);
      Int_t py1 = gPad->VtoPixel(Y1);
      if (X0 < X1) phil = TMath::ATan2(Double_t(py0-py1), Double_t(px1-px0));
      else         phil = TMath::ATan2(Double_t(py1-py0), Double_t(px0-px1));
   }
   cosphi  = TMath::Cos(phi);
   sinphi  = TMath::Sin(phi);
   acosphi = TMath::Abs(cosphi);
   asinphi = TMath::Abs(sinphi);
   if (acosphi <= epsilon) { acosphi = 0;  cosphi  = 0; }
   if (asinphi <= epsilon) { asinphi = 0;  sinphi  = 0; }

//*-*-              Mside positive, tick marks on positive side
//*-*-              Mside negative, tick marks on negative side
//*-*-              Mside zero, tick marks on both sides
//*-*-              Default is positive except for vertical axis

   Mside=1;
   if (X0 == X1 && Y1 > Y0)       Mside = -1;
   if (OptionPlus)                Mside = 1;
   if (OptionMinus)               Mside = -1;
   if (OptionPlus && OptionMinus) Mside = 0;
   XMside = Mside;
   Lside = -Mside;
   if (OptionEqual) Lside = Mside;
   if (OptionPlus && OptionMinus) {
      Lside = -1;
      if (OptionEqual) Lside=1;
  }
   XLside = Lside;

//*-*-              Tick marks size
   if(XMside >= 0) tick_side = 1;
   else            tick_side = -1;
   if (OptionSize) atick[0] = tick_side*axis_length*fTickSize;
   else            atick[0] = tick_side*axis_length*0.03;

   atick[1] = 0.5*atick[0];
   atick[2] = 0.5*atick[1];

//*-*-             Set the side of the grid
   if ((X0 == X1) && (Y1 > Y0))  grid_side =-1;
   else                          grid_side = 1;

//*-*-             Compute Values if Function is given
   if(fFunction) {
      rwmi = fFunction->Eval(wmin);
      rwma = fFunction->Eval(wmax);
      if(rwmi > rwma) {
         Double_t t = rwma;
         rwma = rwmi;
         rwmi = t;
      }
   }

//*-*-              Draw the axis if needed...
   if (!OptionBlank) {
      xpl1 = X0;
      xpl2 = X1;
      ypl1 = Y0;
      ypl2 = Y1;
      lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
   }

//*-*-              No bining

   if (ndiv == 0)goto L210;
   if (wmin == wmax) {
      Error(where, "wmin (%f) == wmax (%f)", wmin, wmax);
      goto L210;
   }

//*-*-              Draw axis title if it exists
   if (!drawGridOnly && strlen(GetTitle())) {
      textaxis->SetTextSize (GetTitleSize());
      charheight = GetTitleSize();
      if ((GetTextFont() % 10) > 2) {
         charheight = charheight/gPad->GetWh();
      }
      Double_t toffset = GetTitleOffset();
      if (toffset < 0.1) toffset = 1;
      if (X1 == X0) Ylabel = XLside*1.6*charheight*toffset;
      else          Ylabel = XLside*1.3*charheight*toffset;
      if (Y1 == Y0) Ylabel = XLside*1.6*charheight*toffset;
      Double_t axispos;
      if (TestBit(TAxis::kCenterTitle)) axispos = 0.5*axis_length;
      else                       axispos = axis_length;
      if (TestBit(TAxis::kRotateTitle)) {
         if (X1 >= X0) {
            if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
            else                              textaxis->SetTextAlign(12);
            Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
         } else {
             if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
           else                                textaxis->SetTextAlign(32);
            Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
         }
         textaxis->PaintLatex(gPad->GetX1() + xpl1*(gPad->GetX2() - gPad->GetX1()),
                              gPad->GetY1() + ypl1*(gPad->GetY2() - gPad->GetY1()),
                              phil=(kPI+phil)*180/kPI,
                              GetTitleSize(),
                              GetTitle());
      } else {
         if (X1 >= X0) {
            if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
            else                              textaxis->SetTextAlign(32);
            Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
         } else {
             if (TestBit(TAxis::kCenterTitle)) textaxis->SetTextAlign(22);
           else                                textaxis->SetTextAlign(12);
            Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
         }
         textaxis->PaintLatex(gPad->GetX1() + xpl1*(gPad->GetX2() - gPad->GetX1()),
                              gPad->GetY1() + ypl1*(gPad->GetY2() - gPad->GetY1()),
                              phil*180/kPI,
                              GetTitleSize(),
                              GetTitle());
      }
   }

//*-*-              Labels preparation:
//*-*-              Get character height
//*-*-              Compute the labels orientation in case of overlaps
//*-*-              (with alphanumeric labels for horizontal axis).

   charheight = GetLabelSize();
   if (OptionText) charheight *= 0.66666;
   textaxis->SetTextFont(GetLabelFont());
   textaxis->SetTextColor(GetLabelColor());
   textaxis->SetTextSize (charheight);
   textaxis->SetTextAngle(GetTextAngle());
   if (GetLabelFont()%10 > 2) {
      charheight /= padh;
   }
   if (!OptionUp && !OptionDown && !OptionY) {
      if (!drawGridOnly && OptionText && ((ymin == ymax) || (xmin == xmax))) {
         textaxis->SetTextAlign(32);
         OptionText = 2;
         Int_t nl = fAxis->GetLast()-fAxis->GetFirst()+1;
         Double_t angle     = 0;
         for (i=fAxis->GetFirst(); i<=fAxis->GetLast(); i++) {
            textaxis->SetText(0,0,fAxis->GetBinLabel(i));
            if (textaxis->GetXsize() < (xmax-xmin)/nl) continue;
            angle = -20;
            break;
         }
         for (i=fAxis->GetFirst(); i<=fAxis->GetLast(); i++) {
            if ((!strcmp(fAxis->GetName(),"xaxis") && !gPad->TestBit(kHori))
              ||(!strcmp(fAxis->GetName(),"yaxis") &&  gPad->TestBit(kHori))) {
               if (nl > 50) angle = 90;
               if (fAxis->TestBit(TAxis::kLabelsHori)) angle = 0;
               if (fAxis->TestBit(TAxis::kLabelsVert)) angle = 90;
               if (fAxis->TestBit(TAxis::kLabelsUp))   angle = 20;
               if (fAxis->TestBit(TAxis::kLabelsDown)) angle =-20;
               if (angle==   0) textaxis->SetTextAlign(23);
               if (angle== -20) textaxis->SetTextAlign(12);
               textaxis->PaintLatex(fAxis->GetBinCenter(i),
                                    gPad->GetUymin() - 3*fAxis->GetLabelOffset()*(gPad->GetUymax()-gPad->GetUymin()),
                                    angle,
                                    charheight,
                                    fAxis->GetBinLabel(i));
            } else if ((!strcmp(fAxis->GetName(),"yaxis") && !gPad->TestBit(kHori))
                    || (!strcmp(fAxis->GetName(),"xaxis") &&  gPad->TestBit(kHori))) {
               textaxis->PaintLatex(gPad->GetUxmin() - 3*fAxis->GetLabelOffset()*(gPad->GetUxmax()-gPad->GetUxmin()),
                                    fAxis->GetBinCenter(i),
                                    0,
                                    charheight,
                                    fAxis->GetBinLabel(i));
            } else {
               textaxis->PaintLatex(xmin - 3*fAxis->GetLabelOffset()*(gPad->GetUxmax()-gPad->GetUxmin()),
                                    ymin +(i-0.5)*(ymax-ymin)/nl,
                                    0,
                                    charheight,
                                    fAxis->GetBinLabel(i));
            }
         }
      }
   }

//*-*-              Now determine orientation of labels on axis
   if (!gPad->IsBatch()) {
      if (cosphi > 0) gVirtualX->SetCharacterUp(-sinphi,cosphi);
      else            gVirtualX->SetCharacterUp(sinphi,-cosphi);
      if (X0 == X1)   gVirtualX->SetCharacterUp(0,1);
      if (OptionVert) gVirtualX->SetCharacterUp(0,1);
      if (OptionPara) gVirtualX->SetCharacterUp(-sinphi,cosphi);
      if (OptionDown) gVirtualX->SetCharacterUp(cosphi,sinphi);
   }

//*-*-              Now determine text alignment
   Xalign = 2;
   Yalign = 1;
   if (X0 == X1)    Xalign = 3;
   if (Y0 != Y1)    Yalign = 2;
   if (OptionCent)  Xalign = 2;
   if (OptionRight) Xalign = 3;
   if (OptionLeft)  Xalign = 1;
   if (TMath::Abs(cosphi) > 0.9) {
      Xalign = 2;
   } else {
      if (cosphi*sinphi > 0)  Xalign = 1;
      if (cosphi*sinphi < 0)  Xalign = 3;
   }
   textaxis->SetTextAlign(10*Xalign+Yalign);

//*-*-              Position of labels in Y
   if (X0 == X1) {
      if (OptionPlus && !OptionMinus) {
         if (OptionEqual) Ylabel =  fLabelOffset/2 + atick[0];
         else             Ylabel = -fLabelOffset;
      } else {
         Ylabel = fLabelOffset;
         if (Lside < 0)  Ylabel += atick[0];
      }
   } else if (Y0 == Y1) {
      if (OptionMinus && !OptionPlus) {
         Ylabel = fLabelOffset+0.5*fLabelSize; 
         Ylabel += TMath::Abs(atick[0]);
      } else {
         Ylabel = -fLabelOffset;
         if (Mside <= 0) Ylabel -= TMath::Abs(atick[0]);
      }
      if (OptionLog)  Ylabel -= 0.5*charheight;
   } else {
      if (Mside+Lside >= 0) Ylabel =  fLabelOffset;
      else                  Ylabel = -fLabelOffset;
   }
   if (OptionText) Ylabel /= 2;

//*-*-              Draw the linear tick marks if needed...
   if (!OptionLog) {
      if (ndiv) {
         if (fFunction) {
            if (OptionNoopt && !OptionInt) {
               DXtick=(BinHigh-BinLow)/Double_t(Nticks-1);
            } else {
               DXtick=(BinHigh-BinLow)/Double_t(Nticks-1);
            }
         } else {
            if (OptionNoopt && !OptionInt) DXtick=axis_length/Double_t(Nticks-1);
            else                           DXtick=axis_lengthN/Double_t(Nticks-1);
         }
         for (k=0;k<Nticks; k++) {
            ltick = 2;
            if (k%NN3 == 0) ltick = 1;
            if (k%NN2 == 0) ltick = 0;
            if (fFunction) {
               Double_t xx = BinLow+Double_t(k)*DXtick;
               Double_t zz = fFunction->Eval(xx)-rwmi;
               Xtick = zz* axis_length / TMath::Abs(rwma-rwmi);
            } else {
               Xtick = Double_t(k)*DXtick;
            }
            Ytick = 0;
            if (!Mside) Ytick -= atick[ltick];
            if ( OptionNoopt && !OptionInt) {
               Rotate(Xtick,Ytick,cosphi,sinphi,X0,Y0,xpl2,ypl2);
               Rotate(Xtick,atick[ltick],cosphi,sinphi,X0,Y0,xpl1,ypl1);
            }
            else {
               Rotate(Xtick,Ytick,cosphi,sinphi,XX0,YY0,xpl2,ypl2);
               Rotate(Xtick,atick[ltick],cosphi,sinphi,XX0,YY0,xpl1,ypl1);
            }
            if (OptionVert) {
               if ((X0 != X1) && (Y0 != Y1)) {
                  if (Mside) {
                     xpl1 = xpl2;
                     if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
                     else            ypl1 = ypl2 - atick[ltick];
                  }
                  else {
                     xpl1 = 0.5*(xpl1 + xpl2);
                     xpl2 = xpl1;
                     ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
                     ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
                  }
               }
            }
            if (!drawGridOnly) lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);

            if (OptionGrid) {
               if (ltick == 0) {
                  if (OptionNoopt && !OptionInt) {
                     Rotate(Xtick,0,cosphi,sinphi,X0,Y0 ,xpl2,ypl2);
                     Rotate(Xtick,grid_side*gridlength ,cosphi,sinphi,X0,Y0 ,xpl1,ypl1);
                  }
                  else {
                     Rotate(Xtick,0,cosphi ,sinphi,XX0,YY0 ,xpl2,ypl2);
                     Rotate(Xtick,grid_side*gridlength ,cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
                  }
                  linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
               }
            }
         }
         Xtick0 = 0;
         Xtick1 = Xtick;

         if ((!OptionNoopt || OptionInt) && axis_length0) {
            if (fFunction) Nticks0 = Int_t((BinLow-wmin)/DXtick);
            else           Nticks0 = Int_t(axis_length0/DXtick);
            if (Nticks0 > 1000) Nticks0 = 1000;
            for (k=0; k<=Nticks0; k++) {
               ltick = 2;
               if (k%NN3 == 0) ltick = 1;
               if (k%NN2 == 0) ltick = 0;
               Ytick0 = 0;
               if (!Mside) Ytick0 -= atick[ltick];
               if (fFunction) {
                  Xtick0 = (fFunction->Eval(BinLow - Double_t(k)*DXtick)-rwmi)
                           * axis_length / TMath::Abs(rwma-rwmi);
               }
               Rotate(Xtick0,Ytick0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
               Rotate(Xtick0,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
               if (OptionVert) {
                  if ((X0 != X1) && (Y0 != Y1)) {
                     if (Mside) {
                        xpl1 = xpl2;
                        if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
                        else            ypl1 = ypl2 - atick[ltick];
                     }
                     else {
                        xpl1 = 0.5*(xpl1 + xpl2);
                        xpl2 = xpl1;
                        ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
                        ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
                     }
                  }
               }
               if (!drawGridOnly) lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);

               if (OptionGrid) {
                  if (ltick == 0) {
                     Rotate(Xtick0,0,cosphi,sinphi,XX0,YY0,xpl2,ypl2);
                     Rotate(Xtick0,grid_side*gridlength ,cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
                     linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
                  }
               }
               Xtick0 -= DXtick;
            }
         }

         if ((!OptionNoopt || OptionInt) && axis_length1) {
            if (fFunction) Nticks1 = int((wmax-BinHigh)/DXtick);
            else           Nticks1 = int(axis_length1/DXtick);
            if (Nticks1 > 1000) Nticks1 = 1000;
            for (k=0; k<=Nticks1; k++) {
               ltick = 2;
               if (k%NN3 == 0) ltick = 1;
               if (k%NN2 == 0) ltick = 0;
               Ytick1 = 0;
               if (!Mside) Ytick1 -= atick[ltick];
               if (fFunction) {
                  Xtick1 = (fFunction->Eval(BinHigh + Double_t(k)*DXtick)-rwmi)
                           * axis_length / TMath::Abs(rwma-rwmi);
               }
               Rotate(Xtick1,Ytick1,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
               Rotate(Xtick1,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
               if (OptionVert) {
                  if ((X0 != X1) && (Y0 != Y1)) {
                     if (Mside) {
                        xpl1 = xpl2;
                        if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
                        else            ypl1 = ypl2 - atick[ltick];
                     }
                     else {
                        xpl1 = 0.5*(xpl1 + xpl2);
                        xpl2 = xpl1;
                        ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
                        ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
                     }
                  }
               }
               if (!drawGridOnly) lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
               if (OptionGrid) {
                  if (ltick == 0) {
                     Rotate(Xtick1,0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
                     Rotate(Xtick1,grid_side*gridlength,cosphi,sinphi,XX0,YY0,xpl1,ypl1);
                     linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
                  }
               }
               Xtick1 += DXtick;
            }
         }
      }
   }

//*-*-              Draw the numeric labels if needed...
   if (!drawGridOnly && !OptionUnlab) {
      if (!OptionLog) {
         if (N1A) {
//*-*-              Spacing of labels
            if ((wmin == wmax) || (ndiv == 0)) {
               Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
               goto L210;
            }
            Wlabel  = wmin;
            DWlabel = (wmax-wmin)/Double_t(N1A);
            if (OptionNoopt && !OptionInt) DXlabel = axis_length/Double_t(N1A);
            else                           DXlabel = axis_lengthN/Double_t(N1A);

            if (!OptionText && !OptionTime) {

//*-*-              We have to decide what format to generate
//*-*-              (for numeric labels only)
//*-*-              Test the magnitude, decide format
               FLEXE  = kFALSE;
               NEXE   = 0;
               FLEXPO = kFALSE;
               FLEXNE = kFALSE;
               WW     = TMath::Max(TMath::Abs(wmin),TMath::Abs(wmax));

//*-*-              First case : (wmax-wmin)/N1A less than 0.001
//*-*-              (0.001 fgMaxDigits of 5 (fgMaxDigits) characters). Then we use x 10 n
//*-*-              format. If AF >=0 x10 n cannot be used
               Double_t xmicros = 0.00099;
               if (maxDigits) xmicros = TMath::Power(10,-maxDigits);
               if (!noExponent && (TMath::Abs(wmax-wmin)/Double_t(N1A)) < xmicros) {
                  AF    = TMath::Log10(WW) + epsilon;
                  if (AF < 0) {
                     FLEXE   = kTRUE;
                     NEXE    = int(AF);
                     IEXE    = TMath::Abs(NEXE);
                     if (IEXE%3 == 1)     IEXE += 2;
                     else if(IEXE%3 == 2) IEXE += 1;
                     if (NEXE < 0) NEXE = -IEXE;
                     else          NEXE =  IEXE;
                     Wlabel  = Wlabel*TMath::Power(10,IEXE);
                     DWlabel = DWlabel*TMath::Power(10,IEXE);
                     IF1     = maxDigits;
                     IF2     = maxDigits-2;
                     goto L110;
                  }
               }
               if (WW >= 1) AF = TMath::Log10(WW);
               else         AF = TMath::Log10(WW*0.0001);
               AF += epsilon;
               NF  = Int_t(AF)+1;
               if (!noExponent && NF > maxDigits)  FLEXPO = kTRUE;
               if (!noExponent && NF < -maxDigits) FLEXNE = kTRUE;

//*-*-              Use x 10 n format. (only powers of 3 allowed)

               if (FLEXPO) {
                  FLEXE = kTRUE;
                  while (1) {
                     NEXE++;
                     WW      /= 10;
                     Wlabel  /= 10;
                     DWlabel /= 10;
                     if (NEXE%3 == 0 && WW <= TMath::Power(10,maxDigits-1)) break;
                  }
               }

               if (FLEXNE) {
                  FLEXE = kTRUE;
                  RNE   = 1/TMath::Power(10,maxDigits-2);
                  while (1) {
                     NEXE--;
                     WW      *= 10;
                     Wlabel  *= 10;
                     DWlabel *= 10;
                     if (NEXE%3 == 0 && WW >= RNE) break;
                  }
               }

               NA = 0;
               for (i=maxDigits-1; i>0; i--) {
                  if (TMath::Abs(WW) < TMath::Power(10,i)) NA = maxDigits-i;
               }
               ndyn = N1A;
               while (ndyn) {
                  Double_t wdyn = TMath::Abs((wmax-wmin)/ndyn);
                  if (wdyn <= 0.999 && NA < maxDigits-2) {
                     NA++;
                     ndyn /= 10;
                  }
                  else break;
               }

               IF2 = NA;
               IF1 = TMath::Max(NF+NA,maxDigits)+1;
L110:
               if (TMath::Min(wmin,wmax) < 0)IF1 = IF1+1;
               IF1 = TMath::Min(IF1,32);

//*-*- In some cases, IF1 and IF2 are too small....
               while (DWlabel < TMath::Power(10,-IF2)) {
                  IF1++;
                  IF2++;
               }
               CODED = &CHCODED[0];
               if (IF1 > 14) IF1=14;
               if (IF2 > 14) IF2=14;
               if (IF2) sprintf(CODED,"%%%d.%df",IF1,IF2);
               else     sprintf(CODED,"%%%d.%df",IF1+1,1);
            }

//*-*-              We draw labels

            sprintf(CHTEMP,"%g",DWlabel);
            Int_t ndecimals = 0;
            if (OptionDecimals) {
               char *dot = strchr(CHTEMP,'.');
               if (dot) ndecimals = CHTEMP + strlen(CHTEMP) -dot;
            }
            if (OptionM) Nlabels = N1A-1;
            else         Nlabels = N1A;
            wTimeIni = Wlabel;
            for ( k=0; k<=Nlabels; k++) {
               if (fFunction) {
                  Double_t xx = BinLow+Double_t(k*NN2)*DXtick;
                  Double_t zz = fFunction->Eval(xx)-rwmi;
                  Wlabel = xx;
                  Xlabel = zz* axis_length / TMath::Abs(rwma-rwmi);
               } else {
                  Xlabel = DXlabel*k;
               }
               if (OptionM)    Xlabel += 0.5*DXlabel;

               if (!OptionText && !OptionTime) {
                  sprintf(LABEL,&CHCODED[0],Wlabel);
                  LABEL[28] = 0;
                  Wlabel += DWlabel;

                  LabelsLimits(LABEL,first,last);  //Eliminate blanks

                  if (LABEL[first] == '.') { //check if '.' is preceeded by a digit
                     strcpy(CHTEMP, "0");
                     strcat(CHTEMP, &LABEL[first]);
                     strcpy(LABEL, CHTEMP);
                     first = 1; last = strlen(LABEL);
                  }
                  if (LABEL[first] == '-' && LABEL[first+1] == '.') {
                     strcpy(CHTEMP, "-0");
                     strcat(CHTEMP, &LABEL[first+1]);
                     strcpy(LABEL, CHTEMP);
                     first = 1; last = strlen(LABEL);
                  }

//*-*-              We eliminate the non significant 0 after '.'
                  if (ndecimals) {
                     char *adot = strchr(LABEL,'.');
                     if (adot) adot[ndecimals] = 0;
                  } else {
                     while (LABEL[last] == '0') { LABEL[last] = 0; last--;}
                  }
//*-*-              We eliminate the dot, unless dot is forced.
                  if (LABEL[last] == '.') {
                     if (!OptionDot) { LABEL[last] = 0; last--;}
                  }
               }

//*-*-              Generate the time labels

               if (OptionTime) {
                  timed = Wlabel + (int)(timeoffset) - rangeOffset;
                  timelabel = (time_t)((Long_t)(timed));
                  if (OptionTime == 1) {
                     utctis = localtime(&timelabel);
                  } else {
                     utctis = gmtime(&timelabel);
                  }
                  TString timeformattmp;
                  if (timeformat.Length() < 220) timeformattmp = timeformat;
                  else timeformattmp = "#splitline{Format}{too long}";

//*-*-              Appends fractionnal part if seconds displayed
                  if (DWlabel<0.9) {
                     double tmpdb;
                     int tmplast;
                     sprintf(LABEL,"%%S%7.5f",modf(timed,&tmpdb));
                     tmplast = strlen(LABEL)-1;

//*-*-              We eliminate the non significiant 0 after '.'
                     while (LABEL[tmplast] == '0') {
                        LABEL[tmplast] = 0; tmplast--;
                     }

                     timeformattmp.ReplaceAll("%S",LABEL);
//*-*-              replace the "0." at the begining by "s"
                     timeformattmp.ReplaceAll("%S0.","%Ss");

                  }
                  
                  strftime(LABEL,256,timeformattmp.Data(),utctis);
                  strcpy(CHTEMP,&LABEL[0]);
                  first = 0; last=strlen(LABEL)-1;
                  Wlabel = wTimeIni + (k+1)*DWlabel;
               }

//*-*-              We generate labels (numeric or alphanumeric).

               if (OptionNoopt && !OptionInt)
                        Rotate (Xlabel,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
               else     Rotate (Xlabel,Ylabel,cosphi,sinphi,XX0,YY0,XX,YY);
               if (Y0 == Y1 && !OptionDown && !OptionUp) {
                  YY -= 0.80*charheight;
               }
               if (OptionVert) {
                  if (X0 != X1 && Y0 != Y1) {
                     if (OptionNoopt && !OptionInt)
                           Rotate (Xlabel,0,cosphi,sinphi,X0,Y0,XX,YY);
                     else  Rotate (Xlabel,0,cosphi,sinphi,XX0,YY0,XX,YY);
                     if (cosphi > 0 ) YY += Ylabel;
                     if (cosphi < 0 ) YY -= Ylabel;
                  }
               }
               if (!OptionY || (X0 == X1)) {
                  if (!OptionText) {
                     if (first > last)  strcpy(CHTEMP, " ");
                     else               strcpy(CHTEMP, &LABEL[first]);
                     textaxis->PaintLatex(gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1()),
                           gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1()),
                           0,
                           textaxis->GetTextSize(),
                           CHTEMP);
                  }
                  else  {
                     if (OptionText == 1) textaxis->PaintLatex(gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1()),
                                                   gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1()),
                                                   0,
                                                   textaxis->GetTextSize(),
                                                   fAxis->GetBinLabel(k+fAxis->GetFirst()));
                  }
               }
               else {

//*-*-       Text alignment is down
                  if (!OptionText)     LNLEN = last-first+1;
                  else {
                     if (k+1 > NHILAB) LNLEN = 0;
                  }
                  for ( l=1; l<=LNLEN; l++) {
                     if (!OptionText) *CHTEMP = LABEL[first+l-2];
                     else {
                        if (LNLEN == 0) strcpy(CHTEMP, " ");
                        else            strcpy(CHTEMP, "1");
                     }
                     textaxis->PaintLatex(gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1()),
                           gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1()),
                           0,
                           textaxis->GetTextSize(),
                           CHTEMP);
                     YY -= charheight*1.3;
                  }
               }
            }

//*-*-                We use the format x 10 ** n

            if (FLEXE && !OptionText && NEXE)  {
               sprintf(LABEL,"#times10^{%d}", NEXE);
               if (X0 != X1) { Xfactor = X1-X0+0.1*charheight; Yfactor = 0; }
               else          { Xfactor = Y1-Y0+0.1*charheight; Yfactor = 0; }
               Rotate (Xfactor,Yfactor,cosphi,sinphi,X0,Y0,XX,YY);
               textaxis->SetTextAlign(11);
               textaxis->PaintLatex(gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1()),
                           gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1()),
                           0,
                           textaxis->GetTextSize(),
                           LABEL);
            }
         }
      }
   }

//*-*-              Log axis

   if (OptionLog && ndiv) {
      UInt_t xi1=0,xi2,wi,yi1=0,yi2,hi;
      Bool_t firstintlab = kTRUE, overlap = kFALSE;
      if ((wmin == wmax) || (ndiv == 0))  {
         Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
         goto L210;
      }
      if (wmin <= 0)   {
         Error(where, "negative logarithmic axis");
         goto L210;
      }
      if (wmax <= 0)     {
         Error(where, "negative logarithmic axis");
         goto L210;
      }
      XMNLOG = TMath::Log10(wmin);
      if (XMNLOG > 0) XMNLOG += 1.E-6;
      else            XMNLOG -= 1.E-6;
      X00    = 0;
      X11    = axis_length;
      H2     = TMath::Log10(wmax);
      H2SAV  = H2;
      if (H2 > 0) H2 += 1.E-6;
      else        H2 -= 1.E-6;
      IH1    = int(XMNLOG);
      IH2    = 1+int(H2);
      NBININ = IH2-IH1+1;
      AXMUL  = (X11-X00)/(H2SAV-XMNLOG);

//*-*-              Plot decade and intermediate tick marks
      decade      = IH1-2;
      labelnumber = IH1;
      if ( XMNLOG > 0 && (XMNLOG-Double_t(IH1) > 0) ) labelnumber++;
      for (j=1; j<=NBININ; j++) {

//*-*-              Plot decade
         firstintlab = kTRUE, overlap = kFALSE;
         decade++;
         if (X0 == X1 && j == 1) Ylabel += charheight*0.33;
         if (Y0 == Y1 && j == 1) Ylabel -= charheight*0.65;
         Xone = X00+AXMUL*(Double_t(decade)-XMNLOG);
         //the following statement is a trick to circumvent a gcc bug
         if (j < 0) printf("j=%d\n",j);
         if (X00 > Xone) goto L160;
         if (Xone > X11) break;
         Xtwo = Xone;
         Y    = 0;
         if (!Mside) Y -= atick[0];
         Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2);
         Rotate(Xtwo,atick[0],cosphi,sinphi,X0,Y0,xpl1,ypl1);
         if (OptionVert) {
            if ((X0 != X1) && (Y0 != Y1)) {
               if (Mside) {
                  xpl1=xpl2;
                  if (cosphi > 0) ypl1 = ypl2 + atick[0];
                  else            ypl1 = ypl2 - atick[0];
               }
               else {
                  xpl1 = 0.5*(xpl1 + xpl2);
                  xpl2 = xpl1;
                  ypl1 = 0.5*(ypl1 + ypl2) + atick[0];
                  ypl2 = 0.5*(ypl1 + ypl2) - atick[0];
               }
            }
         }
         if (!drawGridOnly) lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);

         if (OptionGrid) {
            Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2,ypl2);
            Rotate(Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0,xpl1,ypl1);
            linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
         }

         if (!drawGridOnly && !OptionUnlab)  {

//*-*-              We generate labels (numeric only).
            if (noExponent) {
               rlab = TMath::Power(10,labelnumber);
               sprintf(LABEL, "%f", rlab);
               LabelsLimits(LABEL,first,last);
               while (last > first) {
                  if (LABEL[last] != '0') break;
                  LABEL[last] = 0;
                  last--;
               }
               if (LABEL[last] == '.') {LABEL[last] = 0; last--;}
            } else {
               sprintf(LABEL, "%d", labelnumber);
               LabelsLimits(LABEL,first,last);
            }
            Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
            if ((X0 == X1) && !OptionPara) {
               if (Lside < 0) {
                  if (Mside < 0) {
                     if (labelnumber == 0) NCH=1;
                     else                  NCH=2;
                     XX    += NCH*charheight;
                  } else {
                     if (labelnumber >= 0) XX    += 0.25*charheight;
                     else                  XX    += 0.50*charheight;
                  }
               }
               XX += 0.25*charheight;
            }
            if ((Y0 == Y1) && !OptionDown && !OptionUp) {
               if (noExponent) YY += 0.33*charheight;
            }
            if (N1A == 0)goto L210;
            KMOD = NBININ/N1A;
            if (KMOD == 0) KMOD=1000000;
            if ((NBININ <= N1A) || (j == 1) || (j == NBININ) || ((NBININ > N1A)
            && (j%KMOD == 0))) {
               if (labelnumber == 0) {
                  textaxis->PaintTextNDC(XX,YY,"1");
               } else if (labelnumber == 1) {
                  textaxis->PaintTextNDC(XX,YY,"10");
               } else {
                  if (noExponent) {
                     textaxis->PaintTextNDC(XX,YY,&LABEL[first]);
                  } else {
                        sprintf(CHTEMP, "10^{%d}", labelnumber);
                        textaxis->PaintLatex(gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1()),
                                             gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1()),
                                             0, textaxis->GetTextSize(), CHTEMP);

                  }
               }
            }
            labelnumber++;
         }
L160:
         for (k=2;k<10;k++) {

//*-*-              Plot intermediate tick marks
            Xone = X00+AXMUL*(TMath::Log10(Double_t(k))+Double_t(decade)-XMNLOG);
            if (X00 > Xone) continue;
            if (Xone > X11) goto L200;
            Y = 0;
            if (!Mside)  Y -= atick[1];
            Xtwo = Xone;
            Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2);
            Rotate(Xtwo,atick[1],cosphi,sinphi,X0,Y0,xpl1,ypl1);
            if (OptionVert) {
               if ((X0 != X1) && (Y0 != Y1)) {
                  if (Mside) {
                     xpl1 = xpl2;
                     if (cosphi > 0) ypl1 = ypl2 + atick[1];
                     else            ypl1 = ypl2 - atick[1];
                  }
                  else {
                     xpl1 = 0.5*(xpl1+xpl2);
                     xpl2 = xpl1;
                     ypl1 = 0.5*(ypl1+ypl2) + atick[1];
                     ypl2 = 0.5*(ypl1+ypl2) - atick[1];
                  }
               }
            }
            IDN = N1A*2;
            if ((NBININ <= IDN) || ((NBININ > IDN) && (k == 5))) {
               if (!drawGridOnly) lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);

//*-*- Draw the intermediate LOG labels if requested

               if (MoreLogLabels && !OptionUnlab && !drawGridOnly && !overlap) {
                  if (noExponent) {
                     rlab = Double_t(k)*TMath::Power(10,labelnumber-1);
                     sprintf(CHTEMP, "%g", rlab);
                  } else {
                     if (labelnumber-1 == 0) {
                        sprintf(CHTEMP, "%d", k);
                     } else if (labelnumber-1 == 1) {
                        sprintf(CHTEMP, "%d", 10*k);
                     } else {
                        sprintf(CHTEMP, "%d#times10^{%d}", k, labelnumber-1);
                     }
                  }
                  Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
                  if ((Y0 == Y1) && !OptionDown && !OptionUp) {
                     if (noExponent) YY += 0.33*charheight;
                  }
                  if ((X0 == X1)) XX += 0.25*charheight;
                  if (OptionVert) {
                     if ((X0 != X1) && (Y0 != Y1)) {
                        Rotate(Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
                        if (cosphi > 0) YY += Ylabel;
                        else            YY -= Ylabel;
                     }
                  }
                  textaxis->SetTitle(CHTEMP);
                  Double_t u = gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1());
                  Double_t v = gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1());
                  if (firstintlab) {
                     textaxis->GetBoundingBox(wi, hi); wi=(UInt_t)(wi*1.3); hi*=(UInt_t)(hi*1.3);
                     xi1 = gPad->XtoAbsPixel(u);
                     yi1 = gPad->YtoAbsPixel(v);
                     firstintlab = kFALSE;
                     textaxis->PaintLatex(u,v,0,textaxis->GetTextSize(),CHTEMP);
                  } else {
                     xi2 = gPad->XtoAbsPixel(u);
                     yi2 = gPad->YtoAbsPixel(v);
                     if ((X0 == X1 && yi1-hi <= yi2) || (Y0 == Y1 && xi1+wi >= xi2)){
                        overlap = kTRUE;
                     } else {
                        xi1 = xi2;
                        yi1 = yi2;
                        textaxis->GetBoundingBox(wi, hi); wi=(UInt_t)(wi*1.3); hi*=(UInt_t)(hi*1.3);
                        textaxis->PaintLatex(u,v,0,textaxis->GetTextSize(),CHTEMP);
                     }
                  }
               }

//*-*- Draw the intermediate LOG grid if only three decades are requested
               if (OptionGrid && NBININ <= 5) {
                  Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2, ypl2);
                  Rotate(Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0, xpl1,ypl1);
                  linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
               }
            }  //endif ((NBININ <= IDN) ||
         }  //endfor (k=2;k<10;k++)
      } //endfor (j=1; j<=NBININ; j++)
L200:
      Int_t kuku=0; if (kuku) { }
   }  //endif (OptionLog && ndiv)


L210:
   delete lineaxis;
   delete linegrid;
   delete textaxis;
}

//______________________________________________________________________________
void TGaxis::AdjustBinSize(Double_t A1,  Double_t A2,  Int_t nold
                          ,Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BinWidth)
{
//*-*-*-*-*-*-*-*-*-*-*-*Axis labels optimisation*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                    ========================
//
//   This routine adjusts the bining of the axis
//   in order to have integer values for the labels
//
// _Input parameters:
//
//  A1,A2    : Old WMIN,WMAX .
//  BinLow,BinHigh : New WMIN,WMAX .
//  nold     : Old NDIV (primary divisions)
//  nbins    : New NDIV .
//

   BinWidth = TMath::Abs(A2-A1)/Double_t(nold);
   if (BinWidth <= 1) { BinWidth = 1; BinLow = int(A1); }
   else {
      Int_t width = int(BinWidth/5) + 1;
      BinWidth = 5*width;
      BinLow   = int(A1/BinWidth)*BinWidth;

//*-*-     We determine BinLow to have one tick mark at 0
//*-*-     if there are negative labels.

      if (A1 < 0) {
         for (Int_t ic=0; ic<1000; ic++) {
            Double_t rbl = BinLow/BinWidth;
            Int_t   ibl = int(BinLow/BinWidth);
            if ( (rbl-ibl) == 0 || ic > width) { BinLow -= 5; break;}
         }
      }
   }
   BinHigh     = int(A2);
   nbins       = 0;
   Double_t XB  = BinLow;
   while (XB <= BinHigh) {
      XB += BinWidth;
      nbins++;
   }
   BinHigh = XB - BinWidth;
}

//______________________________________________________________________________
void TGaxis::LabelsLimits(const char *label, Int_t &first, Int_t &last)
{
//*-*-*-*-*-*-*-*-*Find first and last character of a label*-*-*-*-*-*-*-*-*-*
//*-*              ========================================

   last = strlen(label)-1;
   for (Int_t i=0; i<=last; i++) {
      if (strchr("1234567890-+.", label[i]) ) { first = i; return; }
   }
   Error("LabelsLimits", "attempt to draw a blank label");
}

//______________________________________________________________________________
void TGaxis::Rotate(Double_t X,  Double_t Y,  Double_t CFI, Double_t SFI
                   ,Double_t XT, Double_t YT, Double_t &U,   Double_t &V)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*-*Rotate axis coordinates*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                        =======================
      U = CFI*X-SFI*Y+XT;
      V = SFI*X+CFI*Y+YT;
}

//______________________________________________________________________________
void TGaxis::SavePrimitive(ofstream &out, Option_t *)
{
    // Save primitive as a C++ statement(s) on output stream out

   char quote = '"';
   if (gROOT->ClassSaved(TGaxis::Class())) {
       out<<"   ";
   } else {
       out<<"   TGaxis *";
   }
   out<<"gaxis = new TGaxis("<<fX1<<","<<fY1<<","<<fX2<<","<<fY2
      <<","<<fWmin<<","<<fWmax<<","<<fNdiv<<","<<quote<<fChopt.Data()<<quote<<");"<<endl;
   out<<"   gaxis->SetLabelOffset("<<GetLabelOffset()<<");"<<endl;
   out<<"   gaxis->SetLabelSize("<<GetLabelSize()<<");"<<endl;
   out<<"   gaxis->SetTickSize("<<GetTickSize()<<");"<<endl;
   out<<"   gaxis->SetGridLength("<<GetGridLength()<<");"<<endl;
   out<<"   gaxis->SetTitleOffset("<<GetTitleOffset()<<");"<<endl;
   if (strlen(GetName())) {
      out<<"   gaxis->SetName("<<quote<<GetName()<<quote<<");"<<endl;
   }
   if (strlen(GetTitle())) {
      out<<"   gaxis->SetTitle("<<quote<<GetTitle()<<quote<<");"<<endl;
   }

   if (fLabelColor != 1) {
      out<<"   gaxis->SetLabelColor("<<GetLabelColor()<<");"<<endl;
   }
   if (fLineColor != 1) {
      out<<"   gaxis->SetLineColor("<<GetLineColor()<<");"<<endl;   
   }
   if (fLineStyle != 1) {
      out<<"   gaxis->SetLineStyle("<<GetLineStyle()<<");"<<endl;   
   }
   if (fLineWidth != 1) {
      out<<"   gaxis->SetLineWidth("<<GetLineWidth()<<");"<<endl;   
   }
   if (fLabelFont != 62) {
      out<<"   gaxis->SetLabelFont("<<GetLabelFont()<<");"<<endl;   
   }
   if (TestBit(TAxis::kMoreLogLabels)) {
      out<<"   gaxis->SetMoreLogLabels();"<<endl;
   }
   if (TestBit(TAxis::kNoExponent)) {
      out<<"   gaxis->SetNoExponent();"<<endl;
   }
   
   out<<"   gaxis->Draw();"<<endl;
}

//______________________________________________________________________________
void TGaxis::SetDecimals(Bool_t dot)
{
// Set the Decimals flag
// By default, blank characters are stripped, and then the
// label is correctly aligned. The dot, if last character of the string, 
// is also stripped, unless this option is specified.
// One can disable the option by calling axis.SetDecimals(kTRUE).
// Note the bit is set in fBits (as opposed to fBits2 in TAxis!)

   if (dot) SetBit(TAxis::kDecimals);
   else     ResetBit(TAxis::kDecimals);
}

//______________________________________________________________________________
void TGaxis::SetFunction(const char *funcname)
{
//        specify a function to map the axis values
//        =========================================

   fFunctionName = funcname;
   if (strlen(funcname) == 0) {
      fFunction = 0;
      return;
   }
   fFunction = (TF1*)gROOT->GetFunction(funcname);
   if (!fFunction) {
      Error("SetFunction, Unknown function:%s",funcname);
   } else {
      fWmin = fFunction->GetXmin();
      fWmax = fFunction->GetXmax();
   }
}

//______________________________________________________________________________
void TGaxis::SetMaxDigits(Int_t maxd)
{
   // static function to set fgMaxDigits for axis with the bin content
   // (y axis for 1-d histogram, z axis for 2-d histogram)
   //fgMaxDigits is the maximum number of digits permitted for the axis
   //labels above which the notation with 10^N is used.
   //For example, to accept 6 digits number like 900000 on an axis
   //call TGaxis::SetMaxDigits(6). The default value is 5.
   //fgMaxDigits must be greater than 0.

   fgMaxDigits = maxd;
   if (maxd < 1) fgMaxDigits = 1;
}

//______________________________________________________________________________
void TGaxis::SetName(const char *name)
{
//*-*-*-*-*-*-*-*-*-*-*Change the name of the axis*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ============================
   fName = name;
}

//______________________________________________________________________________
void TGaxis::SetMoreLogLabels(Bool_t more)
{
// Set the kMoreLogLabels bit flag
// When this option is selected more labels are drawn when in log scale
// and there is a small number of decades  (<3).
// Note that this option is automatically inherited from TAxis

   if (more) SetBit(TAxis::kMoreLogLabels);
   else      ResetBit(TAxis::kMoreLogLabels);
}

//______________________________________________________________________________
void TGaxis::SetNoExponent(Bool_t noExponent)
{
// Set the NoExponent flag
// By default, an exponent of the form 10^N is used when the label values
// are either all very small or very large.
// One can disable the exponent by calling axis.SetNoExponent(kTRUE).

   if (noExponent) SetBit(TAxis::kNoExponent);
   else            ResetBit(TAxis::kNoExponent);
}

//______________________________________________________________________________
void TGaxis::SetOption(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*To set axis options*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                          ===================

   fChopt = option;
}

//______________________________________________________________________________
void TGaxis::SetTitle(const char *title)
{
//*-*-*-*-*-*-*-*-*-*-*Change the title of the axis*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                  ============================
   fTitle = title;
}

//______________________________________________________________________________
void TGaxis::SetTimeFormat(const char *tformat)
{
//*-*-*-*-*-*-*-*-*-*-*Change the format used for time plotting *-*-*-*-*-*-*-*
//*-*                  ========================================
//  The format string for date and time use the same options as the one used
//  in the standard strftime C function, i.e. :
//    for date :
//      %a abbreviated weekday name
//      %b abbreviated month name
//      %d day of the month (01-31)
//      %m month (01-12)
//      %y year without century
//
//    for time :
//      %H hour (24-hour clock)
//      %I hour (12-hour clock)
//      %p local equivalent of AM or PM
//      %M minute (00-59)
//      %S seconds (00-61)
//      %% %
//
   TString timeformat = tformat;

   if (timeformat.Index("%F")>=0 || timeformat.IsNull()) {
      fTimeFormat = timeformat;
      return;
   }
   
   Int_t IdF = fTimeFormat.Index("%F");
   if (IdF>=0) {
      Int_t LnF = fTimeFormat.Length();
      TString stringtimeoffset = fTimeFormat(IdF,LnF);  
      fTimeFormat = tformat;
      fTimeFormat.Append(stringtimeoffset);        
   } else {
      fTimeFormat = tformat;
      SetTimeOffset(gStyle->GetTimeOffset());
   }
}

//______________________________________________________________________________
void TGaxis::SetTimeOffset(Double_t toffset, Option_t *option)
{
   // Change the time offset
   // If option = "gmt" the time offset is treated as a GMT time.

   TString opt = option;
   opt.ToLower();

   Bool_t gmt = kFALSE;
   if (opt.Contains("gmt")) gmt = kTRUE;

   char tmp[20]; 
   time_t timeoff;
   struct tm* utctis;
   Int_t IdF = fTimeFormat.Index("%F");
   if (IdF>=0) fTimeFormat.Remove(IdF);
   fTimeFormat.Append("%F");

   timeoff = (time_t)((Long_t)(toffset));
   utctis = gmtime(&timeoff); 

   strftime(tmp,256,"%Y-%m-%d %H:%M:%S",utctis); 
   fTimeFormat.Append(tmp);

   // append the decimal part of the time offset
   Double_t ds = toffset-(Int_t)toffset;
   if(ds!= 0) {
      sprintf(tmp,"s%g",ds);
      fTimeFormat.Append(tmp);
   }

   // If the time is GMT, stamp fTimeFormat
   if (gmt) fTimeFormat.Append(" GMT");
}

//______________________________________________________________________________
void TGaxis::Streamer(TBuffer &R__b)
{
   // Stream an object of class TGaxis.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 3) {
         TGaxis::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      TLine::Streamer(R__b);
      TAttText::Streamer(R__b);
      R__b >> fNdiv;
      R__b >> fWmin;
      R__b >> fWmax;
      R__b >> fGridLength;
      R__b >> fTickSize;
      R__b >> fLabelOffset;
      R__b >> fLabelSize;
      R__b >> fTitleOffset;
      R__b >> fTitleSize;
      R__b >> fLabelFont;
      if (R__v > 2) {
         R__b >> fLabelColor;
      }
      fChopt.Streamer(R__b);
      fName.Streamer(R__b);
      fTitle.Streamer(R__b);
      fTimeFormat.Streamer(R__b);
      if (R__v > 1) {
         fFunctionName.Streamer(R__b);
         fFunction = (TF1*)gROOT->GetFunction(fFunctionName.Data());
      }
      R__b.CheckByteCount(R__s, R__c, TGaxis::IsA());
      //====end of old versions

   } else {
      TGaxis::Class()->WriteBuffer(R__b,this);
   }
}
