#include "machdefs.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <typeinfo>

#include <string>
#include <vector>

#include "strutil.h"
#include "timing.h"
#include "perrors.h"
#include "ctimer.h"

#include "psighand.h"

#include "cimage.h" // pour pouvoir faire extract 

#include "pistdimgapp.h"
#include "servnobjm.h"
// #include "pihisto2d.h"
#include "psfile.h"
#include "piimgtools.h"
#include "pidrwtools.h"
#include "piaxestools.h"

#include "pistzwin.h"

#include "piinit.h"
#include "piversion.h"
#include "piaversion.h"


static char ImgDir[256];
static char WorkDir[256];
// Initialiseur
static PIAppInitiator * glst_piai = NULL; 

// Pour la creation de fenetre info (about piapp)
static void createInfoWindow(PIStdImgApp* app);
static void deleteInfoWindow();
static void showInfoWindow(PIStdImgApp* app);
static void hideInfoWindow(PIStdImgApp* app);

// Pour compter le nombre de display same a la suite
static int nb_disp_same = 0;

/* ........................................................... */
/*    Classe SIA_RU__Periodic : mise a jour periodique de      */
/*    la fenetre Stat/Ressource info                           */
/*    + execution de commande soumis de l'exterieur            */
/* ........................................................... */

class SIA_RU__Periodic : public PIPeriodic 
{
public:
  SIA_RU__Periodic(PIStdImgApp* app);
  virtual ~SIA_RU__Periodic();
  virtual void DoPeriodic();
private:
  PIStdImgApp* _app;
};

SIA_RU__Periodic::SIA_RU__Periodic(PIStdImgApp* app)
  : PIPeriodX(1)
{
  _app = app;
}

SIA_RU__Periodic::~SIA_RU__Periodic()
{
}

void SIA_RU__Periodic::DoPeriodic()
{
  if (_app) { 
    _app->ExecuteExtCommand();
    _app->UpdateStatResourceInfo();
  }
}

/* ............................................................. */


/* ........................................................... */
/*                    Classe PIStdImgApp                         */
/* ........................................................... */

/* --Methode-- */
PIStdImgApp::PIStdImgApp(int narg, char* arg[])
: PIApplication(420, 320, narg, arg)
{

// Les menus
m[0] = new PIMenu(Menubar(),"Fichier");
m[0]->AppendItem("About piapp", 10150);
m[0]->AppendItem("Open-Fits", 10120);
m[0]->AppendItem("Open-PPF", 10130);
#ifndef SANS_EVOLPLANCK
m[0]->AppendItem("Open-ASCII", 10140);
#endif
// m[0]->AppendItem("Options", 10101);
m[0]->AppendItem("Help", 10100);
m[0]->AppendSeparator();
m[0]->AppendItem("Exit", 10105);

m[1] = new PIMenu(Menubar(),"Objets");
m[1]->AppendItem("ObjectManager", 10201);
m[1]->AppendItem("OpenOutPPF", 10220);
m[1]->AppendItem("CloseOutPPF", 10230);
m[1]->AppendItem("Delete CurWdg", 10270);

m[2] = new PIMenu(Menubar(),"Tools");
m[2]->AppendItem("Show ImageTools", 10301);
m[2]->AppendItem("Show DrawerTools", 10302);
m[2]->AppendItem("Show AxesTools", 10303);
m[2]->AppendItem("CxxExecutorWindow", 10304);
m[2]->AppendItem("Ext.Pave", 10311);
m[2]->SetSensitivityMsg(10311, false);
m[2]->AppendItem("Ext.Pave+Org", 10312);
m[2]->SetSensitivityMsg(10312, false);
m[2]->AppendItem("Cuts X,Y", 10313);
m[2]->SetSensitivityMsg(10313, false);
mc = new PIMenu(m[2], "StackTools");
mc->AppendItem("DispNext", 10320);
mc->AppendItem("Blink 0.5s", 10321);
mc->AppendItem("Blink 1s", 10322);
mc->AppendItem("Blink 2s", 10324);
mc->AppendItem("Stop Blink", 10329);
mc->AppendItem("RemoveCurrent", 10330);
m[2]->AppendPDMenu(mc);
m[2]->SetSensitivity("StackTools", false);

m[3] = new PIMenu(Menubar(),"Window");
m[3]->AppendItem("StackWindow", 10400);
m[3]->AppendItem("Window", 10411);
m[3]->AppendItem("Window 2x1", 10421);
// m[3]->AppendItem("Window 1x2", 10412);
m[3]->AppendItem("Window 2x2", 10422);
// m[3]->AppendItem("Window 3x1", 10431);
m[3]->AppendItem("Window 3x3", 10433);
m[3]->AppendItem("Cur->LastWdg", 10441);
m[3]->AppendItem("Close CurWin", 10460);
m[3]->AppendCheckItem("StatZoomWin", 10470);
m[3]->SetStateMsg(10470, true);

m[4] = new PIMenu(Menubar(),"PostScript");
m[4]->AppendItem("OpenPS", 10501);
m[4]->AppendItem("ClosePS", 10505);
m[4]->AppendItem("Window->PS", 10511);
m[4]->AppendItem("Image->PS", 10515);
m[4]->AppendItem("Window->EPS", 10512);
m[4]->AppendItem("Image->EPS", 10516);
m[4]->SetSensitivityMsg(10515, false);
m[4]->SetSensitivityMsg(10516, false);

m[5] = new PIMenu(Menubar(),"Special");
m[5]->AppendItem("CloseAll", 10601);
m[5]->AppendCheckItem("Red.Out/Err", 10602);
m[5]->AppendCheckItem("Catch SigFPE", 10603);
m[5]->AppendCheckItem("Catch SigSEGV", 10604);
m[5]->AppendCheckItem("ObjMgr Verb", 10605);
m[5]->AppendItem("CxxExecOption", 10606);

m[6] = new PIMenu(Menubar(),"Modules");

AppendMenu(m[0]);
AppendMenu(m[1]);
AppendMenu(m[2]);
AppendMenu(m[3]);
AppendMenu(m[4]);
AppendMenu(m[5]);
// AppendMenu(m[6]);  Menu Modules vide pour le moment 

int scsx, scsy;
ScreenSize(scsx, scsy);
if (scsy <= 600)  mFgScSz = 0;
else if (scsy <= 800)  mFgScSz = 1;
else if (scsy <= 1024)  mFgScSz = 2;
else   mFgScSz = 3;
int msx = 420+mFgScSz*60;
int msy = 320+mFgScSz*40;
MainWin()->SetSize(msx, msy);

//------------------------------------------------------
// On cree un container intermediaire permettant de gerer 
// le widget zoom, colormap, stats, ...

int bss = 100+mFgScSz*15;

int statc_szy = bss+10+14+mFgScSz*2+5; 
statcont = new PIContainer(MainWin(), "ZGCSCont", msx, statc_szy, 0, 0);
statcont->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_free);

gimv = new PIPixmap(statcont, "GloV", bss, bss, 5, 5);
gimv->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_free, PIBK_free); 
zoom = new PIPixmap(statcont, "Zoom", bss, bss, bss+10, 5);
zoom->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_free, PIBK_free); 
cmapv = new PICMapView(statcont, "CMapView", msx-10, 14+mFgScSz*2, 5, bss+10); 
cmapv->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_free); 

// Widget pour affichage des stats / ressources 
lab_mem = new PILabel(statcont, "memlab", msx-2*(bss+20), 20, 2*bss+20, 10);
lab_mem->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_free); 
lab_mem->SetLabel("MemoryUsage");
lab_mem->SetForegroundColor(PI_Red);
lab_mem->SetBorderWidth(1);
therm_mem = new PIThermometer(statcont, "memtherm", msx-2*(bss+20), 20, 2*bss+20, 35);
therm_mem->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_free); 
therm_mem->SetThreshold(0.5, 0.75);

lab_cpu = new PILabel(statcont, "cpulab", msx-2*(bss+20), 20, 2*bss+20, 60);
lab_cpu->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_free); 
lab_cpu->SetLabel("CPUUsage");
lab_cpu->SetForegroundColor(PI_Black);
lab_cpu->SetBorderWidth(1);
therm_cpu = new PIThermometer(statcont, "cputherm", msx-2*(bss+20), 20, 2*bss+20, 85);
therm_cpu->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_free); 
therm_cpu->SetThreshold(0.75, 0.90);

 fg_exc_cmd = false;
UpdateStatResourceInfo();
resupd_periodic = new SIA_RU__Periodic(this);
//resupd_periodic->SetIntervalms(500);
resupd_periodic->Start();

