#include <stdio.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

#include "sopnamsp.h"
#include "piwdgx.h"
#include "picmapx.h"

/* --Methode-- */
PIColorMapX::PIColorMapX()    
: PIColorMapGen()
{
mColors = NULL;
mColRGB = NULL;
mNewCol = NULL;
}

/* --Methode-- */
PIColorMapX::PIColorMapX(int id, int nc, string const& nom)    
: PIColorMapGen(id, nc, nom)
{

int n = nc;
mColors = new PIXColor[n];
mColRGB = new PIColor[n];
mNewCol = new bool[n];
int i;
for(i=0; i<n; i++)  
  { mColors[i] = BlackPixel(PIXDisplay(), PIXScreen());
  mColRGB[i].red = mColRGB[i].green = mColRGB[i].blue = 0; 
  mNewCol[i] = false; }
// printf("PIColorMapX::PIColorMapX(CMapId, int) %d %d \n", mNCol, Type());
}


/* --Methode-- */
PIColorMapX::~PIColorMapX()
{
if (mColors)  delete[] mColors;
if (mColRGB)  delete[] mColRGB;
if (mNewCol)  delete[] mNewCol;
}


/* --Methode-- */
PIColor PIColorMapX::GetColor(int n)
{
if ((n<0) || (n >= NCol()))   
  {
  PIColor picr;
  picr.red = picr.green = picr.blue = 0;
  return(picr);
  }
if (mFlagReversedIndex) return(mColRGB[NCol()-n-1]);
else return(mColRGB[n]);
}

static  Colormap  defxcmap;
static  int xinicmap = 0;
static int NTotColors = 0;
static int NTotAllocCol = 0;

static int nerrallocol = 0;

/* --Methode-- */
bool PIColorMapX::AllocColor(PIColor const& col, int index)
{
XColor myxcol;

if (!xinicmap)  
  {
  defxcmap = XDefaultColormap (PIXDisplay(), PIXScreen());
  xinicmap = 1;
  }

if ( (index < 0) || (index >= mNCol) )  return(false);

if ( (col.red == 0) && (col.green == 0) && (col.blue == 0) )
  {
  mColors[index] = BlackPixel(PIXDisplay(), PIXScreen());
  mColRGB[index] = col; 
  mNewCol[index] = false;
  return(true);
  }

// Pour diminuer les requetes X, on verifie si la couleur 
// ne se trouve pas deja dans la table    Reza 19/05/98
int kc;
for(kc=0; kc<mNCol; kc++) 
  if ( (col.red == mColRGB[kc].red) && (col.green == mColRGB[kc].green) &&   (col.blue == mColRGB[kc].blue) )
    { mColors[index] = mColors[kc];  mColRGB[index] = mColRGB[kc]; 
    mNewCol[index] = false;  return(true); }

 
myxcol.red = col.red; 
myxcol.blue = col.blue;
myxcol.green = col.green;


if ( XAllocColor(PIXDisplay(), defxcmap, &myxcol) ) {
  mColors[index] = myxcol.pixel;
  mColRGB[index] = col; 
  mNewCol[index] = true;
//  printf("PIColorMapX::AllocColor()  RGB= %d %d %d \n",
//         (int) col.red, (int) col.blue, (int) col.green);
  NTotAllocCol++;  
  return(true);
  }
else {
  nerrallocol++;
  if (nerrallocol < 21) printf("PIColorMapX::AllocColor() Error: Pb Allocation RGB= %d %d %d \n",
         (int) col.red, (int) col.blue, (int) col.green);
  if (nerrallocol == 20) printf("No more  PIColorMapX::AllocColor() Errors will be reported \n");
  return(false);
  }
}

/* --Methode-- 
void PIColorMapX::MakeColMap()
{
}
*/

/* --Methode-- */
void PIColorMapX::FreeColors()
{
PIXColor bpix;
PIColor blc;

if (!xinicmap)  
  {
  defxcmap = XDefaultColormap (PIXDisplay(), PIXScreen());
  xinicmap = 1;
  }

for (int i=0; i<mNCol; i++)
  if ( mNewCol[i] )    XFreeColors(PIXDisplay(), defxcmap, mColors+i, 1, 0);

bpix = BlackPixel(PIXDisplay(), PIXScreen());
blc.red = blc.green = blc.blue = 0;
{for (int i=0; i<mNCol; i++)  
  { mColors[i] = bpix;   mColRGB[i] = blc;  mNewCol[i] = false; }
}
// printf("PIColorMapX::FreeColors()  Type= %d mNCol= %d \n",
//        Type(), NCol());

}


/* --Methode-- */
long PIColorMapX::TotNbColors()
{
if (NTotColors > 0)  return(NTotColors);
// Visual* vis;
// DefaultVisual(PIXDisplay(),  PIXScreen() );
int k,kk;
// On calcule le nombre de couleurs a partir du nb de plans image
kk = DefaultDepth(PIXDisplay(),  PIXScreen() );
NTotColors = 1;
for(k=0; k<kk; k++) NTotColors *= 2;
/*
 printf("PIColorMapX::TotNbColor() / Debug : Nb Tot Colors = %d - D=%d - NCol=%d NP= %d \n", NTotColors, 
 DefaultDepth(PIXDisplay(),  PIXScreen()), 
 DisplayCells(PIXDisplay(),  PIXScreen()), 
 DisplayPlanes(PIXDisplay(),  PIXScreen()) );
*/
return(NTotColors);
}

/* --Methode-- */
int PIColorMapX::NbAllocColors()
{
return(NTotAllocCol);
}


/* --Methode-- */
void PIColorMapX::CopyFrom(PIColorMapGen* x)
{
  if (mColors)  delete mColors;
  if (mColRGB)  delete mColRGB;
  if (mNewCol)  delete mNewCol;
  CopyFromGen(x);
  mColors = new PIXColor[mNCol];
  mColRGB = new PIColor[mNCol];
  mNewCol = new bool[mNCol];
  /*   Remplace par memcpy pour performances, Reza, Nov 2008
  for (int i=0; i<mNCol; i++)  
    { mColors[i] = ((PIColorMapX *)x)->mColors[i];
    mColRGB[i] = ((PIColorMapX *)x)->mColRGB[i]; 
// C'est la table de couleur originale qui est responsable de liberer les couleurs - Reza 8/2/98
    mNewCol[i] = false; }  
  -> memcpy (Nov08) */
  memcpy(mColors, ((PIColorMapX *)x)->mColors, sizeof(PIXColor)*mNCol);
  memcpy(mColRGB, ((PIColorMapX *)x)->mColRGB, sizeof(PIColor)*mNCol);
// C'est la table de couleur originale qui est responsable de liberer les couleurs - Reza 8/2/98
  for (int i=0; i<mNCol; i++)   mNewCol[i] = false;
}
