#include<stdio.h>

#include "pilistx.h"
#include "picontainerx.h"

#include <Xm/Xm.h>
#include <Xm/List.h>


/************* PIListX ************/

// Pour ces sal... de XmString  (ds piwdgx.cc)
int CStrFrXmStr(XmString xms, char* buff, int nmx);

// Fonction prive (CallBack)
static void list_action(Widget w, XtPointer *usd, XmListCallbackStruct *isel);

/* Nouvelle-Fonction */
void  list_action(Widget /*w*/, XtPointer *usd, XmListCallbackStruct *isel)
{
PIListX *pil;

pil = (PIListX *)usd ;
//  printf("list_action/Debug: reason=%d itemPos= %d \n", 
//          isel->reason, isel->item_position);
pil->ToggleSel(isel->item_position-1, true);
return;
}


#define NBITEMB  20
#define NBISELB  5


/* --Methode-- */
PIListX::PIListX(PIContainerGen* par, const char* nom,
                 int sx, int sy, int px, int py)
: PIListGen(par, nom, sx, sy, px, py)
{

mNItem = mNItemMax = 0;
mMess = NULL;  mSel = NULL;
mNbSel = mNSelMax = 0;
mSelNum = NULL;
 
Arg  warg[7];
int n = 0;
XtSetArg(warg[n], XmNlistSizePolicy, XmCONSTANT);  n++;
XtSetArg(warg[n], XmNscrollBarDisplayPolicy, XmAS_NEEDED);  n++;
// **ATTENTION** Il vaut mieux creer avec les bonnes tailles au depart Reza 09/99 
//     .....   C'est fait par CreateXtWdg( ... )
XtSetArg(warg[n],XmNwidth,sx);  n++;
XtSetArg(warg[n],XmNheight,sy);  n++;
XtSetArg(warg[n],XmNx,px);  n++;
XtSetArg(warg[n],XmNy,py);  n++;
mlist = XmCreateScrolledList(((PIWdgX *)par)->XtWdg(), (char *)nom, warg, n);  // const_cast
XtManageChild(mlist);
XtWdg() = XtParent(mlist);
wmis = k_wmi_normal ;
stmng = 0;

// **ATTENTION** A ne pas oublier , fait par CreateXtWdg Reza 09/99 
SetBinding(PIBK_free, PIBK_free, PIBK_free, PIBK_free);
par->ChildAdd(this);

//XtAddCallback(mlist, XmNdefaultActionCallback,
//              list_action, (XtPointer)this);
XtAddCallback(mlist, XmNmultipleSelectionCallback,
              (XtCallbackProc)list_action, (XtPointer)this);
XtAddCallback(mlist, XmNsingleSelectionCallback,
              (XtCallbackProc)list_action, (XtPointer)this);

SetMultipleSelect(false);
Manage();
}

/* --Methode-- */
PIListX::~PIListX()
{

if (mNItemMax > 0)  
  {
    //  XtFree((char *)mItems);
  delete[] mMess;
  delete[] mSel;
  }  
if (mNSelMax > 0)  delete[] mSelNum;
}


/* --Methode-- */
void PIListX::AppendItem(const char * item, PIMessage msg)
{

if (mNItem >= mNItemMax)
  {
  PIMessage *mso;
  bool *slo;
  int i;

  mso = mMess;
  slo = mSel;
  mNItemMax += NBITEMB;
  mMess = new PIMessage[mNItemMax];
  mSel = new bool[mNItemMax];
  for(i=0; i<mNItem; i++)   
    {  mMess[i] = mso[i];  mSel[i] = slo[i]; }

  delete[] mso;
  delete[] slo;
  }

mMess[mNItem] = msg;
mSel[mNItem] = false;
mNItem++;

#if defined(__DECCXX) || defined(__KCC__) || defined(__aCC__)
XmString xms = XmStringCreate(const_cast<char *>(item), XmSTRING_DEFAULT_CHARSET);
#else
XmString xms = XmStringCreate((char *)(item), XmSTRING_DEFAULT_CHARSET);
#endif
XmListAddItem(mlist, xms, 0);
XmStringFree(xms);
return;
}