statcont->Show();
// StatZoomWindowSetVisible(true);
//------------------------------------------------------

//int cpy = bss+10+14+mFgScSz*2+5;
int cpy = statc_szy;

// Creation d'une console avec gestion des commandes  
consolecont = new PIContainer(MainWin(), "ConsoleCont", msx, msy-cpy, 0, cpy );
consolecont->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_fixed); 
mCons = new PIConsole(consolecont, "Console", 30200, 512, 132, msx, msy-cpy, 0, 0 );
mCons->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_fixed); 
mCons->AcceptCmd(true, 50);
consolecont->Show();
redirecout = false;
// RedirectStdOutErr(true);  pas par defaut 
 
mObjMgr = new NamedObjMgr;
mCmd = new PIACmd(mObjMgr, this);

// Pas trop de message de la part de NamedObjMgr
m[5]->SetStateMsg(10605, false);
mObjMgr->SetVerbose(false);

char* varenv;
ImgDir[0] = WorkDir[0] = '\0';
if ( (varenv=getenv("PEIDA_IMAGES")) != NULL )   strncpy(ImgDir, varenv, 256);
if ( (varenv=getenv("PEIDA_WORK")) != NULL )  strncpy(WorkDir, varenv, 256);

pfc_fits = new PIFileChooser(this,"FITS-FileChooser", 10125); 
pfc_ppf = new PIFileChooser(this,"PPF-FileChooser", 10135); 
pfc_ascii = new PIFileChooser(this,"ASCII-FileChooser", 10145); 
pfc_ps = new PIFileChooser(this,"PS-FileChooser", 10525); 

mObjmgrw = new ObjMgrWind(this);
mPpinmgrw = new PPInMgrWind(this);

// Attention : A faire apres creation de ObjMgrWind !!! 
mObjMgr->SetImgApp(this);

// Gestion des feneteres widgets et drawers
mWId = mDId = mBWId = 0;
mCurWin = NULL;  
mCurWdg = NULL;
mLastWdg = NULL;
mGrW = NULL;
mStW = NULL;
mGrIdx = mStIdx = -1;

mFCMsg = 0;
mFgCWImg = false;

// Gestion fichiers PS
num_eps = 0;
name_ps = "";
name_ps = "pia.ps";
mpsfile = new PSFile(name_ps.c_str(),PI_Portrait, PI_A4, 2., 2.);

// Gestion OUT-PPF
mPpfout = NULL;
name_outppf = "";

// Attributs graphiques courants
mAxesFlags = kAxesDflt;
SetInsetLimits(0.4, 0.6, 0.4, 0.6);
mAddTitle = true;

// Initialisation 
glst_piai = new PIAppInitiator(this);

char buff[128];
mCons->AddStr("  ............  starting piapp .............\n", PIVA_Blue );
#ifdef SANS_EVOLPLANCK
sprintf(buff, "Version: piapp=%g  PI=%g  PEIDA=%g \n", (double)PIAPP_VERSIONNUMBER, 
              (double)PI_VERSIONNUMBER, (float)PeidaVersion());
#else
sprintf(buff, "Version: piapp=%g  PI=%g  SOPHYA=%g \n", (double)PIAPP_VERSIONNUMBER, 
              (double)PI_VERSIONNUMBER, glst_piai->Version());
#endif
mCons->AddStr(buff, PIVA_Blue );
mCons->AddStr("  ..........................................\n", PIVA_Blue );
// PrintPeidaVersion();

pfc_fits->SetPath(ImgDir);
pfc_ppf->SetPath(WorkDir);
pfc_ps->SetPath(WorkDir);

SetReady();
}

/* --Methode-- */
PIStdImgApp::~PIStdImgApp()
{
int i;

// On inactive la fenetre principale
//  Sinon, ca peut provoquer un SEGV ds delete de console ?? - Reza 07/2000
MainWin()->Hide();  

// Destrucion de tous les objets de NameObjMgr
string patt = "/*/*";
mObjMgr->DelObjects(patt, true);

delete mc;
for(i=0; i<7; i++)  
  if (m[i]) delete m[i];

WindMList::iterator it;
for(it = mWList.begin(); it != mWList.end(); it++)  delete (*it).second;

delete mObjMgr;
delete mCmd;

delete zoom;
delete gimv;
delete cmapv;

delete lab_mem;
delete therm_mem;
delete lab_cpu;
delete therm_cpu;

delete statcont;

delete pfc_fits;
delete pfc_ppf;
delete pfc_ascii;
delete pfc_ps;

delete mCons;
delete consolecont;

delete mObjmgrw;
delete mPpinmgrw;

deleteInfoWindow();

// Les fichiers 
if (mpsfile) delete mpsfile;
if (mPpfout) delete mPpfout;

if (resupd_periodic) delete resupd_periodic;

if (glst_piai) delete glst_piai;   glst_piai = NULL;

}  

/* --Methode-- */
void PIStdImgApp::Process(PIMessage msg, PIMsgHandler* sender, void* data)
{
PIWdg *sndw;
PIMessage tmsg, smm;

tmsg = msg;
msg = UserMsg(msg);
smm = ModMsg(tmsg);

//printf("SuperDebug: msg=%d Mod=%d  State=%d\n", (int)msg, (int)smm, (int)GetState());
if  ((GetState()) && (msg != mFCMsg)) { PIBeep(); return; }

//   Messages active-window
if (smm == PIMsg_Active)
  {
  sndw = dynamic_cast<PIWdg *>(sender);
  switch(sndw->kind())
    {
    case PIWindow::ClassId :
      mCurWin = dynamic_cast<PIWindow *>(sndw);
      break;

    case PIScDrawWdg::ClassId :
    case PIDraw3DWdg::ClassId :
      mCurWdg = dynamic_cast<PIBaseWdg *>(sender);
//      cerr << "*DBG11* ImgTools -> NonSensitive " << sndw->kind() << endl;
      if (mFgCWImg) {
//        cerr << "*DBG* ImgTools -> NonSensitive " << endl;
        m[2]->SetSensitivityMsg(10311, false);
        m[2]->SetSensitivityMsg(10312, false);
        m[2]->SetSensitivityMsg(10313, false);
        m[4]->SetSensitivityMsg(10515, false);
        m[4]->SetSensitivityMsg(10516, false);
        mFgCWImg = false;
        }
      break;
    case PIImage::ClassId :
      mCurWdg = dynamic_cast<PIBaseWdg *>(sender);
      if (!mFgCWImg) {
//        cerr << "*DBG* ImgTools -> Sensitive " << endl;
        m[2]->SetSensitivityMsg(10311, true);
        m[2]->SetSensitivityMsg(10312, true);
        m[2]->SetSensitivityMsg(10313, true);
        m[4]->SetSensitivityMsg(10515, true);
        m[4]->SetSensitivityMsg(10516, true);
        mFgCWImg = true;
        }
      break;
      /*
    default :
      mCurWdg = NULL;
      if (mFgCWImg) {
        m[2]->SetSensitivityMsg(10311, false);
        m[2]->SetSensitivityMsg(10312, false);
        m[2]->SetSensitivityMsg(10313, false);
        m[4]->SetSensitivityMsg(10515, false);
        m[4]->SetSensitivityMsg(10516, false);
        mFgCWImg = false;
        }
      break;
      */
    }
  }
//  Message window-close
else if (smm == PIMsg_Close)
  {
  sndw = (PIWdg *)sender;
  if(sndw->kind() == PIWindow::ClassId)
    {
    mCurWin = (PIWindow *)sender;
    if (mCurWin == mStW) m[2]->SetSensitivity("StackTools", false); 
    DeleteWindow(mCurWin);
    }
  else  
    printf("PIStdImgApp/Bug ? CloseMsd received from NonWindow (%d %d %lx) \n",
           (int)tmsg,  (int)sndw->kind(), (long)sender);       
  }

// Traitement des messages des menus 
else if ( (msg >= 10100) && (msg < 10200) )  MBProcess1(msg, sender, data);
else if ( (msg >= 10200) && (msg < 10300) )  MBProcess2(msg, sender, data);
else if ( (msg >= 10300) && (msg < 10400) )  MBProcess3(msg, sender, data);
else if ( (msg >= 10400) && (msg < 10500) )  MBProcess4(msg, sender, data);
else if ( (msg >= 10500) && (msg < 10600) )  MBProcess5(msg, sender, data);
else if ( (msg >= 10600) && (msg < 10700) )  MBProcess6(msg, sender, data);
else if ( msg == 30200  ) {    // Objet PIConsole 
  string s = mCons->GetCmdString();
  //  string s2 = "\nExecuting " + s + "\n";
  mCons->AddStr("Cmd> ", PIVA_Blue, false);
  //  s2 = s + "\n";
  mCons->AddStr(s.c_str(), PIVA_Blue|PIVA_Bold, false);
  mCons->AddChar('\n', PIVA_Def, true);
  SetBusy();
#ifdef SANS_EVOLPLANCK
  TRY {
    mCmd->Interpret(s);
    }  CATCH(merr) { 
    fflush(stdout); 
    cout << endl; 
    cerr << endl;
    string es = PeidaExc(merr);
    cerr << "PIStdImgApp::Process()/ Cmd->Do() Exception :" << es << " (" << merr << ")" << endl ;
    }
#else
  try {
    mCmd->Interpret(s);
    }  
  catch ( PThrowable & exc ) {
    cerr << "\n PIStdImgApp::Process()/ Cmd->Interpret() Exception :" 
	 << (string)typeid(exc).name() << " Msg= " 
	 << exc.Msg() << endl;
    cout << endl; 
  }
  catch ( ... ) {
    cerr << "\n PIStdImgApp::Process()/ Cmd->Interpret() Catched Exception ..." 
	 << endl;
    cout << endl; 
  }

#endif
  SetReady();
  }

else printf("PIStdImgApp::Process() BUG?? Msg %d (%d-%d) \n", 
            (int)tmsg,(int)msg,(int)smm);


return;
}

