<commit_before>// @(#)root/fft:$Id$
// Author: Anna Kreshuk   07/4/2006

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

//////////////////////////////////////////////////////////////////////////
//
// TFFTComplexReal
//
// One of the interface classes to the FFTW package, can be used directly
// or via the TVirtualFFT class. Only the basic interface of FFTW is implemented.
//
// Computes the inverse of the real-to-complex transforms (class TFFTRealComplex)
// taking complex input (storing the non-redundant half of a logically Hermitian array)
// to real output (see FFTW manual for more details)
//
// How to use it:
// 1) Create an instance of TFFTComplexReal - this will allocate input and output
//    arrays (unless an in-place transform is specified)
// 2) Run the Init() function with the desired flags and settings
// 3) Set the data (via SetPoints(), SetPoint() or SetPointComplex() functions)
// 4) Run the Transform() function
// 5) Get the output (via GetPoints(), GetPoint() or GetPointReal() functions)
// 6) Repeat steps 3)-5) as needed
//
// For a transform of the same size, but with different flags, rerun the Init()
// function and continue with steps 3)-5)
// NOTE: 1) running Init() function will overwrite the input array! Don't set any data
//          before running the Init() function
//       2) FFTW computes unnormalized transform, so doing a transform followed by
//          its inverse will lead to the original array scaled by the transform size
//
//       3) In Complex to Real transform the input array is destroyed. It cannot then
//          be retrieved when using the Get's methods.
//
//////////////////////////////////////////////////////////////////////////

#include "TFFTComplexReal.h"
#include "fftw3.h"
#include "TComplex.h"

ClassImp(TFFTComplexReal)

//_____________________________________________________________________________
TFFTComplexReal::TFFTComplexReal()
{
//default

   fIn   = 0;
   fOut  = 0;
   fPlan = 0;
   fN    = 0;
   fTotalSize = 0;
   fFlags = 0;
   fNdim = 0;
}

//_____________________________________________________________________________
TFFTComplexReal::TFFTComplexReal(Int_t n, Bool_t inPlace)
{
//For 1d transforms
//Allocates memory for the input array, and, if inPlace = kFALSE, for the output array

   if (!inPlace){
      fIn = fftw_malloc(sizeof(fftw_complex)*(n/2+1));
      fOut = fftw_malloc(sizeof(Double_t)*n);

   } else {
      fIn = fftw_malloc(sizeof(fftw_complex)*(n/2+1));
      fOut = 0;
   }
   fNdim = 1;
   fN = new Int_t[1];
   fN[0] = n;
   fPlan = 0;
   fTotalSize = n;
   fFlags = 0;
}

//_____________________________________________________________________________
TFFTComplexReal::TFFTComplexReal(Int_t ndim, Int_t *n, Bool_t inPlace)
{
//For ndim-dimensional transforms
//Second argurment contains sizes of the transform in each dimension

   fNdim = ndim;
   fTotalSize = 1;
   fN = new Int_t[fNdim];
   for (Int_t i=0; i<fNdim; i++){
      fN[i] = n[i];
      fTotalSize*=n[i];
   }
   Int_t sizein = Int_t(Double_t(fTotalSize)*(n[ndim-1]/2+1)/n[ndim-1]);
   if (!inPlace){
      fIn = fftw_malloc(sizeof(fftw_complex)*sizein);
      fOut = fftw_malloc(sizeof(Double_t)*fTotalSize);
   } else {
      fIn = fftw_malloc(sizeof(fftw_complex)*sizein);
      fOut = 0;
   }
   fPlan = 0;
   fFlags = 0;
}

//_____________________________________________________________________________
TFFTComplexReal::~TFFTComplexReal()
{
//Destroys the data arrays and the plan. However, some plan information stays around
//until the root session is over, and is reused if other plans of the same size are
//created

   fftw_destroy_plan((fftw_plan)fPlan);
   fPlan = 0;
   fftw_free((fftw_complex*)fIn);
   if (fOut)
      fftw_free(fOut);
   fIn = 0;
   fOut = 0;
   if (fN)
      delete [] fN;
   fN = 0;
}

//_____________________________________________________________________________
void TFFTComplexReal::Init( Option_t *flags, Int_t /*sign*/,const Int_t* /*kind*/)
{
//Creates the fftw-plan
//
//NOTE:  input and output arrays are overwritten during initialisation,
//       so don't set any points, before running this function!!!!!
//
//Arguments sign and kind are dummy and not need to be specified
//Possible flag_options:
//"ES" (from "estimate") - no time in preparing the transform, but probably sub-optimal
//   performanc
//"M" (from "measure") - some time spend in finding the optimal way to do the transform
//"P" (from "patient") - more time spend in finding the optimal way to do the transform
//"EX" (from "exhaustive") - the most optimal way is found
//This option should be chosen depending on how many transforms of the same size and
//type are going to be done. Planning is only done once, for the first transform of this
//size and type.

   fFlags = flags;

   if (fOut)
      fPlan = (void*)fftw_plan_dft_c2r(fNdim, fN,(fftw_complex*)fIn,(Double_t*)fOut, MapFlag(flags));
   else
      fPlan = (void*)fftw_plan_dft_c2r(fNdim, fN, (fftw_complex*)fIn, (Double_t*)fIn, MapFlag(flags));
}