/* --Methode-- */
void PIListX::DeleteItem(const char * item)
{
int n;
if ((n=GetNumItem(item)) < 0)  return;
DelItem(n);
return;
}

/* --Methode-- */
void PIListX::DeleteItemMsg(PIMessage msg)
{
int n;
if ((n=GetNumItemMsg(msg)) < 0)  return;
DelItem(n);
return;
}

/* --Methode-- */
void PIListX::DeleteAllItems()
{
int nmax = mNItem;
bool mng = IfManaged();
if (mng) UnManage();
for(int i=0; i<nmax; i++) DelItem(0);
if (mng) Manage();
}

/* --Methode-- */
int PIListX::GetNbItems()
{
return(mNItem);
}

/* --Methode-- */
PIMessage PIListX::GetItemMsg(int n)
{
return(ItemMsg(n));
}

/* --Methode-- */
string PIListX::GetItem(int n)
{
return(ItemStr(n));
}

/* --Methode-- */
void PIListX::SetMultipleSelect(bool ms)
{
Arg  warg[2];

mMultSel = ms;
if (ms)
  XtSetArg(warg[0], XmNselectionPolicy, XmMULTIPLE_SELECT);  
else
  XtSetArg(warg[0], XmNselectionPolicy, XmSINGLE_SELECT);  

XtSetValues(mlist, warg, 1);
}

/* --Methode-- */
int PIListX::GetNbSelection()
{
return(mNbSel);
}

/* --Methode-- */
PIMessage PIListX::GetSelection(int num)
{
if ( (num < 0) || (num >= mNbSel) ) return(0); 
return(ItemMsg(mSelNum[num]));
}

/* --Methode-- */
string PIListX::GetSelectionStr(int num)
{
if ( (num < 0) || (num >= mNbSel) ) return(""); 
string s(ItemStr(mSelNum[num]));
return(s);
}

/* --Methode-- */
void PIListX::SelectItem(const char * item)
{
int n;
if ((n=GetNumItem(item)) < 0)  return;
if ((!mMultSel) && (mNbSel > 0))
  if  (mSelNum[0] != n)  ClrSItem(mSelNum[0], false, true);  
SelItem(n, false, true);
return;
}

/* --Methode-- */
void PIListX::SelectItemMsg(PIMessage msg)
{
int n;
if ((n=GetNumItemMsg(msg)) < 0)  return;
if ((!mMultSel) && (mNbSel > 0))
  if  (mSelNum[0] != n)  ClrSItem(mSelNum[0], false, true);  
SelItem(n, false, true);
return;
}


/* --Methode-- */
void PIListX::ClearSelItem(const char * item)
{
int n;
if ((n=GetNumItem(item)) < 0)  return;
ClrSItem(n, false, true);
return;
}

/* --Methode-- */
void PIListX::ClearSelItemMsg(PIMessage msg)
{
int n;
if ((n=GetNumItemMsg(msg)) < 0)  return;
ClrSItem(n, false, true);
return;
}


/* --Methode-- */
void PIListX::ToggleSel(int n, bool smg)
{
if ( (n < 0) || (n >= mNItem))  return;
if (mSel[n])  ClrSItem(n,smg); 
else
  {
  if ((!mMultSel) && (mNbSel > 0))  ClrSItem(mSelNum[0], smg);
  SelItem(n, smg);
  }
}


/* --Methode-- */
PIMessage PIListX::ItemMsg(int n)
{
if ( (n < 0) || (n >= mNItem))  return(0);
else return(mMess[n]);
}

/* --Methode-- */
char * PIListX::ItemStr(int n)
{
Arg  warg[2];
XmString *xmst=NULL;

if ( (n < 0) || (n >= mNItem))  { mSItem[0] = '\0'; return(mSItem); }
mSItem[0] = '\0';
XtSetArg(warg[0], XmNitems, &xmst);  
XtGetValues(mlist, warg, 1);
CStrFrXmStr(xmst[n], mSItem, 320);
return(mSItem);
}