/* --Methode-- */
void PIStdImgApp::SetReady()
{
mCons->SetSensitive();
gimv->SetSensitive();
PIApplication::SetReady();
}

/* --Methode-- */
void PIStdImgApp::SetBusy()
{
mCons->SetUnSensitive();
gimv->SetUnSensitive();
PIApplication::SetBusy();
// Attention : Appel XSync specifique X11 -  en attendant multi-thread
XSync(PIXDisplay(), False);  
}

/* --Methode-- */
void PIStdImgApp::SetBlocked()
{
mCons->SetUnSensitive();
gimv->SetUnSensitive();
PIApplication::SetBlocked();
// Attention : Appel XSync specifique X11 -  en attendant multi-thread
XSync(PIXDisplay(), False);  
}


/* --Methode-- */
int PIStdImgApp::DispImage(P2DArrayAdapter* nouv, string const & name, string const& sop, int oid)
{
PIImage* pii;
PIWindow* win;
int sx, sy, px, py, flag;

if (nouv == NULL)
  {
  printf("PIStdImgApp::DispImage_Error  Cannot Display  NULL image \n");
  return(-1);
  }

if ( (nouv->XSize() <= 0)  || (nouv->YSize() <= 0))
  {
  printf("PIStdImgApp::DispImage_Error Pb Size Sz=%d*%d  \n", 
          nouv->XSize(), nouv->YSize());
  return(-1);
  }

// On decode les options graphiques
vector<string> opts;
DispWinEnum dwopt = ParseDisplayOption(sop, opts);

// Pas de same ou inset pour DispImage
if ((dwopt == Disp_Same) || (dwopt == Disp_Inset) ) dwopt = Disp_Next;

// Choix de la taille de fenetre
#define MINPIIMGSIZE 100
sx = (nouv->XSize() > MINPIIMGSIZE) ? nouv->XSize() : MINPIIMGSIZE;
sy = (nouv->YSize() > MINPIIMGSIZE) ? nouv->XSize() : MINPIIMGSIZE;
if (sx > 400+mFgScSz*100) sx = 400+mFgScSz*100;
if (sy > 400+mFgScSz*100) sy = 400+mFgScSz*100;
px = py = 0;
win = GetWindow(dwopt, sx, sy, px, py, flag, (char *)name.c_str());
pii = new PIImage(win, (char *)name.c_str(), sx, sy, px,py);
pii->SetBinding(PIBK_elastic, PIBK_elastic, PIBK_elastic, PIBK_elastic);
pii->SetZoomWin(zoom, false);
pii->SetGloVWin(gimv, false);
pii->SetCMapWin(cmapv, false);
pii->ShowCursor(true);
pii->SetUserData(NULL, oid);


// On recalcule la taille de la fenetre si Disp_Win
if (dwopt == Disp_Win) {
  int sx2 = (int)((float)nouv->XSize()*pii->GetZoomF());
  int sy2 = (int)((float)nouv->YSize()*pii->GetZoomF());
  
  if (sx2 > 400+mFgScSz*100) sx2 = 400+mFgScSz*100;
  if (sy2 > 400+mFgScSz*100) sy2 = 400+mFgScSz*100;
  if (sx2 < MINPIIMGSIZE) sx = MINPIIMGSIZE;
  if (sy2 < MINPIIMGSIZE) sy = MINPIIMGSIZE;
  if ((sx2 != sx) || (sy2 != sy))  win->SetSize(sx2, sy2);
}

pii->SetImage(nouv, true, false);

// decode des options en chaine de caracteres
if (mAxesAtt.size() > 0) 
  pii->DecodeOptionString(mAxesAtt, false);   // Les options d'axe
if (mDefaultAtt.size() > 0) 
  pii->DecodeOptionString(mDefaultAtt, false);  // d'abord les options par defaut
if (opts.size() > 0) 
  pii->DecodeOptionString(opts);    // ensuite, les options specifies en argument

// printf("!!DBG!! PIImage Pos= %d %d  Size= %d %d \n", pii->XPos(), pii->YPos(), pii->XSize(), pii->YSize()   );
mCurWin = win;
mCurWdg = pii;
mLastWdg = pii;
mBWId++;
mBWList[mBWId] = pii;
// pii->Refresh();
pii->Apply();
cmapv->Refresh();
return(mBWId); 
}


/* --Methode-- */
int PIStdImgApp::DispScDrawer(PIDrawer* scd, string const & name, string const& sop, 
			      string title, int oid)
{
if (scd == NULL)
  {
  printf("PIStdImgApp::DispScDrawer_Error  Cannot Add NULL ScDrawer \n");
  return(-1);
  }

// On decode les options graphiques
vector<string> opts;
DispWinEnum dwopt = ParseDisplayOption(sop, opts);
if ( (!mLastWdg) && ( (dwopt == Disp_Same) || (dwopt == Disp_Inset) ) )  dwopt = Disp_Next;
// Trace en superpoistion
if ( (dwopt == Disp_Same) && (mLastWdg) ) {  
  // Les options 
  scd->DecodeOptionString(mDefaultAtt, false);
  if (nb_disp_same > 0) {
    vector<string> ostatpos;
    int spo = nb_disp_same%4;
    if (spo == 1) ostatpos.push_back("statposoff=-0.01,-0.26");
    else if (spo == 2)  ostatpos.push_back("statposoff=-0.36,-0.01");
    else  ostatpos.push_back("statposoff=-0.36,-0.26");
    scd->DecodeOptionString(ostatpos, true);
  }
  scd->DecodeOptionString(opts, true);

  if (mLastWdg->kind() == PIScDrawWdg::ClassId)  ((PIScDrawWdg*)mLastWdg)->AddScDrawer(scd, true);
  else mLastWdg->AddDrawer(scd, true, true, true);
  scd->Refresh(); 
  mDId++;
  mDrwList[mDId] = scd;
  return(-mDId);   
}
// Trace en medaillon
else if ( (dwopt == Disp_Inset) && (mLastWdg) ) {
  PIGrCoord x1, x2, y1, y2;
  x1 = mIXmin;  x2 = mIXmax;
  y2 = 1.-mIYmin;  y1 = 1.-mIYmax;
  // Les options 
  scd->DecodeOptionString(mDefaultAtt, false);
  scd->DecodeOptionString(opts, true);

  scd->SetAxesFlags(mAxesFlags);
  scd->UpdateLimits();
  mLastWdg->AddDrawer(scd, x1, y1, x2, y2, true, false, true);
  scd->Refresh();
  mDId++;
  mDrwList[mDId] = scd;
  return(-mDId);   
}

// Creation d'un nouveau PIScDrawWdg
PIWindow* win;
PIScDrawWdg* scw;
int sx, sy, px, py, flag;
sx = 200+mFgScSz*100;
sy = 200+mFgScSz*100;
win = GetWindow(dwopt, sx, sy, px, py, flag, (char *)name.c_str());

scw = new PIScDrawWdg(win, (char *)name.c_str(), sx, sy, px, py);
scw->SetBinding(PIBK_elastic, PIBK_elastic, PIBK_elastic, PIBK_elastic);
scw->SetUserData(NULL, oid);

// Decodage des options :
vector<string> scwatt;
scw->SetAxesFlags(mAxesFlags);
if ( mDefaultAtt.size() > 0) { 
  scwatt = mDefaultAtt;
  scd->DecodeOptionString(scwatt, true);
  scw->DecodeOptionString(scwatt, true);
}
if ( mAxesAtt.size() > 0) { 
  scwatt = mAxesAtt;
  scw->DecodeOptionString(scwatt, true);
}
if (opts.size() > 0) 
  scd->DecodeOptionString(opts, true);
if (opts.size() > 0) 
  scw->DecodeOptionString(opts, false);

//   Titre du plot
if (mAddTitle) {
  if (title.length() <= 0)  title = name;  string t2="";   
  scw->SetTitles(title, t2);    
}

scw->AddScDrawer(scd, true);
// scw->Refresh();   ? Pas necessaire  Reza 19/08/98, 05/05/99 $CHECK$ 

mCurWin = win;
mCurWdg = scw;
mLastWdg = scw;
mBWId++;
mBWList[mBWId] = scw;
return(mBWId); 
}

