#include <stdio.h>

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

#include "sopnamsp.h"
#include "pipixmapx.h"
#include <iostream>

using namespace std;

static  GC    mygc;

/* --Methode-- */
PIPixmapX::PIPixmapX(PIContainerGen *par, const char *nom,
                         int sx, int sy, int px, int py)
: PIPixmapGen(par,nom,sx,sy,px,py) 
{
Init();
AllocXImg();
}


/* --Methode-- */
PIPixmapX::~PIPixmapX()
{
delete[] myximg->data;
XFree(myximg); 
}

/* --Methode-- */
void PIPixmapX::Refresh()
{
int i,j;
int nx = 0;
int ny = 0;
if (pixmap!=NULL) {
  nx = pixmap->XSize();
  if (nx > XSize())  nx = XSize();
  ny = pixmap->YSize();
  if (ny > YSize())  ny = YSize();
  if (pixmap->BytePointer()!=NULL) {
    unsigned char *pp = pixmap->BytePointer();
    for(j=0; j<ny; j++) {
      pp = pixmap->BytePointer()+j*pixmap->XSize();
      for(i=0; i<nx; i++)
        { XPutPixel(myximg, i, j, cmap->Color(*pp) );  pp++; }
      }
  }
  else if (pixmap->ShortPointer()!=NULL) {
    unsigned short *pp = pixmap->ShortPointer();
    for(j=0; j<ny; j++) {
      pp = pixmap->ShortPointer()+j*pixmap->XSize();
      for(i=0; i<nx; i++)  
        { XPutPixel(myximg, i, j, cmap->Color(*pp) );  pp++; }
    }
  }
}
/* ----- On peut laisser le reste - ce n'est pas utilise dans le Draw
// On remplit le restant 
for(j=0; j<YSize(); j++)
  for(i=nx; i<XSize(); i++)
       XPutPixel(myximg, i, j, 0 );
for(j=ny; j<YSize(); j++)
  for(i=0; i<XSize(); i++)
     XPutPixel(myximg, i, j, 0 );
------- */
PIBaseWdgX::Refresh();
}


/* --Methode-- */
void PIPixmapX::Resize()
{
delete[] myximg->data;
XFree(myximg); 
AllocXImg();
if (Msg())  Send(Msg(), PIMsg_Resize, mPpos);
}

/*DEL07 --Methode-- 
void PIPixmapX::Draw(PIGraphicGen* g)
{
if (!pixmap)  return;
if (!g) return; 
if (g->kind() == PI_PSFileGraphics ) {
    g->DrawPixmap(ofx, ofy, pixmap, cmap);
    //  Il faut faire quelque chose Sinon ??! 
  }
else  Draw(g, 0, 0, XSize(), YSize());
}
*/

/* --Methode-- */
void PIPixmapX::Draw(PIGraphic* g, int x0, int y0, int dx, int dy)
{

if (!g) return; 

if (g->kind() == PI_PSFileGraphics ) {
  g->DrawPixmap(ofx, ofy, (*pixmap), cmap);
  return;
  }
  

Window xw = XtWindow(XtWdg());
Display * mdsp = PIXDisplay();

if ((myximg == NULL) || (cmap == NULL) || (pixmap == NULL) ||
    (pixmap->XSize()<=0) || (pixmap->YSize()<=0) ) {
  XClearArea(mdsp, xw, x0, y0, dx, dy, False);  return; 
}

int mx, my, ox, oy;

if (x0 < 0)  x0 = 0;
if (y0 < 0)  y0 = 0;

mx = pixmap->XSize()+ofx;   my = pixmap->YSize()+ofy;

if (dx > (XSize()-x0)) dx = XSize()-x0;
if (dy > (YSize()-y0)) dy = YSize()-y0;
if ((dx <= 0) || (dy <= 0))  return;

if ( (mx < x0 ) || (my < y0) )
  { XClearArea(mdsp, xw, x0, y0, dx, dy, False);  return; }

ox = oy = 0;  
if (ofx > x0)
  { XClearArea(mdsp, xw, x0, y0, ofx-x0, dy, False);   
  dx -= (ofx-x0);  x0 = ofx;  ox = 0; }
else  ox = x0-ofx;
if (ofy > y0)
  { XClearArea(mdsp, xw, x0, y0, dx, ofy-y0, False);  
  dy -= (ofy-y0);  y0 = ofy;  oy = 0; }
else  oy = y0-ofy;
 
if (mx < (x0+dx))
  { XClearArea(mdsp, xw, mx, y0, x0+dx-mx, dy, False);  dx = mx-x0; }
if (my < (y0+dy))
  { XClearArea(mdsp, xw, x0, my, dx, y0+dy-my, False);  dy = my-y0; }

/*
if (ofx > x0)
  XClearArea(mdsp, xw, x0, y0, ofx-x0, dy, False);   
if (ofy > y0)
  XClearArea(mdsp, xw, x0, y0, dx, ofy-y0, False);  
 
if (mx < (x0+dx))
  XClearArea(mdsp, xw, mx, y0, x0+dx-mx, dy, False); 
if (my < (y0+dy))
  XClearArea(mdsp, xw, x0, my, dx, y0+dy-my, False);  

if (ofx > x0)
  { dx -= (ofx-x0);  x0 = ofx;  ox = 0; }
else  ox = x0-ofx;
if (ofy > y0)
  { dy -= (ofy-y0);  y0 = ofy;  oy = 0; }
else  oy = y0-ofy;
if (mx < (x0+dx))  dx = mx-x0;
if (my < (y0+dy))  dy = my-y0;
*/
  
XPutImage(mdsp, xw, mygc, myximg, ox, oy, x0, y0, dx, dy);
XFlush(mdsp);
return;
 
}

static bool fgxpxm = false;


/* --Methode-- */
void PIPixmapX::Init()
{
XGCValues       values;
XtGCMask        mask;

if (fgxpxm)  return; 
fgxpxm = true;


mask = GCFunction | GCPlaneMask;
// mask = GCForeground | GCBackground;
values.function = GXcopy;
values.plane_mask = ~0;
// values.foreground = WhitePixel(mdsp, scr);
// values.background = BlackPixel(mdsp, scr);
mygc = XtGetGC(XtWdg(), mask, &values);

return;
}


/* --Methode-- */
void PIPixmapX::AllocXImg()
{
Display * mdsp;
int scr;
int depth;
int pad;
int i,j;

mdsp = PIXDisplay();
scr = PIXScreen();

depth = DefaultDepth(mdsp,scr);
pad = (depth > 8) ? 32 : 8;
myximg = XCreateImage (mdsp,DefaultVisual(mdsp,scr),
           depth,ZPixmap,0,NULL, XSize(), YSize(), pad,0);
if (myximg == NULL)  return;
myximg->data = new char [YSize()*myximg->bytes_per_line];
if (myximg->data == NULL)  
  { XFree(myximg); myximg = NULL;  return; } 

for(j=0; j<YSize(); j++)
  for(i=0; i<XSize(); i++)
    XPutPixel(myximg, i, j, 0 );

return;
}
