#include <stdio.h>

#include "piwindowx.h"

#include <X11/Xlib.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include <X11/Shell.h>
#include <Xm/Form.h>

/* Fonctions (Callback et action) pour traiter le message Close de WM  */

/* Nouvelle-Fonction */
static void popdwn_cb(Widget /*w*/, XtPointer *usd,  XtPointer * )
{
PIWindowX * dw = (PIWindowX *) usd;
dw->Process(dw->BuildMsg(dw->Msg(),PIMsg_Close), dw, NULL) ;
}


/* Nouvelle-Fonction */
static int fgactl = 0;

static void CloseWindow (Widget w, XEvent*, String*,Cardinal*)
{
XtCallCallbacks(w,  XtNpopdownCallback, NULL);
}



/* --Methode-- */
PIWindowX::PIWindowX(PIMsgHandler *par, char *nom, PIWindowKind k, 
                     int sx, int sy, int px, int py)
: PIWindowGen(par, nom, k, -1, -1, 0, 0)
{
XtTranslations trans;

pwm = new PIWdgX(NULL, nom, sx, sy, px, py);

switch (k)
  {
  case PIWK_normal :
  case PIWK_floating :
    pwm->CreateXtWdg(nom, topLevelShellWidgetClass, NULL, sx, sy, px, py);
    break;
  case PIWK_dialog :
    pwm->CreateXtWdg(nom, transientShellWidgetClass, NULL, sx, sy, px, py);
    break;
  case PIWK_transient :
    pwm->CreateXtWdg(nom, overrideShellWidgetClass, NULL, sx, sy, px, py);
    break;
  }


/*  Il faut "attraper" l'action close, genere par le window-manager       */
/*  2 actions sont necessaires, installation d'une action (CloseWindow()) */
/*  et j'utilise ensuite un callback ds CloseWindow()                     */
/*  Il faut aussi desactiver l'action de destruction du widget par defaut */
/*  (XtSetArg(warg, XmNdeleteResponse, ...                                */
/*  Attention, voir la fonction Show(), pour l'appel a XSetWMProptocols() */
/*  Pour une fenetre donnee, on peut recuperer les Map, UnMap, Destroy,   */
/*  etc... il faut appeler XtAddEventHandler( w, Mask, ...)               */
/*    Mask =  StructureNotifyMask | SubstructureNotifyMask                */



if ((k == PIWK_normal) || (k == PIWK_floating) || (k == PIWK_dialog))
  { 
  if (k == PIWK_dialog)  AutoHideOnClose(false);
  /* XtAddEventHandler(pwm->XtWdg(), StructureNotifyMask | SubstructureNotifyMask, 
                  FALSE, wmaction_evthandler, this);*/

  XtAddCallback(pwm->XtWdg(), XtNpopdownCallback,
                (XtCallbackProc)popdwn_cb, (XtPointer)this);

  if (fgactl == 0) 
    { 
    XtActionsRec desact = {(char *)"CloseWindow" ,CloseWindow};
    int szx, szy, szf;
    XtAppContext * appctx = PIXtAppCtx(szx, szy, szf);
    XtAppAddActions(*appctx, &desact, 1);  fgactl = 1; 
    }

  trans = XtParseTranslationTable("<Message>WM_PROTOCOLS:CloseWindow()");
  XtOverrideTranslations(pwm->XtWdg() , trans);
  Arg warg[2];
  XtSetArg(warg[0], XmNdeleteResponse, XmDO_NOTHING);
  XtSetValues(pwm->XtWdg(), warg, 1);
  }

CreateXtWdg(nom, xmFormWidgetClass, pwm->XtWdg(), sx, sy, 0, 0);
wmis = k_wmi_cascade;
}

/* --Methode-- */
PIWindowX::~PIWindowX()
{
Hide();
delete pwm;
}

/* --Methode-- */
void PIWindowX::SetBinding(PIBindingKind /*left*/, PIBindingKind /*top*/, 
                           PIBindingKind /*right*/, PIBindingKind /*bottom*/)
{
// On ne doit rien faire pour les fenetres 
return;
}

/* --Methode-- */
void PIWindowX::SetSize(int sx, int sy)
{
pwm->SetSize(sx, sy);
PIWdgX::SetSize(sx, sy);
return;
}

/* --Methode-- */
void PIWindowX::SetPos(int px, int py)
{
pwm->SetPos(px, py);
PIWdgX::SetPos(px, py);
return;
}


/* --Methode-- */
void PIWindowX::Show()
{
int fgr = 0;
Display *mdsp;

mdsp = XtDisplay(pwm->XtWdg());

PIContainerGen::Show();
// Manage();  $CHECK$ Ca ne doit plus etre necessaire Reza 9/7/97
if (!XtIsRealized(pwm->XtWdg()))  fgr = 1;
pwm->Manage();
if (fgr) 
  {
  Atom wmd;
  if ((mWtyp == PIWK_normal) || (mWtyp == PIWK_floating) || (mWtyp == PIWK_dialog))
    { 
    wmd = XInternAtom(mdsp, "WM_DELETE_WINDOW",False);
    XSetWMProtocols(mdsp, XtWindow(pwm->XtWdg()), &wmd, 1);
    }
  else 
    XSetTransientForHint(mdsp, XtWindow(PIXtTopWdg()), XtWindow(pwm->XtWdg()));
  //  Pour faire les actions sur les fenetres X, sinon fenetre pas cree 
  PIContainerGen::FinishCreate();
  }

// XRaiseWindow est necessaire, sinon la fenetre passe des fois derriere ...
if (mWtyp == PIWK_transient)  
  XRaiseWindow(mdsp, XtWindow(pwm->XtWdg()));
 
return;
}

/* --Methode-- */
void PIWindowX::Hide()
{
PIWindowGen::Hide();
// UnManage();  $CHECK$ Ca ne doit plus etre necessaire Reza 9/7/97
pwm->UnManage();
}