/* --Methode-- */
int PIStdImgApp::Disp3DDrawer(PIDrawer3D* dr3, string const & name, string const& sop, 
			      string title, int oid)
{
if (dr3 == NULL)
  {
  printf("PIStdImgApp::Disp3DDrawer_Error  Cannot Add NULL 3DDrawer \n");
  return(-1);
  }

// On decode les options graphiques
vector<string> opts;
DispWinEnum dwopt = ParseDisplayOption(sop, opts);

if ( (!mLastWdg) && ( (dwopt == Disp_Same) || (dwopt == Disp_Inset) ) )  dwopt = Disp_Next;
// Trace en superpoistion
if ( (dwopt == Disp_Same) && (mLastWdg) ) {
  // Les options 
  dr3->DecodeOptionString(mDefaultAtt, false);
  if (nb_disp_same > 1) {
    vector<string> ostatpos;
    int spo = nb_disp_same%4;
    if (spo == 1) ostatpos.push_back("statposoff=-0.01,-0.26");
    else if (spo == 2)  ostatpos.push_back("statposoff=-0.36,-0.01");
    else  ostatpos.push_back("statposoff=-0.36,-0.26");
    dr3->DecodeOptionString(ostatpos, true);
  }

  dr3->DecodeOptionString(opts, true);

  if (mLastWdg->kind() == PIDraw3DWdg::ClassId)  ((PIDraw3DWdg*)mLastWdg)->AddDrawer3D(dr3, true);
  else mLastWdg->AddDrawer(dr3, true, true, true);
  dr3->Refresh();
  mDId++;
  mDrwList[mDId] = dr3;
  return(-mDId);   
}
// Trace en medaillon
else if ( (dwopt == Disp_Inset) && (mLastWdg) ) {
  PIGrCoord x1, x2, y1, y2;
  x1 = mIXmin;  x2 = mIXmax;
  y2 = 1.-mIYmin;  y1 = 1.-mIYmax;
  // Les options 
  dr3->DecodeOptionString(mDefaultAtt, false);
  dr3->DecodeOptionString(opts, true);

  dr3->SetAxesFlags(mAxesFlags);
  dr3->UpdateLimits();
  mLastWdg->AddDrawer(dr3, x1, y1, x2, y2, true, false, true);
  dr3->Refresh();
  mDId++;
  mDrwList[mDId] = dr3;
  return(-mDId);   
}


PIWindow* win;
int sx, sy, px, py, flag;
sx = 200+mFgScSz*100;
sy = 200+mFgScSz*100;
win = GetWindow(dwopt, sx, sy, px, py, flag, (char *)name.c_str());
PIDraw3DWdg* wd3 = new PIDraw3DWdg(win, (char *)name.c_str(), sx, sy, px, py);
wd3->SetBinding(PIBK_elastic, PIBK_elastic, PIBK_elastic, PIBK_elastic);
wd3->SetUserData(NULL, oid);

// Decodage des options :
vector<string> scwatt;
// wd3->SetAxesFlags(mAxesFlags);  Attributs d'axes 3D a faire 
if ( mDefaultAtt.size() > 0) { 
  scwatt = mDefaultAtt;
  dr3->DecodeOptionString(scwatt, true);
  wd3->DecodeOptionString(scwatt, true);
}
if ( mAxesAtt.size() > 0) { 
  scwatt = mAxesAtt;
  wd3->DecodeOptionString(scwatt, true);
}
if (opts.size() > 0)  
  dr3->DecodeOptionString(opts, true);
if (opts.size() > 0)  
  wd3->DecodeOptionString(opts, false);

//   Titre du plot
if (mAddTitle) {
  if (title.length() <= 0)  title = name;  string t2="";   
  wd3->SetTitles(title, t2);    
}

wd3->AddDrawer3D(dr3, true);
// wd3->Refresh();   ?Pas necessaire   $CHECK$ 05/05/99

mCurWin = win;
mCurWdg = wd3;
mLastWdg = wd3;
mBWId++;
mBWList[mBWId] = wd3;
return(mBWId); 
}

/* --Methode-- */
int PIStdImgApp::ExecuteExtCommand() 
{ 
if (!fg_exc_cmd) return(0); 
else {
  fg_exc_cmd = false; 
  return CmdInterpreter()->Interpret(exc_command); 
  }
}

/* --Methode-- */
void PIStdImgApp::AddText(string const & txt, double xp, double yp, string const& sop, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());
if (elmgr == NULL) return;

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);
unsigned long tpd = 0;
gratt.DecodeTextPosDirAtt(opts, tpd, false);
elmgr->ElAddText(xp,yp,txt.c_str(), gratt, tpd, fgcn);
eld->Refresh();
}

/* --Methode-- */
void PIStdImgApp::AddCompText(string const & txt, string const & txtup, string const & txtdn, 
			      double xp, double yp, string const& sop, 
			      string const& optss, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());
if (elmgr == NULL) return;

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);
unsigned long tpd = 0;
gratt.DecodeTextPosDirAtt(opts, tpd, false);
ParseDisplayOption(optss, opts);
PIGraphicAtt grattss(opts);
elmgr->ElAddCompText(xp,yp,txt.c_str(), gratt, txtup, txtdn, grattss, tpd, fgcn);
eld->Refresh();
}

/* --Methode-- */
void PIStdImgApp::AddLine(double xp1, double yp1, double xp2, double yp2, 
			  string const& sop, bool fgarrow, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr = NULL;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());
if (elmgr == NULL) return;

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);
if (fgarrow) 
  elmgr->ElAddArrow(xp1, yp1, xp2, yp2, gratt, fgcn);
else elmgr->ElAddLine(xp1, yp1, xp2, yp2, gratt, fgcn);
eld->Refresh();
}

/* --Methode-- */
void PIStdImgApp::AddRectangle(double xp1, double yp1, double xp2, double yp2, 
			       string const& sop, bool fgfill, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr = NULL;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());

double xp,yp;
double dx, dy;
if (xp1 < xp2) {
  xp = xp1; dx = xp2-xp1;
}
else {
  xp = xp2; dx = xp1-xp2;
}
if (yp1 < yp2) {
  yp = yp1; dy = yp2-yp1;
}
else {
  yp = yp2; dy = yp1-yp2;
}

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);

if (fgfill) elmgr->ElAddFRect(xp, yp, dx, dy, gratt, fgcn);
else elmgr->ElAddRect(xp, yp, dx, dy, gratt, fgcn);
eld->Refresh();
}

/* --Methode-- */
void PIStdImgApp::AddCircle(double xc, double yc, double r, string const& sop, 
			    bool fgfill, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr = NULL;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);
if (r < -0.5)
  elmgr->ElAddMarker(xc, yc, gratt);
else {
  if (fgfill) elmgr->ElAddFCirc(xc, yc, r, gratt, fgcn);
  else elmgr->ElAddCirc(xc, yc, r, gratt, fgcn);
}
eld->Refresh();
}
/* --Methode-- */
void PIStdImgApp::AddArc(double xc, double yc, double r, double a, double da, 
			 string const& sop, bool fgfill, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr = NULL;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);
if (fgfill) elmgr->ElAddFArc(xc, yc, r, a, da, gratt, fgcn);
else elmgr->ElAddArc(xc, yc, r, a, da, gratt, fgcn);
eld->Refresh();
}

/* --Methode-- */
void PIStdImgApp::AddArc(double x1, double y1, double x2, double y2,
			 double x3, double y3, string const& sop, bool fgfill, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr = NULL;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());
if (elmgr == NULL) return;

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);
if (fgfill) 
  elmgr->ElAddFArc(x1, y1, x2, y2, x3, y3, gratt, fgcn);
else  elmgr->ElAddArc(x1, y1, x2, y2, x3, y3, gratt, fgcn);
eld->Refresh();
}