//_____________________________________________________________________________
void TFFTComplexReal::Transform()
{
//Computes the transform, specified in Init() function

   if (fPlan)
      fftw_execute((fftw_plan)fPlan);
   else {
      Error("Transform", "transform was not initialized");
      return;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPoints(Double_t *data, Bool_t fromInput) const
{
//Fills the argument array with the computed transform
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPoints", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   std::copy(array,array+fTotalSize, data);
}

//_____________________________________________________________________________
Double_t TFFTComplexReal::GetPointReal(Int_t ipoint, Bool_t fromInput) const
{
//Returns the point #ipoint
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointReal", "Input array has been destroyed");
      return 0;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   return array[ipoint];
}

//_____________________________________________________________________________
Double_t TFFTComplexReal::GetPointReal(const Int_t *ipoint, Bool_t fromInput) const
{
//For multidimensional transforms. Returns the point #ipoint
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointReal", "Input array has been destroyed");
      return 0;
   }
   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-1; i++)
      ireal=fN[i+1]*ireal + ipoint[i+1];

   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   return array[ireal];
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointComplex(Int_t ipoint, Double_t &re, Double_t &im, Bool_t fromInput) const
{
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   re = array[ipoint];
   im = 0;
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointComplex(const Int_t *ipoint, Double_t &re, Double_t &im, Bool_t fromInput) const
{
//For multidimensional transforms. Returns the point #ipoint
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );

   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-1; i++)
      ireal=fN[i+1]*ireal + ipoint[i+1];

   re = array[ireal];
   im = 0;
}
//_____________________________________________________________________________
Double_t* TFFTComplexReal::GetPointsReal(Bool_t fromInput) const
{
//Returns the array of computed transform
// Works only for output (input array is destroyed in a C2R transform)

   // we have 2 different cases
   // fromInput = false; fOut = !NULL (transformed is not in place) : return fOut
   // fromInput = false; fOut = NULL (transformed is in place) : return fIn

   if (fromInput) {
      Error("GetPointsReal","Input array was destroyed");
      return 0;
   }
   return  (Double_t*) ( (fOut) ?  fOut :  fIn );
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointsComplex(Double_t *re, Double_t *im, Bool_t fromInput) const
{
//Fills the argument array with the computed transform
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointsComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   for (Int_t i=0; i<fTotalSize; i++){
      re[i] = array[i];
      im[i] = 0;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointsComplex(Double_t *data, Bool_t fromInput) const
{
//Fills the argument array with the computed transform.
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointsComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   for (Int_t i=0; i<fTotalSize; i+=2){
      data[i] = array[i/2];
      data[i+1]=0;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPoint(Int_t ipoint, Double_t re, Double_t im)
{
//since the input must be complex-Hermitian, if the ipoint > n/2, the according
//point before n/2 is set to (re, -im)

   if (ipoint <= fN[0]/2){
      ((fftw_complex*)fIn)[ipoint][0] = re;
      ((fftw_complex*)fIn)[ipoint][1] = im;
   } else {
      ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][0] = re;
      ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][1] = -im;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPoint(const Int_t *ipoint, Double_t re, Double_t im)
{
//Set the point #ipoint. Since the input is Hermitian, only the first (roughly)half of
//the points have to be set.

   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-2; i++){
      ireal=fN[i+1]*ireal + ipoint[i+1];
   }
   ireal = (fN[fNdim-1]/2+1)*ireal+ipoint[fNdim-1];
   Int_t realN = Int_t(Double_t(fTotalSize)*(fN[fNdim-1]/2+1)/fN[fNdim-1]);

   if (ireal > realN){
      Error("SetPoint", "Illegal index value");
      return;
   }
   ((fftw_complex*)fIn)[ireal][0] = re;
   ((fftw_complex*)fIn)[ireal][1] = im;
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPointComplex(Int_t ipoint, TComplex &c)
{
//since the input must be complex-Hermitian, if the ipoint > n/2, the according
//point before n/2 is set to (re, -im)

   if (ipoint <= fN[0]/2){
      ((fftw_complex*)fIn)[ipoint][0] = c.Re();
      ((fftw_complex*)fIn)[ipoint][1] = c.Im();
   } else {
      ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][0] = c.Re();
      ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][1] = -c.Im();
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPoints(const Double_t *data)
{
//set all points. the values are copied. points should be ordered as follows:
//[re_0, im_0, re_1, im_1, ..., re_n, im_n)

   Int_t sizein = Int_t(Double_t(fTotalSize)*(fN[fNdim-1]/2+1)/fN[fNdim-1]);

   for (Int_t i=0; i<2*(sizein); i+=2){
      ((fftw_complex*)fIn)[i/2][0]=data[i];
      ((fftw_complex*)fIn)[i/2][1]=data[i+1];
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPointsComplex(const Double_t *re, const Double_t *im)
{
//Set all points. The values are copied.

   Int_t sizein = Int_t(Double_t(fTotalSize)*(fN[fNdim-1]/2+1)/fN[fNdim-1]);
   for (Int_t i=0; i<sizein; i++){
      ((fftw_complex*)fIn)[i][0]=re[i];
      ((fftw_complex*)fIn)[i][1]=im[i];
   }
}

//_____________________________________________________________________________
UInt_t TFFTComplexReal::MapFlag(Option_t *flag)
{
//allowed options:
//"ES" - FFTW_ESTIMATE
//"M" - FFTW_MEASURE
//"P" - FFTW_PATIENT
//"EX" - FFTW_EXHAUSTIVE

   TString opt = flag;
   opt.ToUpper();
   if (opt.Contains("ES"))
      return FFTW_ESTIMATE;
   if (opt.Contains("M"))
      return FFTW_MEASURE;
   if (opt.Contains("P"))
      return FFTW_PATIENT;
   if (opt.Contains("EX"))
      return FFTW_EXHAUSTIVE;
   return FFTW_ESTIMATE;
}
<commit_msg>Fix for bug https://savannah.cern.ch/bugs/?97707 (use fIn instead of fOut)<commit_after>// @(#)root/fft:$Id$
// Author: Anna Kreshuk   07/4/2006

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

//////////////////////////////////////////////////////////////////////////
//
// TFFTComplexReal
//
// One of the interface classes to the FFTW package, can be used directly
// or via the TVirtualFFT class. Only the basic interface of FFTW is implemented.
//
// Computes the inverse of the real-to-complex transforms (class TFFTRealComplex)
// taking complex input (storing the non-redundant half of a logically Hermitian array)
// to real output (see FFTW manual for more details)
//
// How to use it:
// 1) Create an instance of TFFTComplexReal - this will allocate input and output
//    arrays (unless an in-place transform is specified)
// 2) Run the Init() function with the desired flags and settings
// 3) Set the data (via SetPoints(), SetPoint() or SetPointComplex() functions)
// 4) Run the Transform() function
// 5) Get the output (via GetPoints(), GetPoint() or GetPointReal() functions)
// 6) Repeat steps 3)-5) as needed
//
// For a transform of the same size, but with different flags, rerun the Init()
// function and continue with steps 3)-5)
// NOTE: 1) running Init() function will overwrite the input array! Don't set any data
//          before running the Init() function
//       2) FFTW computes unnormalized transform, so doing a transform followed by
//          its inverse will lead to the original array scaled by the transform size
//
//       3) In Complex to Real transform the input array is destroyed. It cannot then
//          be retrieved when using the Get's methods.
//
//////////////////////////////////////////////////////////////////////////

#include "TFFTComplexReal.h"
#include "fftw3.h"
#include "TComplex.h"

ClassImp(TFFTComplexReal)

//_____________________________________________________________________________
TFFTComplexReal::TFFTComplexReal()
{
//default

   fIn   = 0;
   fOut  = 0;
   fPlan = 0;
   fN    = 0;
   fTotalSize = 0;
   fFlags = 0;
   fNdim = 0;
}

//_____________________________________________________________________________
TFFTComplexReal::TFFTComplexReal(Int_t n, Bool_t inPlace)
{
//For 1d transforms
//Allocates memory for the input array, and, if inPlace = kFALSE, for the output array

   if (!inPlace){
      fIn = fftw_malloc(sizeof(fftw_complex)*(n/2+1));
      fOut = fftw_malloc(sizeof(Double_t)*n);

   } else {
      fIn = fftw_malloc(sizeof(fftw_complex)*(n/2+1));
      fOut = 0;
   }
   fNdim = 1;
   fN = new Int_t[1];
   fN[0] = n;
   fPlan = 0;
   fTotalSize = n;
   fFlags = 0;
}

//_____________________________________________________________________________
TFFTComplexReal::TFFTComplexReal(Int_t ndim, Int_t *n, Bool_t inPlace)
{
//For ndim-dimensional transforms
//Second argurment contains sizes of the transform in each dimension

   fNdim = ndim;
   fTotalSize = 1;
   fN = new Int_t[fNdim];
   for (Int_t i=0; i<fNdim; i++){
      fN[i] = n[i];
      fTotalSize*=n[i];
   }
   Int_t sizein = Int_t(Double_t(fTotalSize)*(n[ndim-1]/2+1)/n[ndim-1]);
   if (!inPlace){
      fIn = fftw_malloc(sizeof(fftw_complex)*sizein);
      fOut = fftw_malloc(sizeof(Double_t)*fTotalSize);
   } else {
      fIn = fftw_malloc(sizeof(fftw_complex)*sizein);
      fOut = 0;
   }
   fPlan = 0;
   fFlags = 0;
}

//_____________________________________________________________________________
TFFTComplexReal::~TFFTComplexReal()
{
//Destroys the data arrays and the plan. However, some plan information stays around
//until the root session is over, and is reused if other plans of the same size are
//created

   fftw_destroy_plan((fftw_plan)fPlan);
   fPlan = 0;
   fftw_free((fftw_complex*)fIn);
   if (fOut)
      fftw_free(fOut);
   fIn = 0;
   fOut = 0;
   if (fN)
      delete [] fN;
   fN = 0;
}

//_____________________________________________________________________________
void TFFTComplexReal::Init( Option_t *flags, Int_t /*sign*/,const Int_t* /*kind*/)
{
//Creates the fftw-plan
//
//NOTE:  input and output arrays are overwritten during initialisation,
//       so don't set any points, before running this function!!!!!
//
//Arguments sign and kind are dummy and not need to be specified
//Possible flag_options:
//"ES" (from "estimate") - no time in preparing the transform, but probably sub-optimal
//   performanc
//"M" (from "measure") - some time spend in finding the optimal way to do the transform
//"P" (from "patient") - more time spend in finding the optimal way to do the transform
//"EX" (from "exhaustive") - the most optimal way is found
//This option should be chosen depending on how many transforms of the same size and
//type are going to be done. Planning is only done once, for the first transform of this
//size and type.

   fFlags = flags;

   if (fOut)
      fPlan = (void*)fftw_plan_dft_c2r(fNdim, fN,(fftw_complex*)fIn,(Double_t*)fOut, MapFlag(flags));
   else
      fPlan = (void*)fftw_plan_dft_c2r(fNdim, fN, (fftw_complex*)fIn, (Double_t*)fIn, MapFlag(flags));
}

//_____________________________________________________________________________
void TFFTComplexReal::Transform()
{
//Computes the transform, specified in Init() function

   if (fPlan)
      fftw_execute((fftw_plan)fPlan);
   else {
      Error("Transform", "transform was not initialized");
      return;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPoints(Double_t *data, Bool_t fromInput) const
{
//Fills the argument array with the computed transform
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPoints", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   std::copy(array,array+fTotalSize, data);
}

//_____________________________________________________________________________
Double_t TFFTComplexReal::GetPointReal(Int_t ipoint, Bool_t fromInput) const
{
//Returns the point #ipoint
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointReal", "Input array has been destroyed");
      return 0;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   return array[ipoint];
}

//_____________________________________________________________________________
Double_t TFFTComplexReal::GetPointReal(const Int_t *ipoint, Bool_t fromInput) const
{
//For multidimensional transforms. Returns the point #ipoint
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointReal", "Input array has been destroyed");
      return 0;
   }
   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-1; i++)
      ireal=fN[i+1]*ireal + ipoint[i+1];

   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   return array[ireal];
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointComplex(Int_t ipoint, Double_t &re, Double_t &im, Bool_t fromInput) const
{
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   re = array[ipoint];
   im = 0;
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointComplex(const Int_t *ipoint, Double_t &re, Double_t &im, Bool_t fromInput) const
{
//For multidimensional transforms. Returns the point #ipoint
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );

   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-1; i++)
      ireal=fN[i+1]*ireal + ipoint[i+1];

   re = array[ireal];
   im = 0;
}
//_____________________________________________________________________________
Double_t* TFFTComplexReal::GetPointsReal(Bool_t fromInput) const
{
//Returns the array of computed transform
// Works only for output (input array is destroyed in a C2R transform)

   // we have 2 different cases
   // fromInput = false; fOut = !NULL (transformed is not in place) : return fOut
   // fromInput = false; fOut = NULL (transformed is in place) : return fIn

   if (fromInput) {
      Error("GetPointsReal","Input array was destroyed");
      return 0;
   }
   return  (Double_t*) ( (fOut) ?  fOut :  fIn );
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointsComplex(Double_t *re, Double_t *im, Bool_t fromInput) const
{
//Fills the argument array with the computed transform
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointsComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   for (Int_t i=0; i<fTotalSize; i++){
      re[i] = array[i];
      im[i] = 0;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::GetPointsComplex(Double_t *data, Bool_t fromInput) const
{
//Fills the argument array with the computed transform.
// Works only for output (input array is destroyed in a C2R transform)

   if (fromInput){
      Error("GetPointsComplex", "Input array has been destroyed");
      return;
   }
   const Double_t * array =  (const Double_t*) ( (fOut) ?  fOut :  fIn );
   for (Int_t i=0; i<fTotalSize; i+=2){
      data[i] = array[i/2];
      data[i+1]=0;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPoint(Int_t ipoint, Double_t re, Double_t im)
{
//since the input must be complex-Hermitian, if the ipoint > n/2, the according
//point before n/2 is set to (re, -im)

   if (ipoint <= fN[0]/2){
      ((fftw_complex*)fIn)[ipoint][0] = re;
      ((fftw_complex*)fIn)[ipoint][1] = im;
   } else {
      ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][0] = re;
      ((fftw_complex*)fOut)[2*(fN[0]/2)-ipoint][1] = -im;
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPoint(const Int_t *ipoint, Double_t re, Double_t im)
{
//Set the point #ipoint. Since the input is Hermitian, only the first (roughly)half of
//the points have to be set.

   Int_t ireal = ipoint[0];
   for (Int_t i=0; i<fNdim-2; i++){
      ireal=fN[i+1]*ireal + ipoint[i+1];
   }
   ireal = (fN[fNdim-1]/2+1)*ireal+ipoint[fNdim-1];
   Int_t realN = Int_t(Double_t(fTotalSize)*(fN[fNdim-1]/2+1)/fN[fNdim-1]);

   if (ireal > realN){
      Error("SetPoint", "Illegal index value");
      return;
   }
   ((fftw_complex*)fIn)[ireal][0] = re;
   ((fftw_complex*)fIn)[ireal][1] = im;
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPointComplex(Int_t ipoint, TComplex &c)
{
//since the input must be complex-Hermitian, if the ipoint > n/2, the according
//point before n/2 is set to (re, -im)

   if (ipoint <= fN[0]/2){
      ((fftw_complex*)fIn)[ipoint][0] = c.Re();
      ((fftw_complex*)fIn)[ipoint][1] = c.Im();
   } else {
      ((fftw_complex*)fIn)[2*(fN[0]/2)-ipoint][0] = c.Re();
      ((fftw_complex*)fIn)[2*(fN[0]/2)-ipoint][1] = -c.Im();
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPoints(const Double_t *data)
{
//set all points. the values are copied. points should be ordered as follows:
//[re_0, im_0, re_1, im_1, ..., re_n, im_n)

   Int_t sizein = Int_t(Double_t(fTotalSize)*(fN[fNdim-1]/2+1)/fN[fNdim-1]);

   for (Int_t i=0; i<2*(sizein); i+=2){
      ((fftw_complex*)fIn)[i/2][0]=data[i];
      ((fftw_complex*)fIn)[i/2][1]=data[i+1];
   }
}

//_____________________________________________________________________________
void TFFTComplexReal::SetPointsComplex(const Double_t *re, const Double_t *im)
{
//Set all points. The values are copied.

   Int_t sizein = Int_t(Double_t(fTotalSize)*(fN[fNdim-1]/2+1)/fN[fNdim-1]);
   for (Int_t i=0; i<sizein; i++){
      ((fftw_complex*)fIn)[i][0]=re[i];
      ((fftw_complex*)fIn)[i][1]=im[i];
   }
}

//_____________________________________________________________________________
UInt_t TFFTComplexReal::MapFlag(Option_t *flag)
{
//allowed options:
//"ES" - FFTW_ESTIMATE
//"M" - FFTW_MEASURE
//"P" - FFTW_PATIENT
//"EX" - FFTW_EXHAUSTIVE

   TString opt = flag;
   opt.ToUpper();
   if (opt.Contains("ES"))
      return FFTW_ESTIMATE;
   if (opt.Contains("M"))
      return FFTW_MEASURE;
   if (opt.Contains("P"))
      return FFTW_PATIENT;
   if (opt.Contains("EX"))
      return FFTW_EXHAUSTIVE;
   return FFTW_ESTIMATE;
}
<|endoftext|>


<commit_before>#include "plant_generator.h"

#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <numeric>
#include <random>
#include <type_traits>

#include <asdf_multiplat/main/asdf_defs.h>

#include "from_json.h"

using namespace std;

namespace plantgen
{
    //std::vector<std::string> roll_multi_value(multi_value_t const& m);

    std::mt19937 mt_rand( std::chrono::high_resolution_clock::now().time_since_epoch().count() );

    int32_t random_int(uint32_t min, uint32_t max)
    {
        std::uniform_int_distribution<int> dis(min,max);
        return dis(mt_rand);
    }

    int32_t random_int(uint32_t max)
    {
        return random_int(0, max);
    }

    template <typename L>
    uint32_t total_weight(L const& list)
    {
        uint32_t total = 0;

        for(auto const& v : list)
            total += v.weight;

        return total;
    }

    std::vector<std::string> roll_multi_value(multi_value_t const& m)
    {
        if(m.num_to_pick >= m.values.size())
            return m.values;

        std::vector<size_t> inds(m.values.size());
        std::iota(inds.begin(), inds.end(), size_t(0)); //0, 1, 2, 3, ..., size-1
        std::shuffle(inds.begin(), inds.end(), std::mt19937{std::random_device{}()});

        std::vector<std::string> output;
        output.reserve(m.num_to_pick);

        for(size_t i = 0; i < m.num_to_pick; ++i)
            output.push_back(m.values[inds[i]]);

        return output;
    }

    std::vector<std::string> roll_range_value(range_value_t const& r)
    {
        std::vector<std::string> output;
        output.reserve(r.size());

        uint32_t counter = 0;
        for(size_t i = 0; i < r.size() - 1; ++i)
        {
            int roll = 0;

            if(counter < 100)
                roll = random_int(100 - counter);

            counter += roll;
            output.push_back(std::to_string(roll) + "% " + r[i]);
        }

        //push remaining
        output.push_back(std::to_string(100 - counter) + "% " + r.back());

        return output;
    }

    /// Runtime version (compile-time visitor pattern doesn't compile in msvc)
    std::vector<std::string> roll_value(variant_value_t const& variant_val)
    {
        std::vector<std::string> output;

        if(auto* s = std::get_if<std::string>(&variant_val))
        {
            output.push_back(*s);
        }
        else if(auto* r = std::get_if<range_value_t>(&variant_val))
        {
            auto rolled_range = roll_range_value(*r);
            output.insert(output.end(), rolled_range.begin(), rolled_range.end());
        }
        else if(auto* m = std::get_if<multi_value_t>(&variant_val))
        {
            auto rolled_multi = roll_multi_value(*m);
            output.insert(output.end(), rolled_multi.begin(), rolled_multi.end());
        }
        else
        {
            EXPLODE("unexpected variant sub-type");
        }

        return output;
    }

    generated_node_t roll_values(pregen_node_t const& node)
    {
        generated_node_t output_node;

        auto const& value_nodes = node.value_nodes;
        output_node.num_rollable_values = value_nodes.size();

        WARN_IF(value_nodes.empty(), "Rolling values for an empty list");
        if(value_nodes.empty())
            return generated_node_t();

        int roll = random_int(total_weight(value_nodes));

        //if no value from the value list has been hit yet, continue onward into value_nodes
        for(size_t i = 0; i < value_nodes.size(); ++i)
        {
            if(roll <= value_nodes[i].weight)
            {
                output_node.name = value_nodes[i].name;
                output_node.value_index = i;

                if(value_nodes[i].value.index() > 0)
                {
                    output_node.generated_values = roll_value(value_nodes[i].value);
                }
                else
                {
                    auto gend_node = generate_node(value_nodes[i]);
                    output_node.add_value_node(std::move(gend_node));
                }

                return output_node;
            }

            roll -= value_nodes[i].weight;
        }

        EXPLODE("Random roll was too large, ran out of values and value_nodes");
        return generated_node_t("ERROR");
    }

    pregen_node_t node_from_file(stdfs::path const& filepath)
    {
        using namespace std;

        auto ext = filepath.extension();
        if(ext == ".json")
        {
            return node_from_json(filepath);
        }
        else if(ext == ".yaml" || ext == ".yml")
        {
            cout << "TODO: yaml support";
            return pregen_node_t();
        }

        //TODO: exception?
        if(stdfs::is_directory(filepath))
            cout << filepath.string() << " is a directory, not a file";
        else
            cout << "Filetype " << ext << " not recognized";

        return pregen_node_t();
    }

    generated_node_t generate_node(pregen_node_t const& pre_node)
    {
        generated_node_t node;
        node.name = pre_node.name;
        node.weight = pre_node.weight;

        for(auto const& child : pre_node.children)
        {
            node.add_child(generate_node(child));
        }

        if(pre_node.value_nodes.size() > 0)
        {
            generated_node_t rolled = roll_values(pre_node);
            node.merge_with(rolled);
            ASSERT(node.weight == pre_node.weight, "Node merge affected weight unexpectedly");
        }

        // auto search = pre_node.user_data.find("PrintString");
        if(auto const* nd = find(pre_node.user_data, "PrintString"); nd)
        {
            node.print_string = std::get<std::string>(nd->value);
        }

        return node;
    }

    generated_node_t generate_node_from_file(stdfs::path const& filepath)
    {
        auto node = node_from_file(filepath);
        return generate_node(node);
    }

    constexpr size_t indent_amt = 4;
    // constexpr char indent_char = ' ';
    // constexpr char indent_tree_marker = ':';
    constexpr char const* indent_cstr = ":   ";

    std::string indenation_string(size_t indent_level)
    {
        if(indent_level == 0)
            return "";

        // std::string indent_str(indent_level * indent_amt, indent_char);
        // indent_str[indent_str.size()-indent_amt] = indent_tree_marker;

        std::string indent_str;
        for(size_t i = 0; i < indent_level; ++i)
            indent_str.insert(indent_str.end(), indent_cstr, indent_cstr + 4);

        return indent_str;
    }

    /// TODO: factor out similarities with below?
    /// TODO: use regular string concat rather than stringstream
    ///       I'm not using any of the features of SS that make it worth using
    string to_string(user_data_node_t const& node, size_t const depth, size_t level)
    {
        if(level > depth)
            return "";

        stringstream s;

        auto indent = indenation_string(level);

        s << indent << node.name_string() << ": ";

        if(is_leaf(node))
        {
            s << node.value;
            return s.str();
        }

        if(level + 1 > depth)
            return s.str();

        for(auto const& child : node.children)
            s << "\n" << to_string(child, depth, level + 1);

        return s.str();
    }

    string to_string(pregen_node_t const& node, size_t const depth, size_t level)
    {
        if(level > depth)
            return "";

        stringstream s;

        auto indent = indenation_string(level);
        string weight_str = node.weight == 1 ? ""
                                             : " (Weight " + std::to_string(node.weight) + ")";

        if(is_leaf(node))
        {
            s << indent << node.value << weight_str << "\n";
        }
        else
        {
            s << indent << node.name_string() << weight_str << "\n";
        }

        if(level + 1 > depth)
            return s.str();

        if(node.has_user_data())
            s << to_string(node.user_data, depth, level + 1) << "\n";

        for(auto const& child : node.children)
            s << to_string(child, depth, level + 1);

        indent.append(indenation_string(1));

        for(auto const& vnode : node.value_nodes)
            s << to_string(vnode, depth, level + 1);

        return s.str();
    }

    string to_string(generated_node_t const& node, size_t depth, size_t level)
    {
        if(level > depth)
            return "";

        stringstream s;

        auto indent = indenation_string(level);
        s << indent << node.name_string() << "\n";

        if(level + 1 > depth)
            return s.str();

        for(auto const& child : node.children)
            s << to_string(child, depth, level + 1);

        indent.append(indenation_string(1));

        for(auto const& value : node.generated_values)
            s << indent << value << "\n";

        for(auto const& vn : node.value_nodes)
            s << to_string(vn, depth, level + 1);

        return s.str();
    }

    void print_node(pregen_node_t const& node, size_t depth, size_t level)
    {
        cout << to_string(node, depth, level);
    }

    void print_node(generated_node_t const& node, size_t depth, size_t level)
    {
        cout << to_string(node, depth, level);
    }
}<commit_msg>fixed to_string(pregen_node_t const& node)<commit_after>#include "plant_generator.h"

#include <algorithm>
#include <chrono>
#include <functional>
#include <iostream>
#include <numeric>
#include <random>
#include <type_traits>

#include <asdf_multiplat/main/asdf_defs.h>

#include "from_json.h"

using namespace std;

namespace plantgen
{
    //std::vector<std::string> roll_multi_value(multi_value_t const& m);

    std::mt19937 mt_rand( std::chrono::high_resolution_clock::now().time_since_epoch().count() );

    int32_t random_int(uint32_t min, uint32_t max)
    {
        std::uniform_int_distribution<int> dis(min,max);
        return dis(mt_rand);
    }

    int32_t random_int(uint32_t max)
    {
        return random_int(0, max);
    }

    template <typename L>
    uint32_t total_weight(L const& list)
    {
        uint32_t total = 0;

        for(auto const& v : list)
            total += v.weight;

        return total;
    }

    std::vector<std::string> roll_multi_value(multi_value_t const& m)
    {
        if(m.num_to_pick >= m.values.size())
            return m.values;

        std::vector<size_t> inds(m.values.size());
        std::iota(inds.begin(), inds.end(), size_t(0)); //0, 1, 2, 3, ..., size-1
        std::shuffle(inds.begin(), inds.end(), std::mt19937{std::random_device{}()});

        std::vector<std::string> output;
        output.reserve(m.num_to_pick);

        for(size_t i = 0; i < m.num_to_pick; ++i)
            output.push_back(m.values[inds[i]]);

        return output;
    }

    std::vector<std::string> roll_range_value(range_value_t const& r)
    {
        std::vector<std::string> output;
        output.reserve(r.size());

        uint32_t counter = 0;
        for(size_t i = 0; i < r.size() - 1; ++i)
        {
            int roll = 0;

            if(counter < 100)
                roll = random_int(100 - counter);

            counter += roll;
            output.push_back(std::to_string(roll) + "% " + r[i]);
        }

        //push remaining
        output.push_back(std::to_string(100 - counter) + "% " + r.back());

        return output;
    }

    /// Runtime version (compile-time visitor pattern doesn't compile in msvc)
    std::vector<std::string> roll_value(variant_value_t const& variant_val)
    {
        std::vector<std::string> output;

        if(auto* s = std::get_if<std::string>(&variant_val))
        {
            output.push_back(*s);
        }
        else if(auto* r = std::get_if<range_value_t>(&variant_val))
        {
            auto rolled_range = roll_range_value(*r);
            output.insert(output.end(), rolled_range.begin(), rolled_range.end());
        }
        else if(auto* m = std::get_if<multi_value_t>(&variant_val))
        {
            auto rolled_multi = roll_multi_value(*m);
            output.insert(output.end(), rolled_multi.begin(), rolled_multi.end());
        }
        else
        {
            EXPLODE("unexpected variant sub-type");
        }

        return output;
    }

    generated_node_t roll_values(pregen_node_t const& node)
    {
        generated_node_t output_node;

        auto const& value_nodes = node.value_nodes;
        output_node.num_rollable_values = value_nodes.size();

        WARN_IF(value_nodes.empty(), "Rolling values for an empty list");
        if(value_nodes.empty())
            return generated_node_t();

        int roll = random_int(total_weight(value_nodes));

        //if no value from the value list has been hit yet, continue onward into value_nodes
        for(size_t i = 0; i < value_nodes.size(); ++i)
        {
            if(roll <= value_nodes[i].weight)
            {
                output_node.name = value_nodes[i].name;
                output_node.value_index = i;

                if(value_nodes[i].value.index() > 0)
                {
                    output_node.generated_values = roll_value(value_nodes[i].value);
                }
                else
                {
                    auto gend_node = generate_node(value_nodes[i]);
                    output_node.add_value_node(std::move(gend_node));
                }

                return output_node;
            }

            roll -= value_nodes[i].weight;
        }

        EXPLODE("Random roll was too large, ran out of values and value_nodes");
        return generated_node_t("ERROR");
    }

    pregen_node_t node_from_file(stdfs::path const& filepath)
    {
        using namespace std;

        auto ext = filepath.extension();
        if(ext == ".json")
        {
            return node_from_json(filepath);
        }
        else if(ext == ".yaml" || ext == ".yml")
        {
            cout << "TODO: yaml support";
            return pregen_node_t();
        }

        //TODO: exception?
        if(stdfs::is_directory(filepath))
            cout << filepath.string() << " is a directory, not a file";
        else
            cout << "Filetype " << ext << " not recognized";

        return pregen_node_t();
    }

    generated_node_t generate_node(pregen_node_t const& pre_node)
    {
        generated_node_t node;
        node.name = pre_node.name;
        node.weight = pre_node.weight;

        for(auto const& child : pre_node.children)
        {
            node.add_child(generate_node(child));
        }

        if(pre_node.value_nodes.size() > 0)
        {
            generated_node_t rolled = roll_values(pre_node);
            node.merge_with(rolled);
            ASSERT(node.weight == pre_node.weight, "Node merge affected weight unexpectedly");
        }

        // auto search = pre_node.user_data.find("PrintString");
        if(auto const* nd = find(pre_node.user_data, "PrintString"); nd)
        {
            node.print_string = std::get<std::string>(nd->value);
        }

        return node;
    }

    generated_node_t generate_node_from_file(stdfs::path const& filepath)
    {
        auto node = node_from_file(filepath);
        return generate_node(node);
    }

    constexpr size_t indent_amt = 4;
    // constexpr char indent_char = ' ';
    // constexpr char indent_tree_marker = ':';
    constexpr char const* indent_cstr = ":   ";

    std::string indenation_string(size_t indent_level)
    {
        if(indent_level == 0)
            return "";

        // std::string indent_str(indent_level * indent_amt, indent_char);
        // indent_str[indent_str.size()-indent_amt] = indent_tree_marker;

        std::string indent_str;
        for(size_t i = 0; i < indent_level; ++i)
            indent_str.insert(indent_str.end(), indent_cstr, indent_cstr + 4);

        return indent_str;
    }

    /// TODO: factor out similarities with below?
    /// TODO: use regular string concat rather than stringstream
    ///       I'm not using any of the features of SS that make it worth using
    string to_string(user_data_node_t const& node, size_t const depth, size_t level)
    {
        if(level > depth)
            return "";

        stringstream s;

        auto indent = indenation_string(level);

        s << indent << node.name_string() << ": ";

        if(is_leaf(node))
        {
            s << node.value;
            return s.str();
        }

        if(level + 1 > depth)
            return s.str();

        for(auto const& child : node.children)
            s << "\n" << to_string(child, depth, level + 1);

        return s.str();
    }

    string to_string(pregen_node_t const& node, size_t const depth, size_t level)
    {
        if(level > depth)
            return "";

        stringstream s;

        auto indent = indenation_string(level);

        s << indent;

        if(node.name.size() > 0)
            s << node.name_string();

        if(node.value.index() > 0)
            s << node.value;

        if(node.weight != 1)
            s << " (Weight " + std::to_string(node.weight) + ")";

        s << "\n";

        if(level + 1 > depth)
            return s.str();

        if(node.has_user_data())
            s << to_string(node.user_data, depth, level + 1) << "\n";

        for(auto const& child : node.children)
            s << to_string(child, depth, level + 1);

        indent.append(indenation_string(1));

        for(auto const& vnode : node.value_nodes)
            s << to_string(vnode, depth, level + 1);

        return s.str();
    }

    string to_string(generated_node_t const& node, size_t depth, size_t level)
    {
        if(level > depth)
            return "";

        stringstream s;

        auto indent = indenation_string(level);
        s << indent << node.name_string() << "\n";

        if(level + 1 > depth)
            return s.str();

        for(auto const& child : node.children)
            s << to_string(child, depth, level + 1);

        indent.append(indenation_string(1));

        for(auto const& value : node.generated_values)
            s << indent << value << "\n";

        for(auto const& vn : node.value_nodes)
            s << to_string(vn, depth, level + 1);

        return s.str();
    }

    void print_node(pregen_node_t const& node, size_t depth, size_t level)
    {
        cout << to_string(node, depth, level);
    }

    void print_node(generated_node_t const& node, size_t depth, size_t level)
    {
        cout << to_string(node, depth, level);
    }
}<|endoftext|>


<commit_before>#include "ContentWindowManager.h"
#include "Content.h"
#include "DisplayGroupManager.h"
#include "main.h"

ContentWindowManager::ContentWindowManager(boost::shared_ptr<Content> content)
{
    // content dimensions
    content->getDimensions(contentWidth_, contentHeight_);

    // default position / size, assumes a 16/9 aspect ratio
    // the actual aspect ratio will be set after the content is loaded
    x_ = y_ = 0.;
    w_ = 0.1;
    h_ = (double)g_configuration->getTotalWidth() / (double)g_configuration->getTotalHeight() * 9/16. * w_;

    // default to centered
    centerX_ = 0.5;
    centerY_ = 0.5;

    // default to no zoom
    zoom_ = 1.;

    // default window state
    selected_ = false;

    // set content object
    content_ = content;

    // receive updates to content dimensions
    connect(content.get(), SIGNAL(dimensionsChanged(int, int)), this, SLOT(setContentDimensions(int, int)));
}

boost::shared_ptr<Content> ContentWindowManager::getContent()
{
    return content_;
}

boost::shared_ptr<DisplayGroupManager> ContentWindowManager::getDisplayGroupManager()
{
    return displayGroupManager_.lock();
}

void ContentWindowManager::setDisplayGroupManager(boost::shared_ptr<DisplayGroupManager> displayGroupManager)
{
    // disconnect any existing signals to previous DisplayGroupManager
    boost::shared_ptr<DisplayGroupManager> oldDisplayGroupManager = getDisplayGroupManager();

    if(oldDisplayGroupManager != NULL)
    {
        disconnect(this, 0, oldDisplayGroupManager.get(), 0);
    }

    displayGroupManager_ = displayGroupManager;

    // make connections to new DisplayGroupManager
    // don't use queued connections; we want these to execute immediately and we're in the same thread
    if(displayGroupManager != NULL)
    {
        connect(this, SIGNAL(contentDimensionsChanged(int, int, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(coordinatesChanged(double, double, double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(positionChanged(double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(sizeChanged(double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(centerChanged(double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(zoomChanged(double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(selectedChanged(bool, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));

        // we don't call sendDisplayGroup() on movedToFront() or destroyed() since it happens already
    }
}

void ContentWindowManager::moveToFront(ContentWindowInterface * source)
{
    ContentWindowInterface::moveToFront(source);

    if(source != this)
    {
        getDisplayGroupManager()->moveContentWindowManagerToFront(shared_from_this());
    }
}

void ContentWindowManager::close(ContentWindowInterface * source)
{
    ContentWindowInterface::close(source);

    if(source != this)
    {
        getDisplayGroupManager()->removeContentWindowManager(shared_from_this());
    }
}

void ContentWindowManager::render()
{
    content_->render(shared_from_this());

    // optionally render the border
    bool showWindowBorders = true;

    boost::shared_ptr<DisplayGroupManager> dgm = getDisplayGroupManager();

    if(dgm != NULL)
    {
        showWindowBorders = dgm->getOptions()->getShowWindowBorders();
    }

    if(showWindowBorders == true)
    {
        double horizontalBorder = 5. / (double)g_configuration->getTotalHeight(); // 5 pixels
        double verticalBorder = (double)g_configuration->getTotalHeight() / (double)g_configuration->getTotalWidth() * horizontalBorder;

        glPushAttrib(GL_CURRENT_BIT);

        // color the border based on window state
        if(selected_ == true)
        {
            glColor4f(1,0,0,1);
        }
        else
        {
            glColor4f(1,1,1,1);
        }

        GLWindow::drawRectangle(x_-verticalBorder,y_-horizontalBorder,w_+2.*verticalBorder,h_+2.*horizontalBorder);

        glPopAttrib();
    }

    glPushAttrib(GL_CURRENT_BIT);

    // render buttons if any of the markers are over the window
    bool markerOverWindow = false;

    std::vector<boost::shared_ptr<Marker> > markers = getDisplayGroupManager()->getMarkers();

    for(unsigned int i=0; i<markers.size(); i++)
    {
        float markerX, markerY;
        markers[i]->getPosition(markerX, markerY);

        if(QRectF(x_, y_, w_, h_).contains(markerX, markerY) == true)
        {
            markerOverWindow = true;
            break;
        }
    }

    if(markerOverWindow == true)
    {
        // we need this to be slightly in front of the rest of the window
        glPushMatrix();
        glTranslatef(0,0,0.001);

        // button dimensions
        float buttonWidth, buttonHeight;
        getButtonDimensions(buttonWidth, buttonHeight);

        // draw close button
        QRectF closeRect(x_ + w_ - buttonWidth, y_, buttonWidth, buttonHeight);

        // semi-transparent background
        glColor4f(1,0,0,0.125);

        glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_BLEND);
        glDepthMask(GL_FALSE);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glBegin(GL_QUADS);
        glVertex2f(closeRect.x(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y()+closeRect.height());
        glVertex2f(closeRect.x(), closeRect.y()+closeRect.height());
        glEnd();

        glPopAttrib();

        glColor4f(1,0,0,1);

        glBegin(GL_LINE_LOOP);
        glVertex2f(closeRect.x(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y()+closeRect.height());
        glVertex2f(closeRect.x(), closeRect.y()+closeRect.height());
        glEnd();

        glBegin(GL_LINES);
        glVertex2f(closeRect.x(), closeRect.y());
        glVertex2f(closeRect.x() + closeRect.width(), closeRect.y() + closeRect.height());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y());
        glVertex2f(closeRect.x(), closeRect.y() + closeRect.height());
        glEnd();

        // resize indicator
        QRectF resizeRect(x_ + w_ - buttonWidth, y_ + h_ - buttonHeight, buttonWidth, buttonHeight);

        // semi-transparent background
        glColor4f(0.5,0.5,0.5,0.25);

        glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_BLEND);
        glDepthMask(GL_FALSE);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glBegin(GL_QUADS);
        glVertex2f(resizeRect.x(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y()+resizeRect.height());
        glVertex2f(resizeRect.x(), resizeRect.y()+resizeRect.height());
        glEnd();

        glPopAttrib();

        glColor4f(0.5,0.5,0.5,1);

        glBegin(GL_LINE_LOOP);
        glVertex2f(resizeRect.x(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y()+resizeRect.height());
        glVertex2f(resizeRect.x(), resizeRect.y()+resizeRect.height());
        glEnd();

        glBegin(GL_LINES);
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y());
        glVertex2f(resizeRect.x(), resizeRect.y() + resizeRect.height());
        glEnd();

        glPopMatrix();
    }

    glPopAttrib();
}
<commit_msg>setting default window size based on height instead of width. window origin slightly offset from origin.<commit_after>#include "ContentWindowManager.h"
#include "Content.h"
#include "DisplayGroupManager.h"
#include "main.h"

ContentWindowManager::ContentWindowManager(boost::shared_ptr<Content> content)
{
    // content dimensions
    content->getDimensions(contentWidth_, contentHeight_);

    // default position / size, assumes a 16/9 aspect ratio
    // the actual aspect ratio will be set after the content is loaded
    x_ = y_ = 0.01;
    h_ = 0.2;
    w_ = (double)g_configuration->getTotalHeight() / (double)g_configuration->getTotalWidth() * 9/16. * h_;

    // default to centered
    centerX_ = 0.5;
    centerY_ = 0.5;

    // default to no zoom
    zoom_ = 1.;

    // default window state
    selected_ = false;

    // set content object
    content_ = content;

    // receive updates to content dimensions
    connect(content.get(), SIGNAL(dimensionsChanged(int, int)), this, SLOT(setContentDimensions(int, int)));
}

boost::shared_ptr<Content> ContentWindowManager::getContent()
{
    return content_;
}

boost::shared_ptr<DisplayGroupManager> ContentWindowManager::getDisplayGroupManager()
{
    return displayGroupManager_.lock();
}

void ContentWindowManager::setDisplayGroupManager(boost::shared_ptr<DisplayGroupManager> displayGroupManager)
{
    // disconnect any existing signals to previous DisplayGroupManager
    boost::shared_ptr<DisplayGroupManager> oldDisplayGroupManager = getDisplayGroupManager();

    if(oldDisplayGroupManager != NULL)
    {
        disconnect(this, 0, oldDisplayGroupManager.get(), 0);
    }

    displayGroupManager_ = displayGroupManager;

    // make connections to new DisplayGroupManager
    // don't use queued connections; we want these to execute immediately and we're in the same thread
    if(displayGroupManager != NULL)
    {
        connect(this, SIGNAL(contentDimensionsChanged(int, int, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(coordinatesChanged(double, double, double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(positionChanged(double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(sizeChanged(double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(centerChanged(double, double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(zoomChanged(double, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));
        connect(this, SIGNAL(selectedChanged(bool, ContentWindowInterface *)), displayGroupManager.get(), SLOT(sendDisplayGroup()));

        // we don't call sendDisplayGroup() on movedToFront() or destroyed() since it happens already
    }
}

void ContentWindowManager::moveToFront(ContentWindowInterface * source)
{
    ContentWindowInterface::moveToFront(source);

    if(source != this)
    {
        getDisplayGroupManager()->moveContentWindowManagerToFront(shared_from_this());
    }
}

void ContentWindowManager::close(ContentWindowInterface * source)
{
    ContentWindowInterface::close(source);

    if(source != this)
    {
        getDisplayGroupManager()->removeContentWindowManager(shared_from_this());
    }
}

void ContentWindowManager::render()
{
    content_->render(shared_from_this());

    // optionally render the border
    bool showWindowBorders = true;

    boost::shared_ptr<DisplayGroupManager> dgm = getDisplayGroupManager();

    if(dgm != NULL)
    {
        showWindowBorders = dgm->getOptions()->getShowWindowBorders();
    }

    if(showWindowBorders == true)
    {
        double horizontalBorder = 5. / (double)g_configuration->getTotalHeight(); // 5 pixels
        double verticalBorder = (double)g_configuration->getTotalHeight() / (double)g_configuration->getTotalWidth() * horizontalBorder;

        glPushAttrib(GL_CURRENT_BIT);

        // color the border based on window state
        if(selected_ == true)
        {
            glColor4f(1,0,0,1);
        }
        else
        {
            glColor4f(1,1,1,1);
        }

        GLWindow::drawRectangle(x_-verticalBorder,y_-horizontalBorder,w_+2.*verticalBorder,h_+2.*horizontalBorder);

        glPopAttrib();
    }

    glPushAttrib(GL_CURRENT_BIT);

    // render buttons if any of the markers are over the window
    bool markerOverWindow = false;

    std::vector<boost::shared_ptr<Marker> > markers = getDisplayGroupManager()->getMarkers();

    for(unsigned int i=0; i<markers.size(); i++)
    {
        float markerX, markerY;
        markers[i]->getPosition(markerX, markerY);

        if(QRectF(x_, y_, w_, h_).contains(markerX, markerY) == true)
        {
            markerOverWindow = true;
            break;
        }
    }

    if(markerOverWindow == true)
    {
        // we need this to be slightly in front of the rest of the window
        glPushMatrix();
        glTranslatef(0,0,0.001);

        // button dimensions
        float buttonWidth, buttonHeight;
        getButtonDimensions(buttonWidth, buttonHeight);

        // draw close button
        QRectF closeRect(x_ + w_ - buttonWidth, y_, buttonWidth, buttonHeight);

        // semi-transparent background
        glColor4f(1,0,0,0.125);

        glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_BLEND);
        glDepthMask(GL_FALSE);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glBegin(GL_QUADS);
        glVertex2f(closeRect.x(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y()+closeRect.height());
        glVertex2f(closeRect.x(), closeRect.y()+closeRect.height());
        glEnd();

        glPopAttrib();

        glColor4f(1,0,0,1);

        glBegin(GL_LINE_LOOP);
        glVertex2f(closeRect.x(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y()+closeRect.height());
        glVertex2f(closeRect.x(), closeRect.y()+closeRect.height());
        glEnd();

        glBegin(GL_LINES);
        glVertex2f(closeRect.x(), closeRect.y());
        glVertex2f(closeRect.x() + closeRect.width(), closeRect.y() + closeRect.height());
        glVertex2f(closeRect.x()+closeRect.width(), closeRect.y());
        glVertex2f(closeRect.x(), closeRect.y() + closeRect.height());
        glEnd();

        // resize indicator
        QRectF resizeRect(x_ + w_ - buttonWidth, y_ + h_ - buttonHeight, buttonWidth, buttonHeight);

        // semi-transparent background
        glColor4f(0.5,0.5,0.5,0.25);

        glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_BLEND);
        glDepthMask(GL_FALSE);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glBegin(GL_QUADS);
        glVertex2f(resizeRect.x(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y()+resizeRect.height());
        glVertex2f(resizeRect.x(), resizeRect.y()+resizeRect.height());
        glEnd();

        glPopAttrib();

        glColor4f(0.5,0.5,0.5,1);

        glBegin(GL_LINE_LOOP);
        glVertex2f(resizeRect.x(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y());
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y()+resizeRect.height());
        glVertex2f(resizeRect.x(), resizeRect.y()+resizeRect.height());
        glEnd();

        glBegin(GL_LINES);
        glVertex2f(resizeRect.x()+resizeRect.width(), resizeRect.y());
        glVertex2f(resizeRect.x(), resizeRect.y() + resizeRect.height());
        glEnd();

        glPopMatrix();
    }

    glPopAttrib();
}
<|endoftext|>


<commit_before>#ifdef __APPLE__
#include <copyfile.h>
#endif
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>

#include "rtl_exec.h"
#include "enums.inc"

static void handle_error(int error, const utf8string &path)
{
    switch (error) {
        case EACCES: throw RtlException(rtl::ne_file::Exception_FileException_PermissionDenied, path);
        case EEXIST: throw RtlException(rtl::ne_file::Exception_FileException_DirectoryExists, path);
        case ENOENT: throw RtlException(rtl::ne_file::Exception_FileException_PathNotFound, path);
        default:
            throw RtlException(rtl::ne_file::Exception_FileException, path + ": " + strerror(error));
    }
}

namespace rtl {

namespace ne_file {

utf8string _CONSTANT_Separator()
{
    return utf8string("/");
}

void copy(const utf8string &filename, const utf8string &destination)
{
#ifdef __APPLE__
    int r = copyfile(filename.c_str(), destination.c_str(), NULL, COPYFILE_ALL|COPYFILE_EXCL);
    if (r != 0) {
        if (errno == EEXIST) {
            throw RtlException(Exception_FileException_Exists, destination);
        }
        handle_error(errno, filename);
    }
#else
    int sourcefd = open(filename.c_str(), O_RDONLY);
    if (sourcefd < 0) {
        handle_error(errno, filename);
    }
    struct stat statbuf;
    int r = fstat(sourcefd, &statbuf);
    if (r != 0) {
        int error = errno;
        close(sourcefd);
        handle_error(error, filename);
    }
    int destfd = open(destination.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0);
    if (destfd < 0) {
        int error = errno;
        close(sourcefd);
        if (error == EEXIST) {
            throw RtlException(Exception_FileException_Exists, destination);
        }
        handle_error(error, destination);
    }
    char buf[BUFSIZ];
    for (;;) {
        ssize_t n = read(sourcefd, buf, sizeof(buf));
        if (n < 0) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, filename);
        } else if (n == 0) {
            break;
        }
        ssize_t written = write(destfd, buf, n);
        if (written < n) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, destination);
        }
    }
    close(sourcefd);
    if (fchmod(destfd, statbuf.st_mode) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    if (fchown(destfd, statbuf.st_uid, statbuf.st_gid) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    close(destfd);
    struct utimbuf utimebuf;
    utimebuf.actime = statbuf.st_atime;
    utimebuf.modtime = statbuf.st_mtime;
    utime(destination.c_str(), &utimebuf);
#endif
}

void copyOverwriteIfExists(const utf8string &filename, const utf8string &destination)
{
#ifdef __APPLE__
    int r = copyfile(filename.c_str(), destination.c_str(), NULL, COPYFILE_ALL);
    if (r != 0) {
        handle_error(errno, filename);
    }
#else
    int sourcefd = open(filename.c_str(), O_RDONLY);
    if (sourcefd < 0) {
        handle_error(errno, filename);
    }
    struct stat statbuf;
    int r = fstat(sourcefd, &statbuf);
    if (r != 0) {
        int error = errno;
        close(sourcefd);
        handle_error(error, filename);
    }
    int destfd = open(destination.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0);
    if (destfd < 0) {
        int error = errno;
        close(sourcefd);
        handle_error(error, destination);
    }
    char buf[BUFSIZ];
    for (;;) {
        ssize_t n = read(sourcefd, buf, sizeof(buf));
        if (n < 0) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, filename);
        } else if (n == 0) {
            break;
        }
        ssize_t written = write(destfd, buf, n);
        if (written < n) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, destination);
        }
    }
    close(sourcefd);
    if (fchmod(destfd, statbuf.st_mode) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    if (fchown(destfd, statbuf.st_uid, statbuf.st_gid) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    close(destfd);
    struct utimbuf utimebuf;
    utimebuf.actime = statbuf.st_atime;
    utimebuf.modtime = statbuf.st_mtime;
    utime(destination.c_str(), &utimebuf);
#endif
}

void delete_(const utf8string &filename)
{
    int r = unlink(filename.c_str());
    if (r != 0) {
        if (errno != ENOENT) {
            handle_error(errno, filename);
        }
    }
}

bool exists(const utf8string &filename)
{
    return access(filename.c_str(), F_OK) == 0;
}

std::vector<utf8string> files(const utf8string &path)
{
    std::vector<utf8string> r;
    DIR *d = opendir(path.c_str());
    if (d != NULL) {
        for (;;) {
            struct dirent *de = readdir(d);
            if (de == NULL) {
                break;
            }
            r.push_back(utf8string(de->d_name));
        }
        closedir(d);
    }
    return r;
}

Cell getInfo(const utf8string &name)
{
    struct stat st;
    if (stat(name.c_str(), &st) != 0) {
        handle_error(errno, name);
    }
    std::vector<Cell> r;
    r.push_back(Cell(name.str().rfind('/') != std::string::npos ? utf8string(name.str().substr(name.str().rfind('/')+1)) : name));
    r.push_back(Cell(number_from_uint64(st.st_size)));
    r.push_back(Cell(bool(st.st_mode & 0x04)));
    r.push_back(Cell(bool(st.st_mode & 0x02)));
    r.push_back(Cell(bool(st.st_mode & 0x01)));
    r.push_back(Cell(number_from_uint32(
        S_ISREG(st.st_mode) ? ENUM_FileType_normal :
        S_ISDIR(st.st_mode) ? ENUM_FileType_directory :
        ENUM_FileType_special
    )));
    r.push_back(Cell(Number()));
    r.push_back(Cell(number_from_uint32(st.st_atime)));
    r.push_back(Cell(number_from_uint32(st.st_mtime)));
    return Cell(r);
}

bool isDirectory(const utf8string &path)
{
    struct stat st;
    return stat(path.c_str(), &st) == 0 && (st.st_mode & S_IFDIR) != 0;
}

void mkdir(const utf8string &path)
{
    int r = ::mkdir(path.c_str(), 0755);
    if (r != 0) {
        handle_error(errno, path);
    }
}

void removeEmptyDirectory(const utf8string &path)
{
    int r = rmdir(path.c_str());
    if (r != 0) {
        handle_error(errno, path);
    }
}

void rename(const utf8string &oldname, const utf8string &newname)
{
    int r = ::rename(oldname.c_str(), newname.c_str());
    if (r != 0) {
        handle_error(errno, oldname);
    }
}

void symlink(const utf8string &target, const utf8string &newlink, bool /*targetIsDirectory*/)
{
    int r = ::symlink(target.c_str(), newlink.c_str());
    if (r != 0) {
        handle_error(errno, newlink);
    }
}

} // namespace ne_file

} // namespace rtl
<commit_msg>Use S_ISDIR instead of S_IFDIR<commit_after>#ifdef __APPLE__
#include <copyfile.h>
#endif
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>

#include "rtl_exec.h"
#include "enums.inc"

static void handle_error(int error, const utf8string &path)
{
    switch (error) {
        case EACCES: throw RtlException(rtl::ne_file::Exception_FileException_PermissionDenied, path);
        case EEXIST: throw RtlException(rtl::ne_file::Exception_FileException_DirectoryExists, path);
        case ENOENT: throw RtlException(rtl::ne_file::Exception_FileException_PathNotFound, path);
        default:
            throw RtlException(rtl::ne_file::Exception_FileException, path + ": " + strerror(error));
    }
}

namespace rtl {

namespace ne_file {

utf8string _CONSTANT_Separator()
{
    return utf8string("/");
}

void copy(const utf8string &filename, const utf8string &destination)
{
#ifdef __APPLE__
    int r = copyfile(filename.c_str(), destination.c_str(), NULL, COPYFILE_ALL|COPYFILE_EXCL);
    if (r != 0) {
        if (errno == EEXIST) {
            throw RtlException(Exception_FileException_Exists, destination);
        }
        handle_error(errno, filename);
    }
#else
    int sourcefd = open(filename.c_str(), O_RDONLY);
    if (sourcefd < 0) {
        handle_error(errno, filename);
    }
    struct stat statbuf;
    int r = fstat(sourcefd, &statbuf);
    if (r != 0) {
        int error = errno;
        close(sourcefd);
        handle_error(error, filename);
    }
    int destfd = open(destination.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_EXCL, 0);
    if (destfd < 0) {
        int error = errno;
        close(sourcefd);
        if (error == EEXIST) {
            throw RtlException(Exception_FileException_Exists, destination);
        }
        handle_error(error, destination);
    }
    char buf[BUFSIZ];
    for (;;) {
        ssize_t n = read(sourcefd, buf, sizeof(buf));
        if (n < 0) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, filename);
        } else if (n == 0) {
            break;
        }
        ssize_t written = write(destfd, buf, n);
        if (written < n) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, destination);
        }
    }
    close(sourcefd);
    if (fchmod(destfd, statbuf.st_mode) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    if (fchown(destfd, statbuf.st_uid, statbuf.st_gid) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    close(destfd);
    struct utimbuf utimebuf;
    utimebuf.actime = statbuf.st_atime;
    utimebuf.modtime = statbuf.st_mtime;
    utime(destination.c_str(), &utimebuf);
#endif
}

void copyOverwriteIfExists(const utf8string &filename, const utf8string &destination)
{
#ifdef __APPLE__
    int r = copyfile(filename.c_str(), destination.c_str(), NULL, COPYFILE_ALL);
    if (r != 0) {
        handle_error(errno, filename);
    }
#else
    int sourcefd = open(filename.c_str(), O_RDONLY);
    if (sourcefd < 0) {
        handle_error(errno, filename);
    }
    struct stat statbuf;
    int r = fstat(sourcefd, &statbuf);
    if (r != 0) {
        int error = errno;
        close(sourcefd);
        handle_error(error, filename);
    }
    int destfd = open(destination.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0);
    if (destfd < 0) {
        int error = errno;
        close(sourcefd);
        handle_error(error, destination);
    }
    char buf[BUFSIZ];
    for (;;) {
        ssize_t n = read(sourcefd, buf, sizeof(buf));
        if (n < 0) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, filename);
        } else if (n == 0) {
            break;
        }
        ssize_t written = write(destfd, buf, n);
        if (written < n) {
            int error = errno;
            close(sourcefd);
            close(destfd);
            unlink(destination.c_str());
            handle_error(error, destination);
        }
    }
    close(sourcefd);
    if (fchmod(destfd, statbuf.st_mode) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    if (fchown(destfd, statbuf.st_uid, statbuf.st_gid) != 0) {
        int error = errno;
        close(sourcefd);
        close(destfd);
        unlink(destination.c_str());
        handle_error(error, destination);
    }
    close(destfd);
    struct utimbuf utimebuf;
    utimebuf.actime = statbuf.st_atime;
    utimebuf.modtime = statbuf.st_mtime;
    utime(destination.c_str(), &utimebuf);
#endif
}

void delete_(const utf8string &filename)
{
    int r = unlink(filename.c_str());
    if (r != 0) {
        if (errno != ENOENT) {
            handle_error(errno, filename);
        }
    }
}

bool exists(const utf8string &filename)
{
    return access(filename.c_str(), F_OK) == 0;
}

std::vector<utf8string> files(const utf8string &path)
{
    std::vector<utf8string> r;
    DIR *d = opendir(path.c_str());
    if (d != NULL) {
        for (;;) {
            struct dirent *de = readdir(d);
            if (de == NULL) {
                break;
            }
            r.push_back(utf8string(de->d_name));
        }
        closedir(d);
    }
    return r;
}

Cell getInfo(const utf8string &name)
{
    struct stat st;
    if (stat(name.c_str(), &st) != 0) {
        handle_error(errno, name);
    }
    std::vector<Cell> r;
    r.push_back(Cell(name.str().rfind('/') != std::string::npos ? utf8string(name.str().substr(name.str().rfind('/')+1)) : name));
    r.push_back(Cell(number_from_uint64(st.st_size)));
    r.push_back(Cell(bool(st.st_mode & 0x04)));
    r.push_back(Cell(bool(st.st_mode & 0x02)));
    r.push_back(Cell(bool(st.st_mode & 0x01)));
    r.push_back(Cell(number_from_uint32(
        S_ISREG(st.st_mode) ? ENUM_FileType_normal :
        S_ISDIR(st.st_mode) ? ENUM_FileType_directory :
        ENUM_FileType_special
    )));
    r.push_back(Cell(Number()));
    r.push_back(Cell(number_from_uint32(st.st_atime)));
    r.push_back(Cell(number_from_uint32(st.st_mtime)));
    return Cell(r);
}

bool isDirectory(const utf8string &path)
{
    struct stat st;
    return stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
}

void mkdir(const utf8string &path)
{
    int r = ::mkdir(path.c_str(), 0755);
    if (r != 0) {
        handle_error(errno, path);
    }
}

void removeEmptyDirectory(const utf8string &path)
{
    int r = rmdir(path.c_str());
    if (r != 0) {
        handle_error(errno, path);
    }
}

void rename(const utf8string &oldname, const utf8string &newname)
{
    int r = ::rename(oldname.c_str(), newname.c_str());
    if (r != 0) {
        handle_error(errno, oldname);
    }
}

void symlink(const utf8string &target, const utf8string &newlink, bool /*targetIsDirectory*/)
{
    int r = ::symlink(target.c_str(), newlink.c_str());
    if (r != 0) {
        handle_error(errno, newlink);
    }
}

} // namespace ne_file

} // namespace rtl
<|endoftext|>


<commit_before>
#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
#include "rtkRayBoxIntersectionImageFilter.h"
#include "rtkJosephForwardProjectionImageFilter.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"

template<class TImage>
void CheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)
{
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType TestVal = itTest.Get();
    typename TImage::PixelType RefVal = itRef.Get();

    if( TestVal != RefVal )
      {
      TestError += vcl_abs(RefVal - TestVal);
      EnerError += vcl_pow(ErrorType(RefVal - TestVal), 2.);
      }
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/recon->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(255.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;
  // QI
  ErrorType QI = (255.0-ErrorPerPixel)/255.0;
  std::cout << "QI = " << QI << std::endl;

  // Checking results
  if (ErrorPerPixel > 1.25)
    {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of 1.25" << std::endl;
    exit( EXIT_FAILURE);
    }
  if (PSNR < 44.)
    {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of 44" << std::endl;
    exit( EXIT_FAILURE);
    }
}

int main(int , char** )
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::Vector<double, 3>                   VectorType;
  const unsigned int NumberOfProjectionImages = 45;

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  // The test projects a volume filled with ones. The forward projector should
  // then return the intersection of the ray with the box and it is compared
  // with the analytical intersection of a box with a ray.

  // Create Joseph Forward Projector volume input.
  const ConstantImageSourceType::Pointer volInput = ConstantImageSourceType::New();
  origin[0] = -126;
  origin[1] = -126;
  origin[2] = -126;
  size[0] = 64;
  size[1] = 64;
  size[2] = 64;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 1. );
  volInput->UpdateOutputInformation();

  // Initialization Volume, it is used in the Joseph Forward Projector and in the
  // Ray Box Intersection Filter in order to initialize the stack of projections.
  const ConstantImageSourceType::Pointer projInput = ConstantImageSourceType::New();
  size[2] = NumberOfProjectionImages;
  projInput->SetOrigin( origin );
  projInput->SetSpacing( spacing );
  projInput->SetSize( size );
  projInput->SetConstant( 0. );
  projInput->Update();

  // Joseph Forward Projection filter
  typedef rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType> JFPType;
  JFPType::Pointer jfp = JFPType::New();
  jfp->InPlaceOff();
  jfp->SetInput( projInput->GetOutput() );
  jfp->SetInput( 1, volInput->GetOutput() );

  // Ray Box Intersection filter (reference)
  typedef rtk::RayBoxIntersectionImageFilter<OutputImageType, OutputImageType> RBIType;
  RBIType::Pointer rbi = RBIType::New();
  rbi->InPlaceOff();
  rbi->SetInput( projInput->GetOutput() );
  VectorType boxMin, boxMax;
  boxMin[0] = -128.0;
  boxMin[1] = -128.0;
  boxMin[2] = -128.0;
  boxMax[0] =  128.0;
  boxMax[1] =  128.0;
  boxMax[2] =   47.6;
  rbi->SetBoxMin(boxMin);
  rbi->SetBoxMax(boxMax);

  std::cout << "\n\n****** Case 1: inner ray source ******" << std::endl;
  // The circle is divided in 4 quarters
  for(int q=0; q<4; q++) {
    // Geometry
    typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
    GeometryType::Pointer geometry = GeometryType::New();
    for(unsigned int i=0; i<NumberOfProjectionImages;i++)
      {
      const double angle = -45. + i*2.;
      geometry->AddProjection(47.6 / vcl_cos(angle*itk::Math::pi/180.), 1000., q*90+angle);
      }

    if(q==0) {
      rbi->SetGeometry( geometry );
      rbi->Update();
    }

    jfp->SetGeometry(geometry);
    jfp->Update();

    CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
    std::cout << "\n\nTest of quarter #" << q << " PASSED! " << std::endl;
  }

  std::cout << "\n\n****** Case 2: outer ray source ******" << std::endl;
  boxMax[2] = 128.0;
  rbi->SetBoxMax(boxMax);

  // Geometry
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(500., 1000., i*8.);

  rbi->SetGeometry( geometry );
  rbi->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 3: Shepp-Logan, outer ray source ******" << std::endl;

  // Create Shepp Logan reference projections
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp = SLPType::New();
  slp->InPlaceOff();
  slp->SetInput( projInput->GetOutput() );
  slp->SetGeometry(geometry);
  slp->Update();

  // Create a Shepp Logan reference volume (finer resolution)
  origin.Fill(-127);
  size.Fill(128);
  spacing.Fill(2.);
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 0. );

  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->InPlaceOff();
  dsl->SetInput( volInput->GetOutput() );
  dsl->Update();

  // Forward projection
  jfp->SetInput( 1, dsl->GetOutput() );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 4: Shepp-Logan, inner ray source ******" << std::endl;
  geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(120., 1000., i*8.);

  slp->SetGeometry(geometry);
  slp->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  return EXIT_SUCCESS;
}
<commit_msg>Raised tolerance<commit_after>
#include "rtkThreeDCircularProjectionGeometryXMLFile.h"
#include "rtkRayBoxIntersectionImageFilter.h"
#include "rtkJosephForwardProjectionImageFilter.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"

template<class TImage>
void CheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)
{
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType TestVal = itTest.Get();
    typename TImage::PixelType RefVal = itRef.Get();

    if( TestVal != RefVal )
      {
      TestError += vcl_abs(RefVal - TestVal);
      EnerError += vcl_pow(ErrorType(RefVal - TestVal), 2.);
      }
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/recon->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(255.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;
  // QI
  ErrorType QI = (255.0-ErrorPerPixel)/255.0;
  std::cout << "QI = " << QI << std::endl;

  // Checking results
  if (ErrorPerPixel > 1.28)
    {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of 1.28" << std::endl;
    exit( EXIT_FAILURE);
    }
  if (PSNR < 44.)
    {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of 44" << std::endl;
    exit( EXIT_FAILURE);
    }
}

int main(int , char** )
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
  typedef itk::Vector<double, 3>                   VectorType;
  const unsigned int NumberOfProjectionImages = 45;

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  // The test projects a volume filled with ones. The forward projector should
  // then return the intersection of the ray with the box and it is compared
  // with the analytical intersection of a box with a ray.

  // Create Joseph Forward Projector volume input.
  const ConstantImageSourceType::Pointer volInput = ConstantImageSourceType::New();
  origin[0] = -126;
  origin[1] = -126;
  origin[2] = -126;
  size[0] = 64;
  size[1] = 64;
  size[2] = 64;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 1. );
  volInput->UpdateOutputInformation();

  // Initialization Volume, it is used in the Joseph Forward Projector and in the
  // Ray Box Intersection Filter in order to initialize the stack of projections.
  const ConstantImageSourceType::Pointer projInput = ConstantImageSourceType::New();
  size[2] = NumberOfProjectionImages;
  projInput->SetOrigin( origin );
  projInput->SetSpacing( spacing );
  projInput->SetSize( size );
  projInput->SetConstant( 0. );
  projInput->Update();

  // Joseph Forward Projection filter
  typedef rtk::JosephForwardProjectionImageFilter<OutputImageType, OutputImageType> JFPType;
  JFPType::Pointer jfp = JFPType::New();
  jfp->InPlaceOff();
  jfp->SetInput( projInput->GetOutput() );
  jfp->SetInput( 1, volInput->GetOutput() );

  // Ray Box Intersection filter (reference)
  typedef rtk::RayBoxIntersectionImageFilter<OutputImageType, OutputImageType> RBIType;
  RBIType::Pointer rbi = RBIType::New();
  rbi->InPlaceOff();
  rbi->SetInput( projInput->GetOutput() );
  VectorType boxMin, boxMax;
  boxMin[0] = -128.0;
  boxMin[1] = -128.0;
  boxMin[2] = -128.0;
  boxMax[0] =  128.0;
  boxMax[1] =  128.0;
  boxMax[2] =   47.6;
  rbi->SetBoxMin(boxMin);
  rbi->SetBoxMax(boxMax);

  std::cout << "\n\n****** Case 1: inner ray source ******" << std::endl;
  // The circle is divided in 4 quarters
  for(int q=0; q<4; q++) {
    // Geometry
    typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
    GeometryType::Pointer geometry = GeometryType::New();
    for(unsigned int i=0; i<NumberOfProjectionImages;i++)
      {
      const double angle = -45. + i*2.;
      geometry->AddProjection(47.6 / vcl_cos(angle*itk::Math::pi/180.), 1000., q*90+angle);
      }

    if(q==0) {
      rbi->SetGeometry( geometry );
      rbi->Update();
    }

    jfp->SetGeometry(geometry);
    jfp->Update();

    CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
    std::cout << "\n\nTest of quarter #" << q << " PASSED! " << std::endl;
  }

  std::cout << "\n\n****** Case 2: outer ray source ******" << std::endl;
  boxMax[2] = 128.0;
  rbi->SetBoxMax(boxMax);

  // Geometry
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(500., 1000., i*8.);

  rbi->SetGeometry( geometry );
  rbi->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(rbi->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 3: Shepp-Logan, outer ray source ******" << std::endl;

  // Create Shepp Logan reference projections
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp = SLPType::New();
  slp->InPlaceOff();
  slp->SetInput( projInput->GetOutput() );
  slp->SetGeometry(geometry);
  slp->Update();

  // Create a Shepp Logan reference volume (finer resolution)
  origin.Fill(-127);
  size.Fill(128);
  spacing.Fill(2.);
  volInput->SetOrigin( origin );
  volInput->SetSpacing( spacing );
  volInput->SetSize( size );
  volInput->SetConstant( 0. );

  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->InPlaceOff();
  dsl->SetInput( volInput->GetOutput() );
  dsl->Update();

  // Forward projection
  jfp->SetInput( 1, dsl->GetOutput() );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  std::cout << "\n\n****** Case 4: Shepp-Logan, inner ray source ******" << std::endl;
  geometry = GeometryType::New();
  for(unsigned int i=0; i<NumberOfProjectionImages; i++)
    geometry->AddProjection(120., 1000., i*8.);

  slp->SetGeometry(geometry);
  slp->Update();

  jfp->SetGeometry( geometry );
  jfp->Update();

  CheckImageQuality<OutputImageType>(slp->GetOutput(), jfp->GetOutput());
  std::cout << "\n\nTest PASSED! " << std::endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: XMLTextListBlockContext.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _XMLTEXTLISTBLOCKCONTEXT_HXX
#define _XMLTEXTLISTBLOCKCONTEXT_HXX

#include <com/sun/star/container/XIndexReplace.hpp>
#include <xmloff/xmlictxt.hxx>

class XMLTextImportHelper;

class XMLTextListBlockContext : public SvXMLImportContext
{
    XMLTextImportHelper&    rTxtImport;

    ::com::sun::star::uno::Reference<
                ::com::sun::star::container::XIndexReplace > xNumRules;

    const ::rtl::OUString   sNumberingRules;
    ::rtl::OUString         sStyleName;
    SvXMLImportContextRef   xParentListBlock;
    sal_Int16               nLevel;
    sal_Int32               nLevels;
    sal_Bool                bRestartNumbering : 1;
    sal_Bool                bSetDefaults : 1;

public:

    TYPEINFO();

    XMLTextListBlockContext( SvXMLImport& rImport,
            XMLTextImportHelper& rTxtImp, sal_uInt16 nPrfx,
                const ::rtl::OUString& rLName,
                   const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );
    virtual ~XMLTextListBlockContext();

    virtual void EndElement();

    SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                const ::rtl::OUString& rLocalName,
                 const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    const ::rtl::OUString& GetStyleName() const { return sStyleName; }
    sal_Int16 GetLevel() const { return nLevel; }
    sal_Bool IsRestartNumbering() const { return bRestartNumbering; }
    void ResetRestartNumbering() { bRestartNumbering = sal_False; }

//  sal_Bool HasGeneratedStyle() const { return xGenNumRule.is(); }
    const ::com::sun::star::uno::Reference <
        ::com::sun::star::container::XIndexReplace >& GetNumRules() const
        { return xNumRules; }
};

#endif
<commit_msg>INTEGRATION: CWS swlists01 (1.6.138); FILE MERGED 2008/05/08 16:13:25 od 1.6.138.2: RESYNC: (1.6-1.7); FILE MERGED 2008/05/08 14:59:50 od 1.6.138.1: #i86732# changes/adjustments for new list handling<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: XMLTextListBlockContext.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _XMLTEXTLISTBLOCKCONTEXT_HXX
#define _XMLTEXTLISTBLOCKCONTEXT_HXX

#include <com/sun/star/container/XIndexReplace.hpp>
#include <xmloff/xmlictxt.hxx>

class XMLTextImportHelper;

class XMLTextListBlockContext : public SvXMLImportContext
{
    XMLTextImportHelper&    mrTxtImport;

    ::com::sun::star::uno::Reference<
                ::com::sun::star::container::XIndexReplace > mxNumRules;

    // text:style-name property of <list> element
    ::rtl::OUString         msListStyleName;

    SvXMLImportContextRef   mxParentListBlock;

    sal_Int16               mnLevel;
    sal_Bool                mbRestartNumbering : 1;
    sal_Bool                mbSetDefaults : 1;

    // --> OD 2008-04-22 #refactorlists#
    // text:id property of <list> element, only valid for root <list> element
    ::rtl::OUString msListId;
    // text:continue-list property of <list> element, only valid for root <list> element
    ::rtl::OUString msContinueListId;
    // <--

public:

    TYPEINFO();

    // --> OD 2008-05-07 #refactorlists#
    // add optional parameter <bRestartNumberingAtSubList>
    XMLTextListBlockContext(
                SvXMLImport& rImport,
                XMLTextImportHelper& rTxtImp,
                sal_uInt16 nPrfx,
                const ::rtl::OUString& rLName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                const sal_Bool bRestartNumberingAtSubList = sal_False );
    // <--
    virtual ~XMLTextListBlockContext();

    virtual void EndElement();

    SvXMLImportContext *CreateChildContext( sal_uInt16 nPrefix,
                const ::rtl::OUString& rLocalName,
                 const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList );

    const ::rtl::OUString& GetListStyleName() const { return msListStyleName; }
    sal_Int16 GetLevel() const { return mnLevel; }
    sal_Bool IsRestartNumbering() const { return mbRestartNumbering; }
    void ResetRestartNumbering() { mbRestartNumbering = sal_False; }

    const ::com::sun::star::uno::Reference <
        ::com::sun::star::container::XIndexReplace >& GetNumRules() const
        { return mxNumRules; }

    // --> OD 2008-04-22 #refactorlists#
    const ::rtl::OUString& GetListId() const;
    const ::rtl::OUString& GetContinueListId() const;
    // <--

};

#endif
<|endoftext|>