/* --Methode-- */
int PIListX::GetNumItem(const char *it)
{
for(int i=0; i<mNItem; i++)
  if (strcmp(ItemStr(i), it) == 0)  return(i);
return(-1);
}

/* --Methode-- */
int PIListX::GetNumItemMsg(PIMessage msg)
{
for(int i=0; i<mNItem; i++)
  if (mMess[i] == msg)   return(i);  
return(-1);
}



/* --Methode-- */
void PIListX::DelItem(int n)
{
int i;

if ((n < 0) || (n > mNItem))  return;

ClrSItem(n);
for(i=n; i<mNItem-1; i++)
  { mMess[i] = mMess[i+1];  mSel[i] = mSel[i+1]; }
mNItem--;

if (mNItem < (mNItemMax-NBITEMB-1))
  {
    //  XmString *ito;
  PIMessage *mso;
  bool *slo;

  //  ito = mItems;
  mso = mMess;
  slo = mSel;
  mNItemMax -= NBITEMB;
  mMess = new PIMessage[mNItemMax];
  mSel = new bool[mNItemMax];
  //  mItems = (XmString *) XtMalloc(sizeof(XmString)*mNItemMax);
  for(i=0; i<mNItem; i++)   
    { // mItems[i] = ito[i];
    mMess[i] = mso[i];  mSel[i] = slo[i]; }

  //  XtFree((char *)mItems);
  delete[] mso;
  delete[] slo;
  }

XmListDeletePos(mlist, n+1);
return;
}


/* --Methode-- */
bool PIListX::SelItem(int n, bool smg, bool cxw)
{
int i;

if ((n < 0) || (n > mNItem))  return(false);
if (mSel[n])  return(false);

mSel[n] = true;
if (mNbSel >= mNSelMax)
  {
  int * osel;
  osel = mSelNum;
  mNSelMax += NBISELB;
  mSelNum = new int[mNSelMax];
  for(i=0; i<mNbSel; i++)  mSelNum[i] = osel[i];
  if (osel)  delete[] osel;
  }

mSelNum[mNbSel] = n; 
mNbSel++;
if (smg)  
  Send(mMess[n], PIMsg_Select); 
if (cxw)
  XmListSelectPos(mlist, n+1, FALSE);
return(true);
}




/* --Methode-- */
bool PIListX::ClrSItem(int n, bool smg, bool cxw)
{
int i;
if ((n < 0) || (n > mNItem))  return(false);
if (!mSel[n])  return(false);
mSel[n] = false;

mNbSel --;
if (smg)  
  Send(mMess[n], PIMsg_ClearSel); 
if (cxw)
  XmListDeselectPos(mlist, n+1);

if (mSelNum) delete[] mSelNum;
if (mNbSel <= 0)
  { mNSelMax = mNbSel = 0;  mSelNum = NULL; }
else
  {
  mNSelMax = (mNbSel+NBISELB)/NBISELB;
  mSelNum = new int[mNSelMax];
  mNbSel =  0;
  for(i=0; i<mNItem; i++)
    if (mSel[i]) { mSelNum[mNbSel] = i; mNbSel++; }
  }

return(true);
} 


/* --Methode-- 
    A Supprimer .....
void PIListX::ChangeSel()
{
XmString *xmst;
int n;

n=0;
XtSetArg(warg[n], XmNselectedItems, &xmst);  n++;
XtGetValues(mlist, warg, n);
if (xmst)  XtFree(xmst);
xmst =  (XmString *) XtMalloc(sizeof(XmString)*mNbSel);
for(i=0; i<mNbSel; i++)
  xmst[i] = mItems[mSelNum[i]];
n=0;
XtSetArg(warg[n], XmNselectedItems, xmst);  n++;
XtSetArg(warg[n], XmNselectedItemCount, mNbSel);  n++;
XtSetValues(mlist, warg, n);
return;
}
   .....  */