/* --Methode-- */
void PIStdImgApp::AddPoly(vector<double>& xpol, vector<double>& ypol, 
			  string const& sop, bool fgfill, bool fgcn)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;
PIElDrwMgr* elmgr = NULL;
if (eld2) elmgr = &(eld2->ElDrwMgr());
else if (eld3) elmgr = &(eld3->ElDrwMgr());
if (elmgr == NULL) return;

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);
if (fgfill) 
  elmgr->ElAddFPoly(xpol, ypol, gratt, fgcn);
else  elmgr->ElAddPoly(xpol, ypol, gratt, fgcn);
eld->Refresh();

}


/* --Methode-- */
void PIStdImgApp::SetTitle(string const & titletop, string const & titlebottom, string const& sop)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
PIElDrawer3D* eld3 = dynamic_cast<PIElDrawer3D *>(eld);
if ((eld2 == NULL) && (eld3 == NULL)) return;

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);

if (eld2) { 
  eld2->SetTitles(titletop, titlebottom, gratt);
  eld2->ShowTitles(true);
}
else if (eld3) { 
  eld3->SetTitles(titletop, titlebottom, gratt);
  eld3->ShowTitles(true);
}
eld->Refresh();
}
/* --Methode-- */
void PIStdImgApp::SetAxeLabels(string const & xLabel, string const & yLabel, string const& sop)
{
PIDrawer *eld=CurrentElDrawer();
if (eld == NULL) return;
PIElDrawer* eld2 = dynamic_cast<PIElDrawer *>(eld);
if (eld2 == NULL) return;

vector<string> opts;
ParseDisplayOption(sop, opts);
PIGraphicAtt gratt(opts);

eld2->SetAxesLabels(xLabel, yLabel, gratt);
eld2->ShowAxesLabels(true);

eld->Refresh();
}

/* --Methode-- */
PIDrawer* PIStdImgApp::CurrentElDrawer()
{
PIDrawer *eld=NULL;
if (!mLastWdg)  return(eld);
PIScDrawWdg* sdw=NULL;
PIDraw3DWdg* w3d=NULL;
PIImage* imgw;
switch(mLastWdg->kind()) {
  case PIScDrawWdg::ClassId :
    sdw = dynamic_cast<PIScDrawWdg *>(mLastWdg);
    if (sdw) eld = sdw->BaseDrawer();
    break;
  case PIDraw3DWdg::ClassId :
    w3d = dynamic_cast<PIDraw3DWdg *>(mLastWdg);
    if (w3d) eld = w3d->BaseDrawer();
    break;
  case PIImage::ClassId :
    imgw = dynamic_cast<PIImage *>(mLastWdg);
    if (imgw) eld = imgw->BaseDrawer();
    break;
  default :
    break;
  }
return(eld);
}

/* --Methode-- */
void PIStdImgApp::CreateGraphWin(int nx, int ny, int sx, int sy)
{
if (nx < 1)  nx = 1;
if (ny < 1)  ny = 1;
if (nx > 8)  nx = 8;    
if (ny > 8)  ny = 8;
if ( (sx < 50) && (sy < 50) )   sx = sy = 400+mFgScSz*100; 
char buff[64];
mWId++;
int px, py; 
MainWin()->GetScreenPos(px, py);
sprintf(buff, "PI-GraphicWin (%d)",mWId);
PIZoneWindow* win = new PIZoneWindow(this,  buff, PIWK_normal, nx, ny, sx, sy, px+MainWin()->XSize()+30, 0);
win->SetUserData(NULL, ny*10+nx);  // UserFlag= nY*10 + nX  
mWList[mWId*10+1] = (PIWindow*)win;
win->SetAutoDelChilds(true);
// win->Show();
mGrW = win; 
mGrIdx = 0;
}

/* --Methode-- */
void PIStdImgApp::CreateStackWin(int sx, int sy)
{
if ( (sx < 50) && (sy < 50) )   sx = sy = 300+mFgScSz*100; 
char buff[64];
mWId++;
int px, py; 
MainWin()->GetScreenPos(px, py);
sprintf(buff, "PI-StackWin (%d)",mWId); 
PIStackWindow* win = new PIStackWindow(this,  buff, PIWK_normal, sx, sy, px+MainWin()->XSize()+30, 100);
win->SetUserData(NULL, 9999);  // UserFlag= 9999 
mWList[mWId*10+2] = (PIWindow*)win;
win->SetAutoDelChilds(true);
// win->Show();
mStW = win;
m[2]->SetSensitivity("StackTools", true); 
mStIdx = 0;
}

/* --Methode-- */
PIWindow* PIStdImgApp::GetWindow(DispWinEnum typ, int& sx, int& sy, int& px, int& py, int& flag, char * nom)
{
PIWindow* rw;

switch (typ) {
  case Disp_Next :  // Fenetre graphique courante
  case Disp_Default :
    {
    if (mGrW == NULL) CreateGraphWin();
    int nx, ny;
    mGrW->NbZone(nx, ny);
    PIWdg* nw = mGrW->NextChildPosSize(px, py, sx, sy);
//    cerr << "**DBG** PIStdImgApp::GetWindow() DispNext : nw = " << (long)nw << endl;
    if (nw) DeleteBaseWidget((PIBaseWdg*)nw, false, false);
    flag = mGrIdx;
    mGrIdx = (mGrIdx+1)%(nx*ny);
    rw = mGrW;
    break;
    }

  case Disp_Stack :  // Fenetre de type stack (empilement)
    {
    if (mStW == NULL) CreateStackWin(sx, sy);
    px = py = 0;
    sx = mStW->XSize();
    sy = mStW->YSize();
    flag = mStIdx;
    mStIdx++;
    rw = mStW;
    }
    break;

  default :      // Fenetre ordinaire
    {
    int pwx, pwy; 
    MainWin()->GetScreenPos(pwx, pwy);
    if ( (sx < 50) && (sy < 50) )   sx = sy = 300+mFgScSz*100; 
    rw = new PIWindow(this,  nom, PIWK_normal, sx, sy, pwx+MainWin()->XSize()+30, 300);
    rw->SetUserData(NULL, 0);  // UserFlag= 0 
    mWId++;
    mWList[mWId*10] = rw;
    rw->SetAutoDelChilds(true);
    //    rw->Show();
    px = py = 0;
    flag = 0;
    break;
    }
  }

rw->Show();
mCurWin = rw;
return(rw);
}

/* --Methode-- */
void PIStdImgApp::SetZone(int nzx, int nzy)
{
if (!mGrW) CreateGraphWin(nzx, nzy);
else { 
  int k;
  PIWdg* cwd;
  for(k=0; k<mGrW->NbChilds(); k++) {
    if ((cwd = mGrW->GetChild(k)) == NULL)  continue; 
    DeleteBaseWidget((PIBaseWdg*)cwd, false, false);
    }
  mGrW->SetZone(nzx, nzy);
  }
}

/* --Methode-- */
void PIStdImgApp::StackWinNext()
{
if (mStW)  mStW->DispNext();
}

/* --Methode-- */
void PIStdImgApp::DeleteWindow(PIWindow* w)
{
if (w == NULL)  return;
w->Hide();
bool ownwindow=false;  // To Check if this is one of our windows
WindMList::iterator it;
for(it = mWList.begin(); it != mWList.end(); it++) 
  if ((*it).second == w)  { mWList.erase(it);  ownwindow = true; break; }
if (w == mGrW) { mGrW = NULL;  mGrIdx = -1; }
if (w == mStW) { mStW = NULL;  mStIdx = -1; m[2]->SetSensitivity("StackTools", false); }
if (w == mCurWin) mCurWin = NULL;

if (!ownwindow) return; // We do nothing if this is not a window we have created ...

int k;
PIWdg* cwd;
for(k=0; k<w->NbChilds(); k++) {
  if ((cwd = w->GetChild(k)) == NULL)  continue; 
  DeleteBaseWidget((PIBaseWdg*)cwd,false,false);
  }
delete w;
return;
}

