// This may look like C code, but it is really -*- C++ -*-
// Module PI : Peida Interactive      PIBaseWdg
//                                    Reza 95-96
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#include <stdio.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/cursorfont.h>

#include <X11/IntrinsicP.h>
#include <X11/CoreP.h>

#include "sopnamsp.h"
#include "pixtbaseP.h"
#include "pixtbase.h"

#include "pibwdgx.h"


// #define DEBUG_PIBWDGX     Flag pour impression de debug etc ...
static unsigned long colpixwhite, colpixblack;
#define NMAXCURS 5 
static Cursor curs[NMAXCURS];


/* --Methode-- */
PIBaseWdgX::PIBaseWdgX(PIContainerGen *par, const char *nom,
                       int sx, int sy, int px, int py) 
  : PIBaseWdgGen(par, nom, sx, sy, px, py) , bwx_finishDone(false)

{
Arg  wargs[3];

Init();
mWGrC = NULL; // PIGraphic (Contexte graphique) associe a la fenetre

CreateXtWdg(nom, piXtBaseWidgetClass, NULL, sx, sy, px, py);

XtSetArg(wargs[0],PIXNobject,this); 
XtSetArg(wargs[1],XtNbackground, colpixwhite);  
XtSetArg(wargs[2],XtNborderWidth, (Dimension)0);  
XtSetValues(XtWdg(), wargs, 3);

((PIXtBaseWidget)XtWdg())->pixtbase.myeventmask = 0;
XtUninstallTranslations(XtWdg());

mPtrS = PI_CrossPointer;
SelPointerShape();
// ----------------------------------------------------------------------------
// Reza: Fev/Mai 2005 - On doit s'assurer que le bon FinishCreate() est appele
// (table de fonction virtuelle mise a jour par les constructeurs successifs 
// dans les classes heritieres
// et on gere le PIGraphic (Contexte graphique) associe a la fenetre
// Si pas cree par FinishCreate()
if (finishDone) FinishCreate();
else mWGrC = new PIGraphicX(this);   

SetBackgroundColor();
SetForegroundColor();
Manage();
}


/* --Methode-- */
PIBaseWdgX::~PIBaseWdgX()
{
#ifdef DEBUG_PIBWDGX 
printf("PIBaseWdgX::~PIBaseWdgX()_Debug: Object= %lx (%lx) Wdg= %lx \n",
(long)this, (long)(((PIXtBaseWidget)XtWdg())->pixtbase.objet), (long)XtWdg() );  
#endif
Arg  wargs[2];
XtSetArg(wargs[0],PIXNobject,NULL); 
XtSetValues(XtWdg(), wargs, 1);
}

/* --Methode-- */
void PIBaseWdgX::FinishCreate()
{
// appele par la fenetre mere, apres XtRealize()
// Doit pouvoir etre appele de multiple fois 
if (bwx_finishDone) return;
PIWdgX::FinishCreate();

// J'active le backing store pour la fenetre X
XSetWindowAttributes xswa;
if (!XtIsRealized(XtWdg())) XtRealizeWidget( XtWdg() ) ;

Window mwi = XtWindow(XtWdg());

/*
XWindowAttributes xwa;
XGetWindowAttributes(PIXDisplay(), mwi, &xwa);
printf("PIBaseWdgX::FinishCreate()  BS= %d  (No=%d Map=%d Always=%d) planes=%lx \n", 
       xwa.backing_store, NotUseful, WhenMapped, Always, (long)xwa.backing_planes);
*/
xswa.backing_store = WhenMapped;
// xswa.backing_planes = ~0;
// XChangeWindowAttributes(PIXDisplay(), XtWindow(XtWdg()), CWBackingPlanes|CWBackingStore, &xswa);
XChangeWindowAttributes(PIXDisplay(), mwi, CWBackingStore, &xswa);

// PIGraphic (Contexte graphique) associe a la fenetre
if (!mWGrC) mWGrC = new PIGraphicX(this);   
mWGrC->TerminateInit();
bwx_finishDone = true;
} 

/* --Methode-- */
bool PIBaseWdgX::IsVisible()
{
return (finishDone && PIWdg::IsVisible() ); 
}

/* --Methode-- */
void PIBaseWdgX::Refresh()
{
if (XtIsRealized(XtWdg())) {
// if ( IsVisible() )  {
//  EraseWindow();   --> Ne pas faire  Reza 12/98 
  Draw(mWGrC, 0, 0, XSize(), YSize());
  CallDrawers(mWGrC); 
  CallDrawHandlers(0, 0, XSize(), YSize());
  }
return;
}


/* --Methode-- */
void PIBaseWdgX::ActivatePtrCross()
{
XtAddEventHandler( XtWdg(), EnterWindowMask | LeaveWindowMask, 
                   FALSE, event_handler_pixtbase, NULL);
return;
}