/* --Methode-- */
void PIStdImgApp::DeleteBaseWidget(PIBaseWdg* w, bool dw, bool dwin)
{
if (w == NULL)  return;
BWMList::iterator it;
for(it = mBWList.begin(); it != mBWList.end(); it++) 
  if ((*it).second == w)  { mBWList.erase(it);  break; }
int k;
PIDrawer* drw;
for(k=0; k<w->NbDrawers(); k++) {
  if ((drw = w->GetDrawer(k)) == NULL)  continue; 
  DrwMList::iterator itt;
  for(itt = mDrwList.begin(); itt != mDrwList.end(); itt++) 
    if ((*itt).second == drw)  { mDrwList.erase(itt);  break; }
  }

if (w == mCurWdg) {  
  mCurWdg = NULL;
  if (mFgCWImg) {
    m[4]->SetSensitivityMsg(10515, false);
    m[4]->SetSensitivityMsg(10516, false);
    mFgCWImg = false;
    }
  }

if (w == mLastWdg)  mLastWdg = NULL;

PIWdg* pw=NULL;
if (dwin)  pw = (PIWdg*)(w->Parent());
//DBG printf("DeleteBaseWidget(%lx)-DBG kind = %d - %d %d \n", (long)w, w->kind(), (int)dw, (int)dwin); 
if (dw) delete w;
if (pw && (pw->kind() == PIWindow::ClassId )) {
 PIWindow* pww = (PIWindow*) pw;
 if ((pww != (PIWindow*)mGrW) && (pww != (PIWindow*)mStW) && (pww->NbChilds()==0)) 
    DeleteWindow((PIWindow*)pw);
 } 
return;
}



/* --Methode-- */
void PIStdImgApp::DelWRsId(int k)
{
//DBG cerr << "-DBG- PIStdImgApp::DelWRsId(" << k << ")" << endl; 
if (k > 0) { // C'est un BaseWidget
  BWMList::iterator it;
  it  = mBWList.find(k);
  if (it == mBWList.end())  return;
  PIBaseWdg* wd = (*it).second;
//DBG cerr << "-DBG- PIStdImgApp::DelWRsId Deleting BaseWidget " << (long)(wd) << endl ; 
  DeleteBaseWidget(wd, true, true);
  }
else {  // C'est un drawer
  DrwMList::iterator it;
  it  = mDrwList.find(-k);
  if (it == mDrwList.end())  return;
  (*it).second->SetAutoRefreshOnDelete(true);
  delete (*it).second;  
  mDrwList.erase(it);
  //DBG cerr << "+DBG+ PIStdImgApp::DelWRsId Deleting Drawer " << (long)((*it).second) << endl ; 
  }
}
/* --Methode-- */
bool PIStdImgApp::CheckWRsId(int k)
{
if (k > 0) { // C'est un BaseWidget
  BWMList::iterator it;
  it  = mBWList.find(k);
  if (it == mBWList.end())  return(false);
  else return(true);
  }
else {  // C'est un drawer
  DrwMList::iterator it;
  it  = mDrwList.find(-k);
  if (it == mDrwList.end())  return(false);
  else return(true);
  }
}

/* --Methode-- */
void PIStdImgApp::StatZoomWindowSetVisible(bool fg)
{

  if (fg) {
    consolecont->SetBinding(PIBK_free,PIBK_free,PIBK_free, PIBK_free); 
    int szy = MainWin()->YSize();
    MainWin()->SetSize(MainWin()->XSize(), szy+statcont->YSize());
    consolecont->SetPos(0, statcont->YSize());
    consolecont->SetSize(MainWin()->XSize(), szy);
    consolecont->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_fixed); 
    statcont->Show();
    m[3]->SetStateMsg(10470, true);
  }
  else {
    statcont->Hide();
    consolecont->SetBinding(PIBK_free,PIBK_free,PIBK_free, PIBK_free); 
    MainWin()->SetSize(MainWin()->XSize(), MainWin()->YSize()-statcont->YSize());
    consolecont->SetPos(0, 0);
    consolecont->SetSize(MainWin()->XSize(), MainWin()->YSize());
    consolecont->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_fixed); 
    m[3]->SetStateMsg(10470, false);    
  }
  
}

/* --Methode-- */
void PIStdImgApp::UpdateStatResourceInfo()
{
  resusg.Update();
  char buff[256];
  string lab;
  double frac;
  sprintf(buff, "Mem: %ld/Max= %ld kb" , (long)resusg.getMemorySize(), 
	  (long)resusg.getMaxMemorySize());
  lab = buff;
  lab_mem->SetLabel(lab);
  frac = (double)resusg.getMemorySize()/(double)resusg.getMaxMemorySize();
  therm_mem->SetValue(frac);

  sprintf(buff, "CPU: %ld/elap= %ld ms" , (long)resusg.getCPUTime(), 
	  (long)resusg.getElapsedTime());
  lab = buff;
  lab_cpu->SetLabel(lab);
  if (resusg.getCPULoad() > resusg.getAverageCPULoad()) 
    therm_cpu->SetValue(resusg.getCPULoad());
  else 
    therm_cpu->SetValue(resusg.getAverageCPULoad());
}

/* --Methode-- */
void PIStdImgApp::RedirectStdOutErr(bool fg)
{
if (fg) { 
  RedirectOutStream(mCons);
  RedirectErrStream(mCons);
  m[5]->SetStateMsg(10602, true);
  redirecout = true;
  }
else {
  RedirectOutStream(NULL);
  RedirectErrStream(NULL);
  m[5]->SetStateMsg(10602, false);
  redirecout = false;
  }
return;
}

/* --Methode-- */
void PIStdImgApp::CatchSignals(bool fgfpe, bool fgsegv)
{    
#ifdef SANS_EVOLPLANCK
PeidaConfigureSignalhandling(fgfpe, fgsegv, true, true);  
#else
SophyaConfigureSignalhandling(fgfpe, fgsegv, true, true);  
#endif
m[5]->SetStateMsg(10603, fgfpe);
m[5]->SetStateMsg(10604, fgsegv);
}

/* --Methode-- */
void PIStdImgApp::CloseAllWindows()
{
WindMList::iterator it;
for(it = mWList.begin(); it != mWList.end(); it++)   delete (*it).second;
mWList.clear();
mBWList.clear();
mDrwList.clear(); 
mGrW = NULL;
mStW = NULL;
mCurWin = NULL;
mCurWdg = NULL;
mLastWdg = NULL;
m[4]->SetSensitivityMsg(10515, false);
m[4]->SetSensitivityMsg(10516, false);
}

//---------------------------------------------------------------------------
//--------- Gestion des attributs graphiques et autres options de trace -----

/* --Methode-- */
void PIStdImgApp::SetInsetLimits(double xmin, double xmax, double ymin, double ymax)
{
  mIXmin = xmin;  mIXmax= xmax;
  mIYmin = ymin;  mIYmax= ymax;
}

/* --Methode-- */
void PIStdImgApp::SetDefaultGraphicAttributes(string const & opt)
{
  ParseDisplayOption(opt, mDefaultAtt);
}

/* --Methode-- */
void PIStdImgApp::SetDefaultAxesAttributes(string const & opt)
{
  ParseDisplayOption(opt, mAxesAtt);
}

/* --Methode-- */
DispWinEnum PIStdImgApp::ParseDisplayOption(string const & sop, vector<string>& opts)
{
  DispWinEnum rc = Disp_Next;
  //DBG  cerr << " DBG-Parse-A sop=" << sop << " sop.length()= " << sop.length() << endl;
  if (opts.size() > 0)  opts.erase(opts.begin(), opts.end());
  if (sop.length() < 1) return(rc);
  string gratt = sop;
  for(int i=0; i<gratt.length(); i++) gratt[i] = tolower(gratt[i]);
  if ( (gratt == "def") || (gratt == "default") ) return(rc);
// On separe en mots espaces par des blancs ou tabulation 
  size_t p = 0;
  size_t q = 0;
  size_t l = gratt.length();
  string token;
  while (q < l)  {
    p = gratt.find_first_not_of(" \t",q);   // au debut d'un token
    if (p >= l) break;
    q = gratt.find_first_of(" \t",p);       // Premier blanc ou tab suivant
    if (q<l) token = gratt.substr(p,q-p);
    else token = gratt.substr(p);
    if (token == "") continue;
    // Decodage option fenetre d'affichage (win, next, ...)
    if (token == "win")   rc =  Disp_Win;
    else if (token == "same")  rc = Disp_Same;
    else if (token == "inset")   rc = Disp_Inset;
    else  if (token == "stack")   rc = Disp_Stack;
    else  if (token == "next")   rc = Disp_Next;
    // Option a etre decode par les drawers, etc ...
    else  opts.push_back(token); 
  }

  //DBG  cerr << " DBG-Parse-B opts.size()=" << opts.size() << endl;
  if (rc == Disp_Same) nb_disp_same++;
  else nb_disp_same = 0;
  return (rc);
}

//---------------------------------------------------------------------------
//------------       Methodes privees (MBProcessx, ...)    ----------

/* --Methode-- */
void PIStdImgApp::MBProcess1(PIMessage msg, PIMsgHandler* /*sender*/, void* data)
{

  switch(msg)
    {
    case 10150 :
      showInfoWindow(this);
      break;

    case 10155 :
      hideInfoWindow(this);
      break;

    case 10100 :
      mCmd->ShowHelpWindow();
      break;

    case 10120 :
      pfc_fits->AcceptNewFile(false);
      mFCMsg = 10125; 
      pfc_fits->SetMsg(mFCMsg);
      SetBlocked();
      pfc_fits->Show();
      break;

    case 10125 :
      SetBusy();
      if (data)  { 
        string nomobj="";
        ObjMgr()->ReadFits(pfc_fits->GetFileName(), nomobj);
        ObjMgr()->DisplayObj(nomobj, "win");
      }
      mFCMsg = 0;
      SetReady();
      break;

    case 10130 :
      pfc_ppf->AcceptNewFile(false); 
      mFCMsg = 10135; 
      pfc_ppf->SetMsg(mFCMsg);
      SetBlocked();
      pfc_ppf->Show();
      break;

    case 10135 :
      mFCMsg = 0;
      if (data)  { 
        PPInMgrW()->SetFile(pfc_ppf->GetFileName());
        PPInMgrW()->Show();
      }
      SetReady();
      break;
        
#ifndef SANS_EVOLPLANCK
    case 10140 :
      pfc_ascii->AcceptNewFile(false);
      mFCMsg = 10145; 
      pfc_ascii->SetMsg(mFCMsg);
      SetBlocked();
      pfc_ascii->Show();
      break;

    case 10145 :
      SetBusy();
      if (data)  { 
	string afname = pfc_ascii->GetFileName();
        string nomobj = ObjMgr()->GetServiceObj()->FileName2Name(afname);
	string cmd = "mtxfrascii ";
	cmd += nomobj;  cmd += " ";  cmd += afname;
	try {
	  mCmd->Interpret(cmd);
	}  
	catch ( PThrowable & exc ) {
	  cerr << "\n PIStdImgApp::Process()/ Cmd->Interpret() Exception :" 
	       << (string)typeid(exc).name() << " Msg= " 
	       << exc.Msg() << endl;
	  cout << endl; 
	}
	catch ( ... ) {
	  cerr << "\n PIStdImgApp::Process()/ Cmd->Interpret() Catched Exception ... " << endl;
	  cout << endl; 
	}
	
      }
      mFCMsg = 0;
      SetReady();
      break;
#endif

    case 10105:
      Stop();
      break;

  }
return;
}



/* --Methode-- */
void PIStdImgApp::MBProcess2(PIMessage msg, PIMsgHandler* /*sender*/, void* data)
{

switch (msg)  { 
  case 10201 :
     ObjMgrW()->Show();
     break;

  case 10220 :
     pfc_ppf->AcceptNewFile(true);
     mFCMsg = 10225;
     pfc_ppf->SetMsg(mFCMsg);
     SetBlocked();
     pfc_ppf->Show();
     break;

   case 10225 :
     SetBusy();
     if (data) {
       if (mPpfout) {  
         printf("PIStdImg/Info: Closing POutPersist-File %s \n", name_outppf.c_str());
         delete mPpfout;  
       }
       name_outppf = pfc_ppf->GetFileName();
       mPpfout = NULL;
       printf("PIStdImg/Info: Opening POutPersist-File %s \n", name_outppf.c_str());
       mPpfout = new POutPersist(name_outppf);
    }
    mFCMsg = 0;
    SetReady();
    break;

  case 10230 :
    if (!mPpfout)  break;
    printf("PIStdImg/Info: Closing POutPersist-File %s \n", name_outppf.c_str());
    delete mPpfout;  
    name_outppf = "";
    mPpfout = NULL;
    break;

  case 10270 :
    if (mCurWdg) {
      int oid = mCurWdg->UserFlag();
      DeleteBaseWidget(mCurWdg);
      mObjMgr->DelObj_Id(oid);
      }
    break;

  default:
    cerr << "PIStdImgApp::MBProcess2() BUG?? Msg= " <<  msg << endl;    
    break;
}

return;
}

/* --Methode-- */
void PIStdImgApp::MBProcess3(PIMessage msg, PIMsgHandler* /*sender*/, void* /*data*/)
{

switch (msg)  { 
  case 10301 :
    PIImgTools::ShowPIImgTools();
    break; 
  case 10302 :
    PIDrwTools::ShowPIDrwTools();
    break;
  case 10303 :
    PIAxesTools::ShowPIAxesTools();
    break;

  case 10304 :
    mCmd->ShowCxxExecWindow();
    break;

  case 10311 :
  case 10312 :
    {
    PIImage* curpimg = NULL;
    if (!mCurWdg)  return;
    if (mCurWdg->kind() != PIImage::ClassId)  return;
    curpimg = (PIImage*)mCurWdg;
    if (curpimg == NULL)   return;
    P2DArrayAdapter* img = curpimg->Image();
    if (img == NULL) return;
    int dx = curpimg->XSzPave();
    int dy = curpimg->YSzPave();  
    int x0 = curpimg->XPave()-dx/2;
    int y0 = curpimg->YPave()-dy/2;
    if (x0 < 0)  x0 = 0;
    if (y0 < 0)  y0 = 0;
    int x1 = x0+dx;
    int y1 = y0+dy;
    if (x1 > img->XSize()) x1 = img->XSize();
    if (y1 > img->YSize()) y1 = img->YSize();
    dx = x1-x0;  dy = y1-y0;
    ImageR4* pim = new ImageR4(dx, dy); 
    int ii, jj;
    for(jj=0; jj<dy; jj++) 
      for(ii=0; ii<dx; ii++) (*pim)(ii,jj) = (*img)(ii+x0, jj+y0);
    if (msg == 10305) {  // Calcul des coordonnees du sous-pave
      double xc1, yc1;
      img->Coord(x0, y0, xc1, yc1);
      pim->SetOrg((int)xc1, (int)yc1);
    }
    string nom = mCurWdg->Nom() + "_pave";
    ObjMgr()->AddObj(pim, nom);
    ObjMgr()->DisplayObj(nom, "w");
    break;
    }

  case 10313 :
    {
    PIImage* curpimg = NULL;
    if (!mCurWdg)  return;
    if (mCurWdg->kind() != PIImage::ClassId)  return;
    curpimg = (PIImage*)mCurWdg;
    if (curpimg == NULL)   return;
    curpimg->ShowCuts(true);
    break;
    }

  case 10320 :
    if (mStW)  mStW->DispNext();
    break;

  case 10321 :
  case 10322 :
  case 10324 :
//  case 10328 :
    if (mStW) mStW->StartAutoDisp((msg-10320)*500);
    break;

  case 10329 :
    if (mStW) mStW->StopAutoDisp();
    break;

  case 103330 :
    if (mStW) {
      PIWdg* cw =  mStW->CurrentWdg();
      if (cw) DeleteBaseWidget((PIBaseWdg*)cw);
      }
    break;

  default:
    cerr << "PIStdImgApp::MBProcess3() BUG?? Msg= " <<  msg << endl;    
    break;
  }
return;
}

/* --Methode-- */
void PIStdImgApp::MBProcess4(PIMessage msg, PIMsgHandler* /*sender*/, void* /*data*/)
{

switch (msg)  { 

  case 10400 :
    CreateStackWin();
    break;

  case 10411 :
    CreateGraphWin(1,1);
    break;
  case 10421 :
    CreateGraphWin(1,2);
    break;
  case 10412 :
    CreateGraphWin(2,1);
    break;
  case 10422 :
    CreateGraphWin(2,2);
    break;
  case 10431 :
    CreateGraphWin(1,3);
    break;
  case 10433 :
    CreateGraphWin(3,3);
    break;
  case 10441 :
    if (mCurWdg)  { 
      mLastWdg = mCurWdg;
      cout << " Using current widget as last-widget (display same) " << endl;
      }
    else  cout << " No current widget - select widget with mouse " << endl;
    break;
    case 10460 :
      DeleteWindow(mCurWin);
      break;
    case 10470 :
      StatZoomWindowSetVisible(m[3]->GetStateMsg(10470));
      break;
  default:
    cerr << "PIStdImgApp::MBProcess4() BUG?? Msg= " <<  msg << endl;    
    break;
  }
return;
}