/* --Methode-- */
void PIBaseWdgX::ActivateButton(int bid)
{
#ifdef DEBUG_PIBWDGX
printf("PIBaseWdgX::ActivateButton %d \n \n", bid);
#endif
if ( (bid < 1) && (bid > 3) ) return; 
XtAddEventHandler( XtWdg(), ButtonPressMask | ButtonReleaseMask, 
                   FALSE, event_handler_pixtbase, NULL);
if (bid == 1)  ((PIXtBaseWidget)XtWdg())->pixtbase.myeventmask |= Button1Mask ;
else if (bid == 2) ((PIXtBaseWidget)XtWdg())->pixtbase.myeventmask |= Button2Mask ;
else if (bid == 3) ((PIXtBaseWidget)XtWdg())->pixtbase.myeventmask |= Button3Mask ;
return;
}

/* --Methode-- */
void PIBaseWdgX::ActivateMove(int bid)
{
#ifdef DEBUG_PIBWDGX
printf("PIBaseWdgX::ActivateMove %d \n \n", bid);
#endif
unsigned long evtmask = 0;

// bid == 0  -> PointerMove sans bouton 
if ( (bid < 0) && (bid > 3) ) return; 

if (bid == 0) evtmask = PointerMotionHintMask ;
else if (bid == 1) evtmask = Button1MotionMask | PointerMotionHintMask ;
else if (bid == 2) evtmask = Button2MotionMask | PointerMotionHintMask ;
else if (bid == 3) evtmask = Button3MotionMask | PointerMotionHintMask ;
XtAddEventHandler( XtWdg(), evtmask, FALSE, event_handler_pixtbase, NULL);
return;
}


/* --Methode-- */
void PIBaseWdgX::ActivateKeyboard()
{
XtAddEventHandler( XtWdg(), KeyPressMask, FALSE, event_handler_pixtbase, NULL);
((PIXtBaseWidget)XtWdg())->pixtbase.myeventmask |= ShiftMask ;
return;
}


/* --Methode-- */
void PIBaseWdgX::SelPointerShape(PIPointer ptr)  
{
if (ptr == mPtrS)  return;
if ( (ptr < 0) || (ptr >= NMAXCURS))  return;
if ( XtIsRealized(XtWdg()) )
  XDefineCursor(XtDisplay (XtWdg()), XtWindow(XtWdg()), curs[ptr]);
mPtrS = ptr;
return;
}

/* --Methode-- */
void PIBaseWdgX::AssignKeyboard()
{
XSetInputFocus(XtDisplay (XtWdg()), XtWindow(XtWdg()), RevertToParent, PIXGetLastEventTime());
}


/* --Methode-- */
PIPointer  PIBaseWdgX::GetPointerShape()
{
return (mPtrS);
}

/* --Methode-- */
void PIBaseWdgX::GetLastEventInfo(PIKeyModifier& kmod, unsigned long& tm)
{
unsigned int st;
Time t;
PIXGetLastEventInfo(st, t);
tm = t;
kmod = PIKM_Blank;
if  (st & ShiftMask)   kmod = (PIKeyModifier) (kmod | PIKM_Shift);
if  (st & ControlMask) kmod = (PIKeyModifier) (kmod | PIKM_Cntl);
if  (st & Mod1Mask)    kmod = (PIKeyModifier) (kmod | PIKM_Alt);
return;
}

static bool fgbwdg = false ;

/* --Methode-- */
void PIBaseWdgX::Init()
{
int i;

if (fgbwdg)  return;
fgbwdg = true;

Display *mdsp = PIXDisplay();
int scr = XDefaultScreen(mdsp);

colpixwhite = XWhitePixel(mdsp, scr);
colpixblack = XBlackPixel(mdsp, scr);

curs[0] = XCreateFontCursor(mdsp, XC_X_cursor);
for(i=1; i<NMAXCURS; i++)  curs[i] = curs[0];

curs[PI_ArrowPointer] =  XCreateFontCursor(mdsp, XC_arrow);
curs[PI_CrossPointer] =  XCreateFontCursor(mdsp, XC_crosshair);
curs[PI_HandPointer] =  XCreateFontCursor(mdsp, XC_hand2);
curs[PI_TDLRArrowPointer] =  XCreateFontCursor(mdsp, XC_fleur);

return;
}

/* --Methode-- */
void PIBaseWdgX::eXposeProcess(int x0, int y0, int dx, int dy)                                 
{ 
// Appel depuis le PIXtBaseWidget uniquement (ExposeEvt de Xt )
Draw(mWGrC, x0, y0, dx, dy);
CallDrawers(mWGrC, x0, y0, dx, dy); 
return;
}