/* --Methode-- */
void PIStdImgApp::MBProcess5(PIMessage msg, PIMsgHandler* /*sender*/, void* data)
{
char nomps[64],strg[512];
PSFile *mps;
int sxt, syt, syo, syo1, sx[4], sy[4];

switch (msg)
  { 
  case 10501 :
     pfc_ps->AcceptNewFile(true); 
     mFCMsg = 10525; 
     pfc_ps->SetMsg(mFCMsg);
     SetBlocked();
     pfc_ps->Show();
     break;

   case 10525 :
     SetBusy();
     if (data) {
       if (mpsfile) {  
         printf("PIStdImg/Info: Closing PS-File %s \n", name_ps.c_str());
         delete mpsfile;  
         }
        name_ps = pfc_ps->GetFileName();
        printf("PIStdImg/Info: Opening PS-File %s \n", name_ps.c_str());
        mpsfile = new PSFile(name_ps.c_str(), PI_Portrait, PI_A4, 2., 2.);
        }
      mFCMsg = 0;
      SetReady();
      break;

  case 10505 :
    if (!mpsfile)  break;
    printf("PIStdImg/Info: Closing PS-File %s \n", name_ps.c_str());
    delete mpsfile;
    mpsfile = NULL;
    name_ps = "";
    break;

  case 10511 :     // Window -> PS
  case 10512 :     // Window -> EPS 
    if (CurrentWindow() == NULL)  break;
    if (msg == 10512) 
      { 
      num_eps++;
      sprintf(nomps,"pia%d.eps", num_eps);
      printf("PIStdImg/Info: Creating EPSFile %s (CurWin-> EPS) \n", nomps);
      mps = new PSFile(nomps);
      }
    else {
      if (mpsfile == NULL) {
        name_ps = "pia.ps";
        mpsfile = new PSFile(name_ps.c_str(), PI_Portrait, PI_A4, 0., 0.);
        printf("PIStdImg/Info: File PS %s opened \n", name_ps.c_str());
      }
      printf("PIStdImg/Info: CurWin-> PSFile %s\n", name_ps.c_str());      
      mps = mpsfile; 
      }
    CurrentWindow()->PSPrint(mps,0,0);

    if (msg == 10512)   delete mps;   // fichier eps
    break;

  case 10515 :    // Image -> PS
  case 10516 :    // Image -> EPS 
     {
     PIImage* curpimg = NULL;
     if (!mCurWdg)  return;
     if (mCurWdg->kind() != PIImage::ClassId)  return;
     curpimg = (PIImage*)mCurWdg;
     if (curpimg == NULL)   return;
     if (msg == 10516) 
      { 
      num_eps++;
      sprintf(nomps,"pia%d.eps", num_eps);
      printf("PIStdImg/Info: Creating EPSFile %s (CurImage-> EPS)\n", nomps);
      mps = new PSFile(nomps);
      }
    else {
      if (mpsfile == NULL) {
        name_ps = "pia.ps";
        mpsfile = new PSFile(name_ps.c_str(),PI_Portrait, PI_A4, 2., 2.);
        printf("PIStdImg/Info: File PS %s opened \n", name_ps.c_str());
      }
      printf("PIStdImg/Info: CurImage-> PSFile %s\n", name_ps.c_str());       
      mps = mpsfile; 
      }

    sx[0] = gimv->XSize(); 
    sy[0] = gimv->YSize();
    sx[1] = zoom->XSize(); 
    sy[1] = zoom->YSize();
    sx[2] = cmapv->XSize(); 
    sy[2] = cmapv->YSize();
    sx[3] = curpimg->XSize(); 
    sy[3] = curpimg->YSize();
    if (sy[1] > sy[0])  { syo1 = sy[1]+50;  syo = sy[1]+sy[2]+60; }
    else  { syo1 = sy[0]+50;  syo = sy[0]+sy[2]+60; }
    syt = sy[3]+syo;
    sxt = sx[3];
    if (sxt < (sx[0]+sx[1]+20))  sxt = sx[0]+sx[1]+20;
    if (sxt < sx[2])  sxt = sx[2];

    // Pour ecrire le titre 
    mps->NewPage((float)sxt, (float)syt, PI_Portrait);
    mps->NewBloc(0,0, (float)sxt, 30., (float)sxt, 30.);
    sprintf(strg,"Image: %s -  Pave %d %d \n",  curpimg->Nom().c_str(), 
            curpimg->XPave(),  curpimg->YPave());     
    mps->DrawString(10., 25., strg, PI_Black, PI_DefaultFont, PI_BoldFont, 20);
    mps->EndBloc();

    // Les quatre fenetres glovimage, zoom, cmap, image 
    gimv->PSPrint(mps, -gimv->XPos(), -gimv->YPos()+40);
    zoom->PSPrint(mps, -zoom->XPos()+sx[0]+20, -zoom->YPos()+40);
    cmapv->PSPrint(mps, -cmapv->XPos(), -cmapv->YPos()+syo1);
    curpimg->PSPrint(mps, -curpimg->XPos(), -curpimg->YPos()+syo);
     
    if (msg == 10516)   delete mps;    // fichier eps
    break;
    }

  default:
    cerr << "PIStdImgApp::MBProcess5() BUG?? Msg= " <<  msg << endl;    
    break;
  }

}


/* --Methode-- */
void PIStdImgApp::MBProcess6(PIMessage msg, PIMsgHandler* /*sender*/, void* data)
{
switch (msg)  { 
  case 10601:
    CloseAllWindows();
    break;
  case 10602:
    RedirectStdOutErr(*((bool*)data));
    break;
  case 10603:
  case 10604:
    CatchSignals(m[5]->GetStateMsg(10603), m[5]->GetStateMsg(10604));
    break;
  case 10605:
    mObjMgr->SetVerbose(m[5]->GetStateMsg(10605));
    break;
  case 10606:
    mCmd->ShowCxxOptionWindow();
    break;
  default:
    cerr << "PIStdImgApp::MBProcess6() BUG?? Msg= " <<  msg << endl;    
    break;
  }
return;
}



//  -------------------------------------------------
//        Fenetre info piapp (About piapp) 
//  -------------------------------------------------
static PIWindow* infow_win = NULL;
static PIText* infow_txt = NULL;
static PICMapView* infow_cmap = NULL;
static PIButton* infow_but = NULL;

/* Nouvelle-Fonction */
static void createInfoWindow(PIStdImgApp* app)
{
if (infow_win) return;

int bsx, bsy;
PIApplicationPrefCompSize(bsx, bsy);
int spx, spy;
spx = bsx/6;   spy = bsy/6;

infow_win = new PIWindow((PIMsgHandler *)app, "About piapp", 
                         PIWK_dialog, bsx*5+3*spx, bsy*4+spy*3, 200, 200);
infow_win->SetAutoDelChilds(true);
infow_txt = new PIText(infow_win,"about_piapp_text", bsx*5+spx, bsy*3, spx, spy);
infow_txt->SetMutiLineMode(true);
infow_txt->SetTextEditable(false);
infow_txt->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
infow_cmap = new PICMapView(infow_win, "about_piapp_cmap", bsx*4, bsy*0.7, spx, 2*spy+bsy*3.15); 
infow_cmap->SetColMapId(CMAP_COLBR32, 1., -1., false); 
infow_cmap->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
infow_but = new PIButton(infow_win,"OK", 10155, bsx, bsy, bsx*4+2*spx, 2*spy+bsy*3);
infow_but->SetMsgParent((PIMsgHandler *)app);
infow_but->SetBinding(PIBK_elastic,PIBK_elastic, PIBK_elastic,PIBK_elastic);
char buff[128];
#ifdef SANS_EVOLPLANCK
sprintf(buff, "Version: piapp=%g  PI=%g  PEIDA=%g \n", (double)PIAPP_VERSIONNUMBER, 
              (double)PI_VERSIONNUMBER, (float)PeidaVersion());
#else
{
sprintf(buff, "Version: piapp=%g  PI=%g  SOPHYA=%g \n", (double)PIAPP_VERSIONNUMBER, 
              (double)PI_VERSIONNUMBER, glst_piai->Version());
}
#endif
string info = "piapp : Interactive analysis program\n";
info += buff;
info += "(C) LAL-IN2P3/CNRS  1996-2003\n";
info += "(C) SPP-DAPNIA/CEA 1996-2003\n";
#ifndef SANS_EVOLPLANCK
 info += "Check http://www.sophya.org for more information";
#endif
infow_txt->SetText(info);
}

/* Nouvelle-Fonction */
static void showInfoWindow(PIStdImgApp* app)
{
if (!infow_win) createInfoWindow(app);
if (infow_win) infow_win->Show();
}
/* Nouvelle-Fonction */
static void hideInfoWindow(PIStdImgApp* app)
{
if (infow_win) infow_win->Hide();
}

/* Nouvelle-Fonction */
static void deleteInfoWindow()
{
if (!infow_win) return;
delete infow_win;
infow_win = NULL;
infow_txt = NULL;
infow_cmap = NULL;
infow_but = NULL;
}


