/*********************************************************************
 *
 *         EZWGL, the EZ Widget and Graphics Library
 *
 *             Copyright (C) 1996, 1997  Maorong Zou
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **********************************************************************/
/*
 *  June 1996.  Beta Release.
 *  Sept 1996.  Release Version 1.0
 *  Dec 1996.  Release Version 1.1 Beta
 *  April 1997.  Release Version 1.2
 *  November 1997.  Release Version 1.3
 */
/*****************************************************************
 ***                                                           ***
 ***              Widget Internal Fancy List Box               ***
 ***                                                           ***
 *****************************************************************/
#define _EZ_WIDGET_IFLIST_BOX_C_
#include "EZ_Widget.h"
#include <X11/Xatom.h>

/*********************************************************************
 * 
 *  Functions implemented in this file:
 */
EZ_Widget        *EZ_CreateIFListBox MY_ANSIARGS((EZ_Widget *parent, int ncols, int seltype));
void             EZ_DrawWidgetIFListBox MY_ANSIARGS((EZ_Widget *widget));
void             EZ_ComputeWidgetIFListBoxSize MY_ANSIARGS((EZ_Widget *widget, int *w, int *h));
void             EZ_FreeWidgetIFListBoxData MY_ANSIARGS((EZ_Widget *widget));
void             EZ_IFListBoxEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

void             EZ_SetIFListBoxData MY_ANSIARGS((EZ_Widget *widget, EZ_Item **items, int row, int col));
void             EZ_InsertIFListBoxRow  MY_ANSIARGS((EZ_Widget *widget, EZ_Item **items, int nitems, int where));
void             EZ_DeleteIFListBoxRow  MY_ANSIARGS((EZ_Widget *widget, int idx));
void             EZ_DeleteIFListBoxSomeRows MY_ANSIARGS((EZ_Widget *widget, int *idces, int cnt));
void             EZ_ReplaceIFListBoxItem  MY_ANSIARGS((EZ_Widget *widget, EZ_Item *old, EZ_Item *newItem));
void             EZ_ReplaceIFListBoxItemUsingIdx MY_ANSIARGS((EZ_Widget *widget, int row, int col, EZ_Item *newItem));
void             EZ_ClearIFListBox  MY_ANSIARGS((EZ_Widget *widget));
void             EZ_SetIFListBoxHeader  MY_ANSIARGS((EZ_Widget *widget, EZ_Item **elts, int nelts));

EZ_Item          **EZ_GetIFListBoxSelection  MY_ANSIARGS((EZ_Widget *widget));
EZ_Item          *EZ_GetIFListBoxItemUsingIdx  MY_ANSIARGS((EZ_Widget *widget, int row, int col));

int              EZ_FindPointerOnRowIFL  MY_ANSIARGS((EZ_Item ***array, int nrow, int ncol, int x, int y,
						      int Rx, int Ry, int RW, int RH));
void             EZ_FindPointerOnRowAndColIFL  MY_ANSIARGS((EZ_Item ***array, int nrow, int ncol, int x, int y,
							    int *rowR, int *colR, int Rx, int Ry, int RW, int RH));

void             EZ_FlashRowOutline MY_ANSIARGS((EZ_Widget *widget, EZ_Item **row, int nelts));
void             EZ_DnDOutlineRow MY_ANSIARGS((EZ_Widget *widget, EZ_Item **row, int nelts,
					       int Rx, int Ry, int Rw, int Rh));

void             EZ_IFListBoxSelectItemUsingIdx MY_ANSIARGS((EZ_Widget *widget, int Srow, int Scol, int *location));
void             EZ_IFListBoxSelectItem MY_ANSIARGS((EZ_Widget *widget, EZ_Item *item, int *location));
void             EZ_IFListBoxAllocNewStorage MY_ANSIARGS((EZ_Widget *widget,int rows, int cols));

/*********************************************************************
 * 
 * Local functions.
 */
static void   update_ifl_scrollbars MY_ANSIARGS((EZ_Widget *widget));
static void   IFTimerCallBack MY_ANSIARGS((EZ_Timer *timer, void *data));
static void   iflistbox_vscroll_update_selection MY_ANSIARGS((EZ_Widget *widget,
							      int sline, int nsline, int mode));
static void   iflistbox_hscroll_update_selection MY_ANSIARGS((EZ_Widget *widget,
							      int sline, int col, int ncol, int tt));
static void   EZ_IFListBoxSetSelection MY_ANSIARGS((EZ_Widget *widget));

static void   EZ_IFListBoxGrowStorage MY_ANSIARGS((EZ_Widget *widget, int count));
static void   EZ_IFListBoxFindItem MY_ANSIARGS((EZ_Widget *widget, EZ_Item *item, int *loc));
/*********************************************************************
 * 
 *  Local Variables.
 */
static EZ_WidgetHandle EZ_IFListBoxHandle =
{
  EZ_ComputeWidgetIFListBoxSize,
  EZ_DrawWidgetIFListBox,
  EZ_FreeWidgetIFListBoxData,
  EZ_IFListBoxEventHandle,
};

/*********************************************************************/

EZ_Widget  *EZ_CreateIFListBox(parent, ncolumns, selectionType)
     EZ_Widget  *parent;     /* parent widget    */
     int ncolumns;
     int selectionType;
{
  EZ_Widget  *wptr;

  wptr = EZ_CreateNewWidget(parent);
  EZ_WidgetHandlingFunctions[EZ_WIDGET_IFANCY_LIST_BOX] = &EZ_IFListBoxHandle;

  EZ_SetWidgetTypeAndNames(wptr,EZ_WIDGET_IFANCY_LIST_BOX);
  EZ_WidgetBorderStyle(wptr)  = EZ_BORDER_DOWN;
  EZ_WidgetBorderWidth(wptr)  = 2;
  EZ_WidgetPadX(wptr) = 1;
  EZ_WidgetPadY(wptr) = 1;
  EZ_WidgetPadB(wptr) = 2;

  EZ_IFListBoxColumns(wptr)  = (ncolumns < 1 ?  1 : (ncolumns > 100? 100: ncolumns));
  EZ_IFListBoxRows(wptr)     = 0;
  EZ_IFListBoxSpace(wptr)    = 0;
  EZ_IFListBoxSelectionIDX(wptr)  = -1;
  EZ_IFListBoxSelectionCol(wptr)  = -1;

  EZ_IFListBoxHighlightBG(wptr)   = ~0;
  EZ_IFListBoxHighlightFG(wptr)   = ~0;
  EZ_IFListBoxTextBG(wptr)        = ~0;
  EZ_IFListBoxXSize(wptr)         = 1;
  EZ_IFListBoxXPageSize(wptr)     = 1; 
  EZ_IFListBoxXStart(wptr)        = 0; 
  EZ_IFListBoxYSize(wptr)         = 1; 
  EZ_IFListBoxYPageSize(wptr)     = 1; 
  EZ_IFListBoxYStart(wptr)        = 0; 
  EZ_IFListBoxDirty(wptr)         = 1;
  EZ_IFListBoxDisplayed(wptr)     = 0;

  EZ_IFListBoxFListBox(wptr) = (EZ_Widget *)NULL;
  EZ_IFListBoxHScroll(wptr) = (EZ_Widget *)NULL;
  EZ_IFListBoxVScroll(wptr) = (EZ_Widget *)NULL;

  EZ_IFListBoxSelectionType(wptr)  = (selectionType != 0);
  
  EZ_CreateTimer(0,330000,-1, (EZ_CallBack)IFTimerCallBack, wptr, 0);

  EZ_IFListBoxHSizes(wptr) = (int *)NULL;
  EZ_IFListBoxVSizes(wptr) = (int *)NULL;
  EZ_IFListBoxData(wptr) = (EZ_Item ***)NULL;
  EZ_IFListBoxSpace(wptr) = 0;

  EZ_IFListBoxAllocNewStorage(wptr, 64, ncolumns);  

  EZ_SetWidgetFocusableFlag(wptr);  

  EZ_Insert2DnDWidgetList(wptr);
  EZ_WidgetDnDHandler(wptr) = (EZ_DnDMsgHandler)EZ_IFListBoxDnDHandle;
  
  return(wptr);
}

void  EZ_FreeWidgetIFListBoxData(widget)
     EZ_Widget *widget;
{
  int          i, j;
  int          ncolumns = EZ_IFListBoxColumns(widget);
  int          nrows = EZ_IFListBoxSpace(widget);
  EZ_Item      ***data= EZ_IFListBoxData(widget);

  for(i = 0; i < nrows; i++)
    {
      EZ_Item **items = data[i];
      for(j = 0; j < ncolumns; j++)
	{
	  if(items[j]) EZ_DestroyItem(items[j]);
	}
      (void) my_free((char *)items);
    }
  (void) my_free((char *)data);
  (void) my_free((char *)EZ_IFListBoxHSizes(widget));
  (void) my_free((char *)EZ_IFListBoxVSizes(widget));
}
 
/********************************************************************
 *
 *  Figure out the dimension of an internal list box.
 */
void EZ_ComputeWidgetIFListBoxSize(widget, w, h)
     EZ_Widget *widget;
     int             *w, *h;
{
  int cw, ch;

  if(!(EZ_GetWidgetSizeComputedFlag(widget)))
    { 
      EZ_SetWidgetSizeComputedFlag(widget);
    }
  cw = EZ_WidgetPadX(widget) + EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
  ch = EZ_WidgetPadY(widget) + EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
  cw = cw + cw + 30;
  ch = ch + ch + 30;

  EZ_IFListBoxXPageSize(widget)     = 30; 
  EZ_IFListBoxYPageSize(widget)     = 30; 

  *w = cw;
  *h = ch;
}

/****************************************************************************
 *
 *  Draw a IFListBox widget
 */
void  EZ_DrawWidgetIFListBox(wptr)
     EZ_Widget *wptr;
{
  int             w, h, bw, padb,padb2;
  Pixmap          pixmap;
  Window          win;
  GC              gc;
  unsigned long   bgpv;

  win = EZ_WidgetWindow(wptr);
  w   = EZ_WidgetWidth(wptr);
  h   = EZ_WidgetHeight(wptr);
  bw = EZ_WidgetBorderWidth(wptr);
  padb = EZ_WidgetPadB(wptr);
  padb2 = padb + padb;
  /*-----------------------------------------------------------
   *  Create a pixmap, draw into this pixmap.
   *----------------------------------------------------------*/
  pixmap = XCreatePixmap(EZ_Display, win, w, h, EZ_Depth);    
  /*  */
  {
    EZ_Bitmap *bitmap = EZ_WidgetPixmap(wptr);
    if(bitmap && EZ_BitmapType(bitmap) == EZ_BITMAP_IS_PIXMAP)
      {
	int xx = EZ_IFListBoxXStart(wptr);
	int yy = EZ_IFListBoxYStart(wptr);
	gc = EZ_TILEGC;
	XSetTile(EZ_Display,gc,bitmap->pixmap);
	XSetTSOrigin(EZ_Display, gc, xx,yy);
      }
    else if(EZ_IFListBoxTextBG(wptr) != ~0)
      {
	XSetForeground(EZ_Display, EZ_WRITABLEGC, EZ_IFListBoxTextBG(wptr));	
	gc = EZ_WRITABLEGC;
      }
    else EZ_GetBackgroundGC(wptr, &gc, &bgpv, 0, 0);
  }
  XFillRectangle(EZ_DisplayForWidgets, pixmap, gc, padb,padb, w -padb2, h-padb2); 

  /* display the lists */
  if(EZ_IFListBoxRows(wptr) > 0)
    {
      EZ_Item ***data = EZ_IFListBoxData(wptr);
      EZ_Item **row;
      int nitems = EZ_IFListBoxRows(wptr); 
      int ncolumns = EZ_IFListBoxColumns(wptr);
      int Wsize, Hsize, itmp;
      int bww =  EZ_WidgetBorderWidth(wptr) + EZ_WidgetPadB(wptr); 
      int xoff = bww + EZ_WidgetPadX(wptr);
      int yoff = bww + EZ_WidgetPadY(wptr);
      int vspacing = EZ_WidgetSepY(wptr);
      int x, y, i;
      int Rx = bww;
      int Ry = yoff;
      int Rw = w -(bww << 1);
      int Rh = h -(bww + yoff);
      
      int *hsa = EZ_IFListBoxHSizes(wptr);
      int *vsa = EZ_IFListBoxVSizes(wptr);

      if(EZ_IFListBoxDirty(wptr))
	{
	  EZ_ComputeItemArrayGeometry(data, nitems, ncolumns, &Wsize, &Hsize, hsa, vsa); 
	  itmp = Wsize + (ncolumns -1) * (int) EZ_WidgetSepX(wptr);
	  EZ_IFListBoxXSize(wptr) = (itmp + (xoff << 1));
	  itmp = Hsize + (nitems -1) * (int) EZ_WidgetSepY(wptr);
	  EZ_IFListBoxYSize(wptr) = (itmp + (yoff << 1));
	  EZ_IFListBoxDirty(wptr)= 0;
	  if(EZ_IFListBoxXStart(wptr) + EZ_IFListBoxXSize(wptr) <= 0)
	    {
	      int itmp = Rw -  EZ_IFListBoxXSize(wptr);
	      EZ_IFListBoxXStart(wptr) = (itmp > 0? 0: itmp);
	    }
	  if(EZ_IFListBoxYStart(wptr) + EZ_IFListBoxYSize(wptr) <= 0)
	    {
	      int itmp = Rh -  EZ_IFListBoxYSize(wptr);
	      EZ_IFListBoxYStart(wptr) = itmp > 0 ? 0: itmp;
	    }
	}
      EZ_IFListBoxXPageSize(wptr) = w;
      EZ_IFListBoxYPageSize(wptr) = h;
      
      x = EZ_IFListBoxXStart(wptr) + xoff;
      y = yoff;
      itmp = (int) EZ_WidgetSepX(wptr);
      
      /* check for header */
      row = data[0];
      if(row[0]) 
	{
	  y += vsa[0];
	  Ry +=  vsa[0];
	  Rh -=  vsa[0];  
	  /* EZ_IFListBoxYPageSize(wptr) -= vsa[0]; */
	}
      y += EZ_IFListBoxYStart(wptr);
      for(i = 1; i < nitems; i++)
	{
	  row = data[i];
	  EZ_DisplayOneRowOfItems(wptr, pixmap, row, ncolumns, x,y, itmp, hsa,
				  Rx,Ry,Rw,Rh);
	  y +=  vsa[i] + vspacing;
	}

      /* update the header !!! */
      row = data[0];
      if(row[0]) 
	{
	  x = EZ_IFListBoxXStart(wptr) + xoff;
	  y = yoff;
	  EZ_DisplayOneRowOfItems(wptr, pixmap, row, ncolumns, x,y, itmp, hsa,
				  Rx, yoff, Rw,Rh);
	}

      /* highlight selection */
      if(EZ_IFListBoxSelectionType(wptr))
	{
	  int sline = EZ_IFListBoxSelectionIDX(wptr);
	  if(sline > 0 && sline < nitems)
	    {
	      EZ_Item **row =  data[sline];
	      unsigned long fg = EZ_IFListBoxHighlightFG(wptr);
	      unsigned long bg = EZ_IFListBoxHighlightBG(wptr);
	      EZ_HighlightOneRow(wptr, pixmap, row,ncolumns,fg, bg,
				 Rx,Ry,Rw,Rh);
	    }
	}
      else
	{
	  int sline = EZ_IFListBoxSelectionIDX(wptr); 
	  int scol = EZ_IFListBoxSelectionCol(wptr);

	  if(sline > 0 && scol >= 0)
	    {
	      EZ_Item **row, *sitem;

	      row = (EZ_IFListBoxData(wptr))[sline];
	      sitem = row[scol];
	      if(sitem)
		{
		  unsigned long fg = EZ_IFListBoxHighlightFG(wptr);
		  unsigned long bg = EZ_IFListBoxHighlightBG(wptr);
		  EZ_HighlightOneItem(wptr, pixmap, sitem, fg, bg, Rx,Ry,Rw,Rh);
		}
	    }
	}
    }

  if(padb > 0)
    {
      EZ_GetParentBgGCN(wptr, &gc,&bgpv);
      XFillRectangle(EZ_Display, pixmap, gc, 0,0, w, padb);
      XFillRectangle(EZ_Display, pixmap, gc, 0,h-padb, w, padb);       
      XFillRectangle(EZ_Display, pixmap, gc, 0,padb, padb, h-padb2); 
      XFillRectangle(EZ_Display, pixmap, gc, w-padb,padb, padb, h-padb2); 
    }
  EZ_DrawRectBorder(wptr, pixmap);
  XCopyArea(EZ_Display,pixmap,win, EZ_WRITABLEGC,0,0,w,h,0,0); 
  XFreePixmap(EZ_DisplayForWidgets, pixmap); 

  update_ifl_scrollbars(wptr);

  if(EZ_IFListBoxDisplayed(wptr) == 0)
    {
      int srow = EZ_IFListBoxSelectionIDX(wptr);
      EZ_IFListBoxDisplayed(wptr) = 1;
      
      if( srow > 0)
	{
	  int smode = EZ_IFListBoxSelectionType(wptr);
	  iflistbox_vscroll_update_selection(wptr, srow, srow, smode);
	  if(smode == 0) 
	    {
	      int scol = EZ_IFListBoxSelectionCol(wptr);
	      iflistbox_hscroll_update_selection(wptr, srow, scol, scol, 0);
	    }
	  EZ_HandleMotionCallBacks(wptr,EZ_IFListBoxMotionCallBack(wptr));
	  /* EZ_IFListBoxSetSelection(wptr);*/
	}
    }
}
/*************************************************************************/
static void update_ifl_scrollbars(wptr)
     EZ_Widget *wptr;
{
  if(EZ_IFListBoxHScroll(wptr) != (EZ_Widget *)NULL)
    {
      EZ_UpdateScrollbarI(EZ_IFListBoxHScroll(wptr),
			  EZ_IFListBoxXSize(wptr),
			  EZ_IFListBoxXPageSize(wptr),
			  EZ_IFListBoxXStart(wptr));
    }

  if(EZ_IFListBoxVScroll(wptr) != (EZ_Widget *)NULL)
    {
      EZ_UpdateScrollbarI(EZ_IFListBoxVScroll(wptr),
			  EZ_IFListBoxYSize(wptr),
			  EZ_IFListBoxYPageSize(wptr),
			  -EZ_IFListBoxYStart(wptr));
    }
}
/*************************************************************************
 *
 *  Event handling
 */
void  EZ_IFListBoxEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent          *event;
{
  XEvent    xevent;
  int       x, y, bw, Rx,Ry,Rw,Rh, xoffset, yoffset, done,  smode;
  int       Ox=0, Oy=0, oldx=0, oldy=0, dx,dy, rootx, rooty,tx,ty,Sx,Sy, moved = 0;
  int       ix0, iy0, iww=1, ihh=1, iarea, snapshot = 0, grabed;
  int       sline, wox,woy;
  int       *vsa,ww,hh;
  EZ_Item   **nsitems = NULL, *nsitem = NULL;
  Window    root, child;
  unsigned  int    mask;

  if(event->type == Expose)   EZ_DrawWidget(widget);      
  if( EZ_GetWidgetDisabledFlag(widget) )  return;

  vsa = EZ_IFListBoxVSizes(widget);
  smode = EZ_IFListBoxSelectionType(widget); /* 0 for picking an item, 1 for picking a row */

  switch(event->type)
    {
    case SelectionRequest:
      EZ_HandleSelectionRequest(widget,event);
      break;
    case ButtonPress:
      /* first, get focus if we don;t have it */
      if(event->xbutton.button == EZ_Btn1) 	  /* get keyboard focus */
	{ 
	  Window fw; int rt;
	  EZ_Widget *tmp;
	  XGetInputFocus(EZ_Display, &fw, &rt);
	  tmp = EZ_LookupWidgetFromMappedHT(fw);
	  if(tmp != widget) EZ_SetFocusTo(widget);
	}
      if(EZ_IFListBoxRows(widget) <= 0) {return;}
      if(event->xbutton.button == EZ_Btn1)
	{
	  Time  time_stamp = event->xbutton.time;   
	  int   elapsedtime = EZ_LastButton1ClickTime - time_stamp; 
	  EZ_LastButton1ClickTime = time_stamp;

	  bw = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
	  xoffset = bw + EZ_WidgetPadX(widget);
	  yoffset = bw + EZ_WidgetPadY(widget);

	  Rx = bw;
	  Ry = yoffset + vsa[0];
	  ww = EZ_WidgetWidth(widget);
	  Rw = ww - (bw << 1);
	  hh = EZ_WidgetHeight(widget);
	  Rh = hh - bw - Ry;

	  x = event->xbutton.x;
	  y = event->xbutton.y;
	  if(smode)  
	    { /* a row a time */
	      sline = EZ_FindPointerOnRowIFL(EZ_IFListBoxData(widget), 
					  EZ_IFListBoxRows(widget), 
					  EZ_IFListBoxColumns(widget), 
					  x,y, Rx,Ry,Rw,Rh);

	      if(sline >=0 && sline != EZ_IFListBoxSelectionIDX(widget))
		{
		  int tline =  EZ_IFListBoxSelectionIDX(widget); 
		  if(tline > 0)
		    {
		      EZ_UpdateOneRow(widget, EZ_WidgetWindow(widget),
				      EZ_IFListBoxData(widget)[tline],
				      EZ_IFListBoxColumns(widget),
				      Rx,Ry,Rw,Rh);
		    }
		  EZ_IFListBoxSelectionIDX(widget) = sline;
		  {
		    EZ_Item **row =  EZ_IFListBoxData(widget)[sline];
		    unsigned long fg = EZ_IFListBoxHighlightFG(widget);
		    unsigned long bg = EZ_IFListBoxHighlightBG(widget);
		    EZ_HighlightOneRow(widget, EZ_WidgetWindow(widget), row, 
				       EZ_IFListBoxColumns(widget),fg, bg,
				       Rx,Ry,Rw,Rh);
		  }
		  EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
		  EZ_IFListBoxSetSelection(widget);
		}
	      /*
	       * a double click cause the execuation of the call back function
	       */
	      if(sline > 0 && ABSV(elapsedtime) < DOUBLE_CLICK_TIME_INTERVAL)
		{ 
		  EZ_Item *item, **items = EZ_IFListBoxData(widget)[sline];
		  int i, ncols =  EZ_IFListBoxColumns(widget);
		  for(i = 0; i < ncols; i++)
		    {
		      item = items[i];
		      if(item) {EZ_HandleItemCallBacks(item);}
		    }
		  EZ_ExecuteWidgetCallBacks(widget);
		  return;
		}

	      if(sline > 0)
		{
		  int i, ncols =  EZ_IFListBoxColumns(widget);
		  nsitems = EZ_IFListBoxData(widget)[sline];
		  for(i = 0; i < ncols; i++)
		    {
		      nsitem = nsitems[i];
		      if(nsitem) break;
		    }
		}
	      if(nsitem)
		{
		  int save_row = -1;
		  done = 0;
		  moved = 0;
		  while(!done)
		    {
		      do {
			XNextEvent(EZ_Display, &xevent); 	      
			if(EZ_FilterEvent(&xevent))
			  EZ_InvokePrivateEventHandler(&xevent);
			if(xevent.type == MotionNotify)
			  {
			    moved = 1; 
			    x = xevent.xmotion.x;
			    y = xevent.xmotion.y;
			  }
			else if(xevent.type == ButtonRelease)
			  {
			    if(xevent.xbutton.button == EZ_Btn1) { done = 1; break;}
			  }
			else if(xevent.type == Expose || xevent.type == FocusIn || xevent.type == FocusOut)
			  EZ_WidgetDispatchEvent(&xevent);
		      } while(XPending(EZ_Display) && !done) ;
		      
		      if(!done)
			{
			  if(moved)
			    { 
			      int tmp = EZ_FindPointerOnRowIFL(EZ_IFListBoxData(widget), 
							       EZ_IFListBoxRows(widget), 
							       EZ_IFListBoxColumns(widget), 
							       x,y, Rx,Ry,Rw,Rh);
			      if(tmp != save_row && tmp != EZ_IFListBoxSelectionIDX(widget))
				{
				  if(save_row >= 0)
				    EZ_UpdateOneRow(widget, EZ_WidgetWindow(widget),
						    EZ_IFListBoxData(widget)[save_row],
						    (int)EZ_IFListBoxColumns(widget),
						    Rx,Ry,Rw,Rh);
				  if(tmp >= 0) EZ_FlashRowOutline(widget, 
								  EZ_IFListBoxData(widget)[tmp],
								  (int)EZ_IFListBoxColumns(widget));
				  save_row = tmp;
				}
			    }
			}
		      else /* we are done */
			{
			  if(save_row >= 0) /* cannot be the current selection */
			    {
			      int tline = EZ_IFListBoxSelectionIDX(widget);
			      if(tline > 0)
				{
				  EZ_UpdateOneRow(widget, EZ_WidgetWindow(widget),
						  EZ_IFListBoxData(widget)[tline],
						  EZ_IFListBoxColumns(widget),
						  Rx,Ry,Rw,Rh);
				}
			      EZ_IFListBoxSelectionIDX(widget) = save_row;
			      {
				EZ_Item **row =  EZ_IFListBoxData(widget)[save_row];
				unsigned long fg = EZ_IFListBoxHighlightFG(widget);
				unsigned long bg = EZ_IFListBoxHighlightBG(widget);
				EZ_HighlightOneRow(widget, EZ_WidgetWindow(widget), row, 
						   EZ_IFListBoxColumns(widget),fg, bg,
						   Rx,Ry,Rw,Rh);
			      }
			      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
			      EZ_IFListBoxSetSelection(widget);
			    }
			}
		    } /* while */
		}
	      else /* not on a row, scroll */
		{
		  done = 0;
		  xevent.type = 0;
		  while(!done)
		    {
		      if(XPending(EZ_Display))
			{
			  while(XPending(EZ_Display))
			    {
			      if(xevent.type == MotionNotify)
				{
				  x = xevent.xmotion.x;
				  y = xevent.xmotion.y;
				}
			      else if(xevent.type == ButtonRelease)
				{
				  if( xevent.xbutton.button == EZ_Btn1) break;
				}
			      else if(xevent.type == Expose || xevent.type == FocusIn || xevent.type == FocusOut)
				EZ_WidgetDispatchEvent(&xevent);
			      XNextEvent(EZ_Display, &xevent);
			      if(EZ_FilterEvent(&xevent))
				EZ_InvokePrivateEventHandler(&xevent);
			    }
			}
		      else { EZ_SitForALittleBit(50000); }
		      if(xevent.type == ButtonRelease && xevent.xbutton.button == EZ_Btn1) {done = 1; break;}
		      if( x < xoffset || x > ww - xoffset || y <= yoffset + vsa[0] || y > hh - yoffset)
			{
			  if(y <= yoffset + vsa[0])
			    {
			      /* scroll down */
			      if(EZ_IFListBoxYStart(widget) < 0)
				{
				  int tmp = EZ_IFListBoxYStart(widget) + 10;
				  EZ_IFListBoxYStart(widget) = (tmp < 0 ? tmp: 0);
				  EZ_DrawWidget(widget);
				}
			    }
			  else if( y > hh - yoffset)
			    {
			      /* scroll up */ 
			      int  th = EZ_IFListBoxYSize(widget);
			      if(th > hh)
				{
				  int dif = hh - th;
				  int tmp = EZ_IFListBoxYStart(widget) - 10;
				  EZ_IFListBoxYStart(widget) = (tmp > dif ? tmp: dif);
				  EZ_DrawWidget(widget);				  
				}
			    }
			  else if(x < xoffset)
			    {
			      /* scroll right */
			      if(EZ_IFListBoxXStart(widget) < 0)
				{
				  int tmp = EZ_IFListBoxXStart(widget) + 10;
				  EZ_IFListBoxXStart(widget) = (tmp < 0 ? tmp: 0);
				  EZ_DrawWidget(widget);
				}
			    }
			  else if( x > ww - xoffset)
			    {
			      /* scroll left */ 
			      int  tw = EZ_IFListBoxXSize(widget);
			      if(tw > ww)
				{
				  int dif = ww - tw;
				  int tmp = EZ_IFListBoxXStart(widget) - 10;
				  EZ_IFListBoxXStart(widget) = (tmp > dif ? tmp: dif);
				  EZ_DrawWidget(widget);				  
				}
			    }
			}
		    } /* done scrolling */		  		  
		}
	    }
	  else /* one item a time */
	    {
	      int rowN, colN;
	      EZ_FindPointerOnRowAndColIFL(EZ_IFListBoxData(widget), 
					EZ_IFListBoxRows(widget), 
					EZ_IFListBoxColumns(widget), 
					x,y, &rowN, &colN,
					Rx,Ry,Rw,Rh);
	      
	      if(rowN > 0 && colN >= 0)
		{
		  EZ_Item ***data, **row, *sitem = NULL;
		  int sline = EZ_IFListBoxSelectionIDX(widget);
		  int col =  EZ_IFListBoxSelectionCol(widget);
		  data = EZ_IFListBoxData(widget);
		  if(sline > 0 && col >= 0)
		    {
		      row = data[sline];
		      sitem = row[col];
		    }
		  if(sline != rowN || col != colN)
		    {
		      EZ_IFListBoxSelectionIDX(widget) = rowN;
		      EZ_IFListBoxSelectionCol(widget) = colN;
		      if(sitem) EZ_UpdateOneItem(widget,EZ_WidgetWindow(widget),sitem, Rx,Ry,Rw,Rh);
		      {
			unsigned long fg = EZ_IFListBoxHighlightFG(widget);
			unsigned long bg = EZ_IFListBoxHighlightBG(widget);
			row = data[rowN];
			sitem = row[colN];
			if(sitem) EZ_HighlightOneItem(widget, EZ_WidgetWindow(widget),
						      sitem, fg, bg, Rx,Ry,Rw,Rh);
		      }
		      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
		      EZ_IFListBoxSetSelection(widget);
		    }
		  /*
		   * a double click cause the execuation of the call back function
		   */
		  if(sitem && ABSV(elapsedtime) < DOUBLE_CLICK_TIME_INTERVAL)
		    { 
		      /* EZ_Widget *fl = EZ_IFListBoxFListBox(widget);*/
		      EZ_HandleItemCallBacks(sitem);
		      EZ_ExecuteWidgetCallBacks(widget);
		      /* if(fl) {EZ_ExecuteWidgetCallBacks(fl);}*/
		      return;
		    }
		  nsitem = sitem;
		  /* to make gcc happy */
		  {	Ox = Oy = 0; oldx = oldy = 1; iww = ihh = 1; }
		  
		  if(nsitem)
		    {
		      int save_row = -1, save_col = -1;
		      done = 0;
		      moved = 0;
		      while(!done)
			{
			  do {
			    XNextEvent(EZ_Display, &xevent); 	      
			    if(EZ_FilterEvent(&xevent))
			      EZ_InvokePrivateEventHandler(&xevent);
			    if(xevent.type == MotionNotify)
			      {
				moved = 1; 
				x = xevent.xmotion.x;
				y = xevent.xmotion.y;
			      }
			    else if(xevent.type == ButtonRelease)
			      {
				if(xevent.xbutton.button == EZ_Btn1) { done = 1; break;}
			      }
			    else if(xevent.type == Expose || xevent.type == FocusIn || xevent.type == FocusOut) 
			      EZ_WidgetDispatchEvent(&xevent);
			  } while(XPending(EZ_Display) && !done) ;
			  
			  if(!done)
			    {
			      if(moved)
				{ 
				  int rowN, colN;
				  EZ_FindPointerOnRowAndColIFL(EZ_IFListBoxData(widget), 
							       EZ_IFListBoxRows(widget), 
							       EZ_IFListBoxColumns(widget), 
							       x,y, &rowN, &colN,
							       Rx,Ry,Rw,Rh);
				  if( (rowN != save_row || colN != save_col) &&
				     (rowN != (int) EZ_IFListBoxSelectionIDX(widget) ||
				      colN != (int)EZ_IFListBoxSelectionCol(widget)))
				    {
				      if(save_row > 0 && save_col >= 0)
					{
					  EZ_Item ***data, **row, *item = NULL;
					  data = EZ_IFListBoxData(widget);
					  row = data[save_row];
					  item = row[save_col];
					  EZ_UpdateOneItem(widget,EZ_WidgetWindow(widget),item, Rx,Ry,Rw,Rh);
					}
				      if(rowN > 0 && colN >= 0)
					{
					  EZ_Item ***data, **row, *item = NULL;
					  data = EZ_IFListBoxData(widget);
					  row = data[rowN];
					  item = row[colN];
					  EZ_FlashItemOutline(widget,item, Rx,Ry,Rw,Rh);
					}
				      save_row = rowN; save_col = colN;
				    }
				}
			    }
			  else /* we are done */
			    {
			      if(save_row > 0 && save_col >= 0) /* cannot be the current selection */
				{
				  int rowN = (int)EZ_IFListBoxSelectionIDX(widget);
				  int colN = (int)EZ_IFListBoxSelectionCol(widget);
				  
				  if(rowN > 0 && colN >= 0)
				    {
				      EZ_Item ***data, **row, *item = NULL;
				      data = EZ_IFListBoxData(widget);
				      row = data[rowN];
				      item = row[colN];
				      EZ_UpdateOneItem(widget,EZ_WidgetWindow(widget),item, Rx,Ry,Rw,Rh);
				    }
				  EZ_IFListBoxSelectionIDX(widget) = save_row;
				  EZ_IFListBoxSelectionCol(widget) = save_col;
				  {
				    EZ_Item **row =  EZ_IFListBoxData(widget)[save_row];
				    EZ_Item *item = row[save_col];
				    unsigned long fg = EZ_IFListBoxHighlightFG(widget);
				    unsigned long bg = EZ_IFListBoxHighlightBG(widget);
				    EZ_HighlightOneItem(widget,EZ_WidgetWindow(widget),item,fg,bg, Rx, Ry, Rw, Rh);
				  }
				  EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
				  EZ_IFListBoxSetSelection(widget);
				}
			    }
			} /* while */
		    } 
		}
	      else /* click is on the background */
		{
		  done = 0;
		  xevent.type = 0;
		  while(!done)
		    {
		      if(XPending(EZ_Display))
			{
			  while(XPending(EZ_Display))
			    {
			      if(xevent.type == MotionNotify)
				{
				  x = xevent.xmotion.x;
				  y = xevent.xmotion.y;
				}
			      else if(xevent.type == ButtonRelease)
				{
				  if( xevent.xbutton.button == EZ_Btn1) break;
				}
			      else if(xevent.type == Expose || xevent.type == FocusIn || xevent.type == FocusOut)  
				EZ_WidgetDispatchEvent(&xevent);
			      XNextEvent(EZ_Display, &xevent);
			      if(EZ_FilterEvent(&xevent))
				EZ_InvokePrivateEventHandler(&xevent);
			    }
			}
		      else { EZ_SitForALittleBit(50000); }
		      if(xevent.type == ButtonRelease && xevent.xbutton.button == EZ_Btn1) {done = 1; break;}
		      if( x < xoffset || x > ww - xoffset || y <= yoffset + vsa[0] || y > hh - yoffset)
			{
			  if(y <= yoffset + vsa[0])
			    {
			      /* scroll down */
			      if(EZ_IFListBoxYStart(widget) < 0)
				{
				  int tmp = EZ_IFListBoxYStart(widget) + 10;
				  EZ_IFListBoxYStart(widget) = (tmp < 0 ? tmp: 0);
				  EZ_DrawWidget(widget);
				}
			    }
			  else if( y > hh - yoffset)
			    {
			      /* scroll up */ 
			      int  th = EZ_IFListBoxYSize(widget);
			      if(th > hh)
				{
				  int dif = hh - th;
				  int tmp = EZ_IFListBoxYStart(widget) - 10;
				  int nOff = (tmp > dif ? tmp: dif);
				  if( EZ_IFListBoxYStart(widget) != nOff)
				    {
				      EZ_IFListBoxYStart(widget) = nOff;
				      EZ_DrawWidget(widget);		
				    }		  
				}
			    }
			  else if(x < xoffset)
			    {
			      /* scroll right */
			      if(EZ_IFListBoxXStart(widget) < 0)
				{
				  int tmp = EZ_IFListBoxXStart(widget) + 10;
				  EZ_IFListBoxXStart(widget) = (tmp < 0 ? tmp: 0);
				  EZ_DrawWidget(widget);
				}
			    }
			  else if( x > ww - xoffset)
			    {
			      /* scroll left */ 
			      int  tw = EZ_IFListBoxXSize(widget);
			      if(tw > ww)
				{
				  int dif = ww - tw;
				  int tmp = EZ_IFListBoxXStart(widget) - 10;
				  int nOff = (tmp > dif ? tmp: dif);
				  if(EZ_IFListBoxXStart(widget) !=  nOff)
				    {
				      EZ_IFListBoxXStart(widget) = nOff;
				      EZ_DrawWidget(widget);		
				    }		  
				}
			    }
			}
		    } /* done scrolling */		  		  
		}
	    }
	}
      else if(event->xbutton.button == EZ_Btn3)
	{
	  Window ptWin = event->xbutton.window;
	  Window oldPtWin = ptWin;
	  Window widgetwin = ptWin;
	  unsigned int actionType = (event->xbutton.state) & (ShiftMask | ControlMask | Mod1Mask);
	  int dragCancelled = 0;
	  int helpRequested = 0;
	  bw = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
	  xoffset = bw + EZ_WidgetPadX(widget);
	  yoffset = bw + EZ_WidgetPadY(widget);

	  Rx = bw;
	  Ry = yoffset + vsa[0];
	  ww = EZ_WidgetWidth(widget);
	  Rw = ww - (bw << 1);
	  hh = EZ_WidgetHeight(widget);
	  Rh = hh - bw - Ry;

	  x = event->xbutton.x;
	  y = event->xbutton.y;

	  if(smode)  
	    { /* a row a time */
	      sline = EZ_FindPointerOnRowIFL(EZ_IFListBoxData(widget), 
					  EZ_IFListBoxRows(widget), 
					  EZ_IFListBoxColumns(widget), 
					  x,y, Rx,Ry,Rw,Rh);

	      if(sline >=0 && sline != EZ_IFListBoxSelectionIDX(widget))
		{
		  int tline =  EZ_IFListBoxSelectionIDX(widget); 
		  if(tline > 0)
		    {
		      EZ_UpdateOneRow(widget, widgetwin,
				      EZ_IFListBoxData(widget)[tline],
				      EZ_IFListBoxColumns(widget),
				      Rx,Ry,Rw,Rh);
		    }
		  EZ_IFListBoxSelectionIDX(widget) = sline;
		  {
		    EZ_Item **row =  EZ_IFListBoxData(widget)[sline];
		    unsigned long fg = EZ_IFListBoxHighlightFG(widget);
		    unsigned long bg = EZ_IFListBoxHighlightBG(widget);
		    EZ_HighlightOneRow(widget, widgetwin, row, 
				       EZ_IFListBoxColumns(widget),fg, bg,
				       Rx,Ry,Rw,Rh);
		  }
		  EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
		  EZ_IFListBoxSetSelection(widget); 
		}
	  
	      if(sline > 0)
		{
		  int i, ncols =  EZ_IFListBoxColumns(widget);
		  nsitems = EZ_IFListBoxData(widget)[sline];
		  for(i = 0; i < ncols; i++)
		    {
		      nsitem = nsitems[i];
		      if(nsitem) break;
		    }
		}
	      if(nsitem)
		{
		  if( EZ_ItemIsDnDSrc(nsitem))
		    {
		      unsigned long serial = 0L;
		      int newEvent = 0;
		      done = 0;
		      moved = 0;
		      grabed = 0;
		      while(!done)
			{
			  while(XPending(EZ_Display) && !done)
			    {
			      XNextEvent(EZ_Display, &xevent); 
			      if(EZ_FilterEvent(&xevent))
				EZ_InvokePrivateEventHandler(&xevent);
			      newEvent = 1;
			      
			      if(xevent.type == MotionNotify)
				{
				  moved = 1;
				  serial = xevent.xmotion.serial;
				  ptWin = xevent.xmotion.window; 
				  if(xevent.xmotion.window == widgetwin)
				    {
				      if(xevent.xmotion.x < 0 ||  xevent.xmotion.y < 0 ||
					 xevent.xmotion.x >= EZ_WidgetWidth(widget) ||  
					 xevent.xmotion.y >= EZ_WidgetHeight(widget))
					ptWin = 0L;
				    }
				  if(helpRequested)
				    {
				      EZ_DnDSendCancelHelpMsg();
				      EZ_DnDInfo.ptWin = (unsigned long)ptWin;
				      helpRequested = 0;
				    }
				}
			      else if(xevent.type == ButtonRelease)
				{
				  if(xevent.xbutton.button == EZ_Btn3) 
				    {
				      ptWin = xevent.xbutton.window; 
				      if(xevent.xbutton.window == widgetwin)
					{
					  if(xevent.xbutton.x < 0 ||  xevent.xbutton.y < 0 ||
					     xevent.xbutton.x >= EZ_WidgetWidth(widget) ||  
					     xevent.xbutton.y >= EZ_WidgetHeight(widget))
					    ptWin = 0L;
					}
				      done = 1; 
				      break;
				    }
				}
			      else if(xevent.type == KeyPress)
				{
				  KeySym            keysym;
				  XComposeStatus    compose; 
				  char              tmpbuffer[4];
				  int               count;
				  count = XLookupString(&(xevent.xkey), tmpbuffer, 4, &keysym, &compose);
				  switch(keysym)
				    {
				    case XK_F1: 
#ifdef XK_KP_F1
				    case XK_KP_F1:  /* help */
#endif
				      if(grabed && helpRequested == 0 && ptWin != 0)
					{
					  EZ_DnDSendRequestHelpMsg();
					  EZ_DnDInfo.ptWin = (unsigned long)ptWin;
					  helpRequested = 1;
					}
				      break;
				    case XK_Escape:   /* cancel */
				      {
					dragCancelled = 1;
					done = 1;
				      }
				    break;
				    default:
				      break;
				    }
				}
			      else if(xevent.type == Expose || xevent.type == FocusIn || xevent.type == FocusOut)  
				EZ_WidgetDispatchEvent(&xevent);
			      if(oldPtWin != ptWin)
				{
				  if(grabed && oldPtWin != 0)
				    {
				      unsigned long twin = EZ_DnDInfo.ptWin;
				      EZ_DnDInfo.ptWin = (unsigned long)(oldPtWin);
				      EZ_DnDSendLeaveWindowMsg();
				      EZ_DnDInfo.ptWin = twin;
				    }
				  oldPtWin = ptWin;
				}
			    }
			  if(newEvent == 0)
			    {
			      EZ_CheckDnDTimer();
			      EZ_SitForALittleBit(1000);
			    }
			  
			  if(!done && newEvent) /* not done yet */
			    {
			      newEvent = 0;
			      if(moved)
				{
				  if(grabed == 0)  /* pointer moved, start drag */
				    {
				      XTranslateCoordinates(EZ_Display, widgetwin,
							    RootWindow(EZ_Display, EZ_ScreenNum),
							    0, 0,
							    &wox,&woy, &child);
				      ix0 = Rx + 1;
				      iy0 = EZ_ItemOriginY(nsitem);
				      ihh = EZ_ItemAHeight(nsitem);
				      iww = Rw - 2;
				      iarea  = iww * ihh;
				      
				      tx = ix0 - x;
				      ty = iy0 - y;
				      oldx = wox + x;
				      oldy = woy + y;
				      Sx = Ox = oldx + tx;
				      Sy = Oy = oldy + ty;
				
				      EZ_InitDrag(serial, EZ_DND_OBJ_IS_ITEM, widgetwin,
						  widget, nsitem, Sx,Sy, iww, ihh, oldx, oldy, tx, ty);      

				      if(EZ_DnDInfo.id == serial)
					{
					  Cursor cursor = EZ_ItemDnDDragCursor(nsitem);
					  if(cursor != (Cursor ) NULL)
					    { 
					      snapshot = EZ_DND_DRAG_ICON_CURSOR;
					      EZ_DnDInfo.cursor = cursor;
					    }
					  else if(iarea < 40000)
					    snapshot = EZ_MakeSnapShot(widget,1,ix0,iy0,iww,ihh);
					  else snapshot = EZ_DND_DRAG_ICON_OUTLINE;
					  {
					    EZ_DnDInfo.actionType = actionType;
					    EZ_DnDInfo.px = oldx;
					    EZ_DnDInfo.py = oldy;
					    EZ_DnDInfo.dragIconType = snapshot;
					    {
					      char *smsg; int smsg_len;
					      EZ_GenerateDragStartedMessage(&smsg, &smsg_len);
					      EZ_BroadcastDnDMessage(EZ_DND_DRAG_START,smsg, smsg_len, 0);
					    }
					    /*EZ_BroadcastDnDMessage(EZ_DND_DRAG_START,NULL, 0, 0);*/
					  }
					  if(EZ_PointerGrabed == 0)  /* grab the pointer ! */
					    {
					      if(XGrabPointer(EZ_Display,widgetwin, True,
							      ButtonReleaseMask|ButtonPressMask|PointerMotionMask,
							      GrabModeAsync, GrabModeAsync, None,
							      (cursor == (Cursor)NULL)?None:cursor, CurrentTime)
						 == GrabSuccess) EZ_PointerGrabed = 1;
					    }	
					  grabed = 1;
					}
				    }
				  if(grabed)
				    {
				      XQueryPointer(EZ_Display, RootWindow(EZ_Display, EZ_ScreenNum),
						    &root,       /* root return win */
						    &child,      /* child ret win   */
						    &rootx, &rooty,   /* x, y in root    */
						    &tx,&ty,            /* x, y in win     */
						    &mask);  
				      dx = rootx - oldx;  dy = rooty - oldy;
				      oldx = rootx;   oldy = rooty;
				  
				      if(dx | dy)
					{
					  Ox += dx; Oy += dy;
					  if(snapshot != EZ_DND_DRAG_ICON_CURSOR)
					    EZ_MoveSnapShotOrOutline(snapshot, Ox, Oy, iww, ihh, 1);
					  EZ_DnDInfo.px = oldx;
					  EZ_DnDInfo.py = oldy;
					  EZ_DnDInfo.ptWin = (unsigned long)ptWin;
					  EZ_BroadcastDnDMessage(EZ_DND_DRAG_MOTION, NULL, 0, 0);
					  if(snapshot != EZ_DND_DRAG_ICON_CURSOR)
					    EZ_MoveSnapShotOrOutline(snapshot, Ox, Oy, iww, ihh, 0);
					}
				    }
				}/* moved */
			    } /* not done */
			  else if(done) /* done */
			    {
			      if(EZ_PointerGrabed)
				{
				  XUngrabPointer(EZ_Display,CurrentTime);
				  EZ_PointerGrabed = 0;
				}
			      if(grabed) /* dragged */
				{
				  char *message;
				  int length;
				  Window commWin;

				  if(snapshot != EZ_DND_DRAG_ICON_CURSOR)				  
				    EZ_MoveSnapShotOrOutline(snapshot, 0,0,0,0,1);
				  if(ptWin != 0) commWin = (Window) EZ_WindowIsDnDTarget(ptWin);
				  else commWin = 0L;
				  EZ_FinishDrag(commWin, ptWin, oldx, oldy); /* prepare for drop */

				  if(commWin != 0L)
				    {
				      if(helpRequested)
					{
					  EZ_DnDSendCancelHelpMsg();
					  helpRequested = 0;
					}
				      
				      if(dragCancelled == 0)
					{
					  EZ_DnDInfo.actionType = actionType;
					  EZ_GenerateDragIsDropedMessage(&message, &length);
					  EZ_SendDnDMessage(EZ_DND_DRAG_DROPPED, message, length, 1);
					}
				      else  /* cancelled */
					{
					  EZ_SendDnDMessage(EZ_DND_DRAG_CANCELLED, NULL, 0, 0);
					  EZ_AbortDrag();
					}
				    }	
				  else if(ptWin == RootWindow(EZ_Display, EZ_ScreenNum) &&
					  dragCancelled == 0)
				    {
				      /* drop to the root window, handle this internally */
				      EZ_DnDDataEncoder  *encoder = EZ_FindSpecialEncoder();
				      if(encoder)
					{
					  char *msg; int mlen, needFree, ok = EZ_DND_FAILURE;
					  
					  EZ_DnDInfo.srcStatus = EZ_DRAG_CONVERTING;
					  ok = (encoder->encoder) (encoder->object,
								   encoder->data,
								   &msg, &mlen, &needFree);
					  if(ok != EZ_DND_FAILURE)
					    {
					      if((encoder->callback).callback)
						{
						  EZ_DnDInfo.srcStatus = EZ_DRAG_EXECUTING_CALLBACK;
						  ((encoder->callback).callback)(encoder->object, 
										 (encoder->callback).data);
						}
					      EZ_DnDInfo.id = 0; /* forget about this drag */   
					    }
					  else EZ_AbortDrag();
					}
				      else  EZ_AbortDrag();
				    }
				  else    EZ_AbortDrag();
				}
			    }
			} /* while */
		    }  /* item is a drag src */
		}
	    }
	  else /* one item a time */
	    {
	      int rowN, colN;
	      EZ_FindPointerOnRowAndColIFL(EZ_IFListBoxData(widget), 
					EZ_IFListBoxRows(widget), 
					EZ_IFListBoxColumns(widget), 
					x,y, &rowN, &colN,
					Rx,Ry,Rw,Rh);
	      
	      if(rowN > 0 && colN >= 0)
		{
		  EZ_Item ***data, **row, *sitem = NULL;
		  int sline = EZ_IFListBoxSelectionIDX(widget);
		  int col =  EZ_IFListBoxSelectionCol(widget);
		  data = EZ_IFListBoxData(widget);
		  if(sline > 0 && col >= 0)
		    {
		      row = data[sline];
		      sitem = row[col];
		    }
		  if(sline != rowN || col != colN)
		    {
		      EZ_IFListBoxSelectionIDX(widget) = rowN;
		      EZ_IFListBoxSelectionCol(widget) = colN;
		      if(sitem) EZ_UpdateOneItem(widget,widgetwin,sitem, Rx,Ry,Rw,Rh);
		      {
			unsigned long fg = EZ_IFListBoxHighlightFG(widget);
			unsigned long bg = EZ_IFListBoxHighlightBG(widget);
			row = data[rowN];
			sitem = row[colN];
			if(sitem) EZ_HighlightOneItem(widget, widgetwin,
						      sitem, fg, bg, Rx,Ry,Rw,Rh);
		      }
		      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
		      EZ_IFListBoxSetSelection(widget);
		    }
		  nsitem = sitem;
		  /* to make gcc happy */
		  {	Ox = Oy = 0; oldx = oldy = 1; iww = ihh = 1; }
		  
		  if(nsitem)
		    {
		      if( EZ_ItemIsDnDSrc(nsitem))
			{
			  unsigned long serial = 0L;
			  int newEvent = 0;
			  done = 0;
			  moved = 0;
			  grabed = 0;
			  while(!done)
			    {
			      while(XPending(EZ_Display) && !done)
				{
				  XNextEvent(EZ_Display, &xevent); 
				  if(EZ_FilterEvent(&xevent))
				    EZ_InvokePrivateEventHandler(&xevent);
				  newEvent = 1;
				  
				  if(xevent.type == MotionNotify) 
				    {
				      moved = 1; 
				      serial = xevent.xmotion.serial; 
				      ptWin = xevent.xmotion.window; 
				      if(xevent.xmotion.window == widgetwin)
					{
					  if(xevent.xmotion.x < 0 ||  xevent.xmotion.y < 0 ||
					     xevent.xmotion.x >= EZ_WidgetWidth(widget) ||  
					     xevent.xmotion.y >= EZ_WidgetHeight(widget))
					    ptWin = 0L;
					}
				      if(helpRequested)
					{
					  EZ_DnDSendCancelHelpMsg();
					  EZ_DnDInfo.ptWin = (unsigned long)ptWin;
					  helpRequested = 0;
					}
				    }
				  else if(xevent.type == ButtonRelease)
				    {
				      if(xevent.xbutton.button == EZ_Btn3) 
					{
					  ptWin = xevent.xbutton.window; 					
					  if(xevent.xbutton.window == widgetwin)
					    {
					      if(xevent.xbutton.x < 0 ||  xevent.xbutton.y < 0 ||
						 xevent.xbutton.x >= EZ_WidgetWidth(widget) ||  
						 xevent.xbutton.y >= EZ_WidgetHeight(widget))
						ptWin = 0L;
					    }
					  done = 1;
					  break;
					}
				    }
				  else if(xevent.type == KeyPress)
				    {
				      KeySym            keysym;
				      XComposeStatus    compose; 
				      char              tmpbuffer[4];
				      int               count;
				      count = XLookupString(&(xevent.xkey), tmpbuffer, 4, &keysym, &compose);
				      switch(keysym)
					{
					case XK_F1: 
#ifdef XK_KP_F1
					case XK_KP_F1:  /* help */
#endif
					  if(grabed && helpRequested == 0 && ptWin != 0)
					    {
					      EZ_DnDInfo.ptWin = (unsigned long)ptWin;
					      EZ_DnDSendRequestHelpMsg();
					      helpRequested = 1;
					    }
					  break;
					case XK_Escape:   /* cancel */
					  {
					    dragCancelled = 1;
					    done = 1;
					  }
					break;
					default:
					  break;
					}
				    }
				  else if(xevent.type == Expose || xevent.type == FocusIn || xevent.type == FocusOut)  
				    EZ_WidgetDispatchEvent(&xevent);

				  if(oldPtWin != ptWin)
				    {
				      if(grabed && oldPtWin != 0)
					{
					  unsigned long twin = EZ_DnDInfo.ptWin;
					  EZ_DnDInfo.ptWin = (unsigned long)(oldPtWin);
					  EZ_DnDSendLeaveWindowMsg();
					  EZ_DnDInfo.ptWin = twin;
					}
				      oldPtWin = ptWin;
				    }
				}
			      if(newEvent == 0)
				{
				  EZ_CheckDnDTimer();
				  EZ_SitForALittleBit(1000);
				}
		      
			      if(!done && newEvent) /* not done yet */			      
				{
				  newEvent = 0;
				  if(moved)
				    {
				      if(grabed == 0)  /* pointer moved, start drag */
					{
					  XTranslateCoordinates(EZ_Display, widgetwin,
								RootWindow(EZ_Display, EZ_ScreenNum),
								0, 0,
								&wox,&woy, &child);
					  
					  ix0 = EZ_ItemOriginX(nsitem);
					  iy0 = EZ_ItemOriginY(nsitem);
					  iww = EZ_ItemAWidth(nsitem);
					  ihh = EZ_ItemAHeight(nsitem);
					  iarea  = iww * ihh;
					  
					  tx = ix0 - x;
					  ty = iy0 - y;
					  oldx = wox + x;
					  oldy = woy + y;
					  Sx = Ox = oldx + tx;
					  Sy = Oy = oldy + ty;

					  EZ_InitDrag(serial, EZ_DND_OBJ_IS_ITEM, widgetwin,
						      widget, nsitem, Sx,Sy, iww, ihh, oldx, oldy, tx, ty);
					  if(EZ_DnDInfo.id == serial)
					    {  
					      Cursor cursor = EZ_ItemDnDDragCursor(nsitem);
					      if(cursor != (Cursor ) NULL)
						{ 
						  snapshot = EZ_DND_DRAG_ICON_CURSOR;
						  EZ_DnDInfo.cursor = cursor;
						}
					      else if(iarea < 40000)
						snapshot = EZ_MakeSnapShot(widget,1,ix0,iy0,iww,ihh);
					      else snapshot = EZ_DND_DRAG_ICON_OUTLINE;
					      {
						EZ_DnDInfo.actionType = actionType;
						EZ_DnDInfo.px = oldx;
						EZ_DnDInfo.py = oldy;
						EZ_DnDInfo.dragIconType = snapshot;
						{
						  char *smsg; int smsg_len;
						  EZ_GenerateDragStartedMessage(&smsg, &smsg_len);
						  EZ_BroadcastDnDMessage(EZ_DND_DRAG_START,smsg, smsg_len, 0);
						}
						/*EZ_BroadcastDnDMessage(EZ_DND_DRAG_START,NULL, 0, 0);*/
					      }
					      if(EZ_PointerGrabed == 0)  /* grab the pointer ! */
						{
						  if(XGrabPointer(EZ_Display,widgetwin, True,
								  ButtonReleaseMask|ButtonPressMask|
								  PointerMotionMask,
								  GrabModeAsync, GrabModeAsync, None, 
								  (cursor == (Cursor)NULL)?None: cursor, CurrentTime)
						     == GrabSuccess) EZ_PointerGrabed = 1;
						}	
					      grabed = 1;
					    }
					}
				      if(grabed)
					{
					  XQueryPointer(EZ_Display, RootWindow(EZ_Display, EZ_ScreenNum),
							&root,       /* root return win */
							&child,      /* child ret win   */
							&rootx, &rooty,   /* x, y in root    */
							&tx,&ty,            /* x, y in win     */
							&mask);  
					  dx = rootx - oldx;  dy = rooty - oldy;
					  oldx = rootx;   oldy = rooty;
					  if(dx | dy)
					    {
					      Ox += dx; Oy += dy;
					      if(snapshot != EZ_DND_DRAG_ICON_CURSOR)
						EZ_MoveSnapShotOrOutline(snapshot, Ox, Oy, iww, ihh, 1);
					      EZ_DnDInfo.px = oldx;
					      EZ_DnDInfo.py = oldy;
					      EZ_DnDInfo.ptWin = (unsigned long)ptWin;
					      EZ_BroadcastDnDMessage(EZ_DND_DRAG_MOTION, NULL, 0, 0);
					      if(snapshot != EZ_DND_DRAG_ICON_CURSOR)
						EZ_MoveSnapShotOrOutline(snapshot, Ox, Oy, iww, ihh, 0);
					    }
					}
				    }/* moved */
				} /* not done */
			      else if(done)/* done */
				{
				  if(EZ_PointerGrabed)
				    {
				      XUngrabPointer(EZ_Display,CurrentTime);
				      EZ_PointerGrabed = 0;
				    }
				  if(grabed) /* dragged */
				    {
				      char *message;
				      int length;
				      Window commWin;

				      if(snapshot != EZ_DND_DRAG_ICON_CURSOR)				      
					EZ_MoveSnapShotOrOutline(snapshot, 0,0,0,0,1);
				      if(ptWin != 0) commWin = (Window) EZ_WindowIsDnDTarget(ptWin);
				      else commWin = 0L;
				      EZ_FinishDrag(commWin, ptWin, oldx, oldy); /* prepare for drop */

				      if(commWin != 0L)
					{
					  if(helpRequested)
					    {
					      EZ_DnDSendCancelHelpMsg();
					      helpRequested = 0;
					    }
					  
					  if(dragCancelled == 0)
					    {
					      EZ_DnDInfo.actionType = actionType;
					      EZ_GenerateDragIsDropedMessage(&message, &length);
					      EZ_SendDnDMessage(EZ_DND_DRAG_DROPPED, message, length, 1);
					    }
					  else  /* cancelled */
					    {
					      EZ_SendDnDMessage(EZ_DND_DRAG_CANCELLED, NULL, 0, 0);
					      EZ_AbortDrag();
					    }
					}
				      else if(ptWin == RootWindow(EZ_Display, EZ_ScreenNum) &&
					      dragCancelled == 0)
					{
					  /* drop to the root window, handle this internally */
					  EZ_DnDDataEncoder  *encoder = EZ_FindSpecialEncoder();
					  if(encoder)
					    {
					      char *msg; int mlen, needFree, ok = EZ_DND_FAILURE;
					      
					      EZ_DnDInfo.srcStatus = EZ_DRAG_CONVERTING;
					      ok = (encoder->encoder) (encoder->object,
								       encoder->data,
								       &msg, &mlen, &needFree);
					      if(ok != EZ_DND_FAILURE)
						{
						  if((encoder->callback).callback)
						    {
						      EZ_DnDInfo.srcStatus = EZ_DRAG_EXECUTING_CALLBACK;
						      ((encoder->callback).callback)(encoder->object, 
										     (encoder->callback).data);
						    }
						  EZ_DnDInfo.id = 0; /* forget about this drag */   
						}
					      else EZ_AbortDrag();
					    }
					  else  EZ_AbortDrag();
					}
				      else EZ_AbortDrag();
				    }
				}
			    } /* while */
			}  /* if IsDnDSrc */
		    }
		}
	    }
	}
      break;
    case EnterNotify:
      break;
    case LeaveNotify:
      break;
    case KeyPress:
      if(EZ_IFListBoxRows(widget) > 0)
	{
	  if(EZ_IFListBoxSelectionIDX(widget) < 0)
	    EZ_IFListBoxSelectionIDX(widget) = 0;
	  if(smode == 0 && EZ_IFListBoxSelectionCol(widget) < 0)
	    EZ_IFListBoxSelectionCol(widget) = 0;
	  {
#define TEMP_BUFFER_SIZE    32
	    int               count, move_unit = 1;
	    KeySym            keysym;
	    XComposeStatus    compose; 
	    char              tmpbuffer[TEMP_BUFFER_SIZE];
	    int               buffersize = TEMP_BUFFER_SIZE;
#undef TEMP_BUFFER_SIZE
	    if(event->xkey.state & ShiftMask) move_unit = 2;
	    if(event->xkey.state & ControlMask)     move_unit = 4;
	
	    count = XLookupString(&(event->xkey), tmpbuffer, buffersize, &keysym, &compose);
	    tmpbuffer[count] = '\0'; 
	
	    switch(keysym)
	      {
	      case XK_Up: case XK_k:  case XK_p: case XK_K:  case XK_P: 
#ifdef XK_KP_Up
	      case XK_KP_Up:
#endif
		{
		  int sline = EZ_IFListBoxSelectionIDX(widget);
		  int tmp = sline - move_unit;
		  if(tmp <= 0 ) break;
		  
		  if(tmp != sline)
		    {
		      iflistbox_vscroll_update_selection(widget, sline, tmp, smode);
		      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
		      EZ_IFListBoxSetSelection(widget);
		    }
		}
	      break;
	      case XK_Down: case XK_n: case XK_j: case XK_N: case XK_J:  
#ifdef XK_KP_Down
	      case XK_KP_Down:
#endif
		{
		  int sline = EZ_IFListBoxSelectionIDX(widget);
		  int tmp = sline + move_unit;
		  int nrows = EZ_IFListBoxRows(widget);
		  if(tmp >= nrows) break;
		  
		  if(tmp != sline)
		    {
		      iflistbox_vscroll_update_selection(widget, sline, tmp, smode);
		      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
		      EZ_IFListBoxSetSelection(widget); 
		    }
		}
	      break;
	      case XK_Left: case XK_b:  case XK_h: case XK_B:  case XK_H:  
#ifdef XK_KP_Left
	      case XK_KP_Left:
#endif
		{
		  if(smode)
		    {
		      if(EZ_IFListBoxXSize(widget) > EZ_IFListBoxXPageSize(widget))
			{
			  int aaa = (move_unit << 3);
			  int itmp = EZ_IFListBoxXStart(widget) + aaa;
			  if(itmp > 0) itmp = 0;
		  
			  if(EZ_IFListBoxXStart(widget) != itmp)
			    {
			      EZ_IFListBoxXStart(widget) = itmp;
			      if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
			    }
			}
		    }
		  else
		    {
		      int sline = EZ_IFListBoxSelectionIDX(widget); 
		      int col =  EZ_IFListBoxSelectionCol(widget); 
		      int itmp = col -1;
		      itmp = itmp >= 0 ? itmp : 0;

		      if(col != itmp && sline >= 0)
			{
			  iflistbox_hscroll_update_selection(widget, sline,col, itmp, -1);		      
			  EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
			  EZ_IFListBoxSetSelection(widget);
			}
		    }
		}
	      break;
	      case XK_Right: case XK_f: case XK_l: case XK_F: case XK_L:  
#ifdef XK_KP_Right
	      case XK_KP_Right: 
#endif
		{
		  if(smode)
		    {
		      if(EZ_IFListBoxXSize(widget) > EZ_IFListBoxXPageSize(widget))
			{
			  int bw = EZ_WidgetBorderWidth(widget);
			  int w = EZ_WidgetWidth(widget) - (bw << 1);
			  int tw = EZ_IFListBoxXSize(widget);
			  int aaa = -(move_unit << 3);
			  int itmp = EZ_IFListBoxXStart(widget) + aaa;
			  if(itmp < w - tw) itmp = w -tw;
		  
			  if(EZ_IFListBoxXStart(widget) != itmp)
			    {
			      EZ_IFListBoxXStart(widget) = itmp;
			      if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
			    }
			}
		    }
		  else
		    {
		      int sline = EZ_IFListBoxSelectionIDX(widget); 
		      int col =  EZ_IFListBoxSelectionCol(widget); 
		      int columns = EZ_IFListBoxColumns(widget) -1;
		      int itmp = col +1;
		      itmp = itmp <= columns ? itmp : columns;

		      if(col != itmp && sline > 0)
			{
			  iflistbox_hscroll_update_selection(widget, sline, col, itmp, 1);		      
			  EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
			  EZ_IFListBoxSetSelection(widget);
			}

		    }
		}
	      break;
	      case XK_Return: case XK_Linefeed: case XK_space: 
#ifdef XK_KP_Enter
	      case XK_KP_Enter:
#endif
		{ 
		  EZ_Item *item;
		  int row = EZ_IFListBoxSelectionIDX(widget);
		  int ok = 0;
		  if(smode == 0)
		    {
		      int col = EZ_IFListBoxSelectionCol(widget);
		      if(row > 0 && col >= 0)
			{
			  EZ_Item ***data = EZ_IFListBoxData(widget);
			  item = data[row][col];
			  if(item){ EZ_HandleItemCallBacks(item); ok = 1;}
			}
		    }
		  else
		    {
		      EZ_Item *item, **items = EZ_IFListBoxData(widget)[row];
		      int i, ncols =  EZ_IFListBoxColumns(widget);
		      for(i = 0; i < ncols; i++)
			{
			  item = items[i];
			  if(item) {EZ_HandleItemCallBacks(item); ok = 1;}
			}
		    }
		  /* exec the call backs */
		  if(ok)
		  {
		    /* EZ_Widget *flistbox = EZ_IFListBoxFListBox(widget); */
		    EZ_ExecuteWidgetCallBacks(widget);
		    /* if(flistbox) {EZ_ExecuteWidgetCallBacks(flistbox);} */
		  }
		}
	      break;
	      default:
		break;
	      }
	  }
	  { 
	    XEvent tmpevent; 
	    while(XCheckTypedEvent(EZ_Display, KeyPress, &tmpevent))
	      if(EZ_FilterEvent(&tmpevent))
		EZ_InvokePrivateEventHandler(&tmpevent);
	  }
	}            
      break;
    default:
      break;
    }
}
/***********************************************************************************/
static int find_Pointer_Item_linear();
int EZ_FindPointerOnRowIFL(array, nrows, ncolumns,x, y,Rx,Ry,Rw,Rh)
     EZ_Item ***array;
     int nrows, ncolumns;
     int x,y;
     int Rx,Ry,Rw,Rh;
{
  EZ_Item ***ptr, **row, *item;
  int len, len1, find = -1;
  int idx, j, y0=0;

  if(y <= Ry || y >= Ry + Rh) 
    {return (-1); }

  /* do a binary search */
  len = nrows/2;
  len1 = nrows - len;

  idx = len;
  ptr = array;

  while(1)
    {
      row = ptr[idx];
      item = row[0];

      if(item)
	{
	  y0 = EZ_ItemOriginY(item);
	}
      else
	{
	  for(j = 1; j < ncolumns; j++)
	    {
	      item = row[j];
	      if(item) 
		{ 
		  y0 = EZ_ItemOriginY(item);
		  break;
		}
	    }
	}
      if(item)
	{
	  int h = EZ_ItemAHeight(item);
	  if(y < y0)
	    {
	      int itmp = len >> 1;
	      len1 = len - itmp; 
	      len = itmp;
	      idx -= len1;
	    }
	  else if(y > y0+h)
	    {
	      len = len1 >> 1;
	      len1 = len1 - len; 
	      if(len) idx += len;
	      else idx += len1;
	    }
	  else
	    {
	      if( y >= y0 && y <= y0+h) { find = idx; break; }
	    }
	}
      else  /* an empty row: fails, do a linear search */
	{
	  return(find_Pointer_Item_linear(array, nrows, ncolumns,x, y,Rx,Ry,Rw,Rh));
	  break;
	}
      if(len1 == 0) {find = idx; break;}
      if(idx >= nrows) break;
    }
  if(find == 0) find = -1;
  return(find);
}

static int find_Pointer_Item_linear(array, nrows, ncolumns,x, y,Rx,Ry,Rw,Rh)
     EZ_Item ***array;
     int nrows, ncolumns;
     int x,y;
     int Rx,Ry,Rw,Rh;
{
  EZ_Item ***ptr, **row, *item;
  int i,j, y0=0;

  if(y <= Ry ) y = Ry+1;
  ptr = array;
  for(i = 1; i < nrows;  i++)
    {
      row = ptr[i];
      item = NULL;

      for(j = 0; j < ncolumns; j++)
	{
	  item = row[j];
	  if(item) break;
	}
      if(item)
	{
	  int h = EZ_ItemAHeight(item);
	  y0 = EZ_ItemOriginY(item);
	  if( y >= y0 && y <= y0+h) return(i);
	} 
    }
  return(-1);
}

/***********************************************************************************/

void EZ_FindPointerOnRowAndColIFL(array, nrows, ncolumns,x, y, rowN, colN,
				Rx,Ry,Rw,Rh)
     EZ_Item ***array;
     int nrows, ncolumns;
     int x,y,*rowN, *colN;
     int Rx,Ry,Rw,Rh;
{
  int rowNumber;
  int find =  -1;

  if(y <= Ry ) { *rowN = -1; *colN =  -1; return; }
  rowNumber = EZ_FindPointerOnRowIFL(array, nrows, ncolumns,x, y, Rx,Ry,Rw,Rh);
  
  if(rowNumber > 0)
    {
      EZ_Item **row, *item;
      int i;

      row = array[rowNumber];
      for(i = 0; i  < ncolumns; i++)
	{
	  item = row[i];
	  if(item)
	    {
	      int x0 = EZ_ItemOriginX(item);
	      int w =  EZ_ItemAWidth(item);
	      if( x >= x0 && x <= x0 + w) 
		{
		  find = i;
		  break;
		}
	    }
	}
    }
  *rowN = rowNumber;
  *colN = find;
}
/**************************************************************************/
static void IFTimerCallBack(timer, cdata)
     EZ_Timer *timer; 
     void *cdata;
{
  EZ_Widget *widget = (EZ_Widget *)cdata;
  if(widget && EZ_LookupWidgetFromAllHT(widget) == widget &&
     EZ_WidgetType(widget) == EZ_WIDGET_IFANCY_LIST_BOX)
    {
      if(EZ_WidgetWindow(widget) && EZ_WidgetMapped(widget) &&
	 EZ_IFListBoxRows(widget) > 0)
	{
	  int smode = EZ_IFListBoxSelectionType(widget);
	  int yoffset = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
	  int *vsa = EZ_IFListBoxVSizes(widget);
	  yoffset += (vsa[0] + EZ_WidgetPadY(widget));
	  
	  if(smode)
	    {
	      int sline = EZ_IFListBoxSelectionIDX(widget);
              if(sline > 0)
                {
                  EZ_Item **row = (EZ_IFListBoxData(widget))[sline];
		  int nelts = EZ_IFListBoxColumns(widget);
		  EZ_FlashRowOutline(widget, row, nelts);
		}
	    }
	  else /* item mode */
	    {
	      int sline = EZ_IFListBoxSelectionIDX(widget);
	      int scol =  EZ_IFListBoxSelectionCol(widget);
	      if(sline > 0 && scol >= 0)
		{
		  EZ_Item ***data = EZ_IFListBoxData(widget);
		  EZ_Item *sel = data[sline][scol];
		  if(sel)
		    {
		      int Rx = EZ_WidgetBorderWidth(widget)+1+ EZ_WidgetPadB(widget);
		      int Ry = yoffset;
		      int Rw = EZ_WidgetWidth(widget) - (Rx+Rx);
		      int Rh = EZ_WidgetHeight(widget) -(Rx+Ry);

		      EZ_FlashItemOutline(widget,sel, Rx,Ry,Rw,Rh);
		    }
		}
	    }
	}
    }
  else EZ_CancelTimer(timer);
}
/***********************************************************************************************/     
void EZ_FlashRowOutline(widget, row, nelts)
     EZ_Widget *widget;
     EZ_Item **row;
     int nelts;
{
  if(row)
    {
      int yy=0, hh=0;
      int tw = 0, tx = -999999;
      EZ_Item *item;
      int i, ncols = nelts;

      for(i = 0; i< ncols; i++)
	{
	  item = row[i];
	  if(item)
	    {
	      if(hh == 0)
		{
		  yy = EZ_ItemOriginY(item);
		  hh = EZ_ItemAHeight(item);
		}
	      if(tx == -999999) tx = EZ_ItemOriginX(item);
	      tw =  EZ_ItemOriginX(item) + EZ_ItemAWidth(item);
	    }
	}
      if(hh > 1) /* we are ok */
	{
	  int *vsa = EZ_IFListBoxVSizes(widget);
	  int bw = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
	  int x0 = bw;
	  int y0 = yy;
	  int top, bottom;
	  int width =  EZ_WidgetWidth(widget) - bw;
	  int ww;
	  XPoint points[2];
	  Window win = EZ_WidgetWindow(widget);
	  GC gc;
	  EZ_GetMovingDashedLineGC(&gc);

	  if(tx > bw) x0 = tx;
	  if(tw < width ) { ww = tw;}
	  else ww = width;
	  ww -= (x0+1);
	  hh -= 1;
	  if(vsa[0] > 0) top = bw + vsa[0] + EZ_WidgetPadY(widget);
	  else top = bw;
	  bottom = EZ_WidgetHeight(widget) - bw;
	  if(tx > bw)
	    {
	      int tmp = y0+hh;
	      points[0].x = x0;     points[0].y = y0;
	      points[1].x = x0;   points[1].y = (tmp < bottom? tmp: bottom);
	      XDrawLines(EZ_Display, win, gc, points, 2, CoordModeOrigin);
	    }
	  if(yy >= top && yy < bottom)
	    {
	      points[0].x = x0;     points[0].y = y0;
	      points[1].x = x0+ww;   points[1].y = y0;
	      XDrawLines(EZ_Display, win, gc, points, 2, CoordModeOrigin);
	    }
	  if(yy + hh >= top && yy +hh < bottom)
	    {
	      points[0].x = x0+ww;     points[0].y = y0 + hh;
	      points[1].x = x0;   points[1].y = y0 + hh;
	      XDrawLines(EZ_Display, win, gc, points, 2, CoordModeOrigin);
	    }
	  if(tw < width)
	    {
	      int tmp = y0 +hh;
	      points[0].x = x0+ww;     points[0].y = y0;
	      points[1].x = x0+ww;   points[1].y = (tmp < bottom? tmp: bottom);
	      XDrawLines(EZ_Display, win, gc, points, 2, CoordModeOrigin);	      
	    }
	}
    }
}
/***********************************************************************************************/     
static void   iflistbox_vscroll_update_selection(widget, sline, nsline, smode)
     EZ_Widget *widget;
     int sline, nsline, smode;
{
  EZ_Item ***data = EZ_IFListBoxData(widget);
  EZ_Item **row, *item;
  int y0=0, h0=0;
  int redraw = 0;

  row = data[nsline];
  item = row[0];
  if(item)
    {
      y0 = EZ_ItemOriginY(item);
      h0 = EZ_ItemAHeight(item);
    }
  else
    {
      int i, ncolumns = EZ_IFListBoxColumns(widget);
      for(i = 1; i < ncolumns; i++)
	{
	  item = row[i];
	  if(item)
	    {
	      y0 = EZ_ItemOriginY(item);
	      h0 = EZ_ItemAHeight(item);
	      break;
	    }
	}
    }
  if(item)  /* do the scrolling */
    {
      int yoff, bw,Ry,Rh;
      int *vsa = EZ_IFListBoxVSizes(widget);

      bw = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
      yoff = bw + EZ_WidgetPadY(widget);
      Rh = EZ_WidgetHeight(widget) - yoff;
      Ry =  yoff + vsa[0];

      if(y0 < Ry || y0 + h0 > Rh)
	{
	  if(y0 < Ry)
	    {
	      int itmp  =  Ry - y0  + EZ_IFListBoxYStart(widget);
	      itmp = (itmp < 0 ? itmp: 0); 
	      if(itmp != EZ_IFListBoxYStart(widget))
		{
		  EZ_IFListBoxYStart(widget) = itmp;
		  redraw = 1;
		}
	    }
	  else
	    {
	      int th = Rh;
	      int dif = th - EZ_IFListBoxYSize(widget);
	      if(dif < 0)
		{
		  int itmp =  EZ_IFListBoxYStart(widget) - h0 + th - y0; 
		  itmp = (itmp > dif ? itmp: dif);
		  if(EZ_IFListBoxYStart(widget) != itmp)
		    {
		      EZ_IFListBoxYStart(widget) = itmp;
		      redraw = 1; 
		    }
		}
	    }
	}
    }
  if(redraw == 0 && EZ_WidgetMapped(widget))
    {
      int bw, yoffset, Rx,Ry,Rw,Rh;
	  
      bw = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
      yoffset = bw + EZ_WidgetPadY(widget);

      Rx = bw;
      Ry = yoffset + (EZ_IFListBoxVSizes(widget))[0];
      Rw = EZ_WidgetWidth(widget) - (bw << 1);
      Rh = EZ_WidgetHeight(widget) - bw - Ry;

      if(smode)
	{
	  if(sline > 0)
	    {
	      EZ_UpdateOneRow(widget, EZ_WidgetWindow(widget),
			      EZ_IFListBoxData(widget)[sline],
			      EZ_IFListBoxColumns(widget),
			      Rx,Ry,Rw,Rh);
	    }
	  {
	    EZ_Item **row =  EZ_IFListBoxData(widget)[nsline];
	    unsigned long fg = EZ_IFListBoxHighlightFG(widget);
	    unsigned long bg = EZ_IFListBoxHighlightBG(widget);
	    EZ_HighlightOneRow(widget, EZ_WidgetWindow(widget), row, 
			       EZ_IFListBoxColumns(widget),fg, bg,
			       Rx,Ry,Rw,Rh);
	  }
	}
      else
	{
	  EZ_Item ***data = EZ_IFListBoxData(widget);
	  EZ_Item **row, *item;
	  int col = EZ_IFListBoxSelectionCol(widget);
	  if(sline > 0 && col >= 0)
	    {
	      row = data[sline];
	      item = row[col];
	      if(item) EZ_UpdateOneItem(widget,EZ_WidgetWindow(widget),item, Rx,Ry,Rw,Rh);
	      row = data[nsline];
	      item = row[col];
	      if(item)
		{
		  unsigned long fg = EZ_IFListBoxHighlightFG(widget);
		  unsigned long bg = EZ_IFListBoxHighlightBG(widget);
		  EZ_HighlightOneItem(widget, EZ_WidgetWindow(widget),item, fg, bg, Rx,Ry,Rw,Rh);
		}
	    }
	}
    }
  EZ_IFListBoxSelectionIDX(widget) = nsline;
  if(redraw && EZ_WidgetMapped(widget)) EZ_DrawWidget(widget); 
}
/*****************************************************************************/
static void iflistbox_hscroll_update_selection(widget, sline, col, ncol, flag)
     EZ_Widget *widget;
     int sline, col, ncol, flag;
{
  EZ_Item ***data;
  EZ_Item **row, *item;
  int redraw = 0;
  int bw, xoff, Rw, x0, w0;

  if(sline <= 0) return;

  data  = EZ_IFListBoxData(widget);
  bw = EZ_WidgetBorderWidth(widget) + EZ_WidgetPadB(widget);
  xoff = bw + EZ_WidgetPadX(widget);
  Rw = EZ_WidgetWidth(widget) - xoff;

  row = data[sline];
  item = row[ncol];

  if(item == NULL && flag != 0)
    {
      int ncolums = EZ_IFListBoxColumns(widget);
      int tmp = ncol + flag;
      while(tmp >= 0 && tmp < ncolums)
	{
	    if(row[tmp] != NULL) 
	      {
		item = row[tmp];
		ncol = tmp;
		break;
	      }
	    tmp += flag;
	}
      if(item == NULL) return;
    }

  if(item)
    {
      x0 = EZ_ItemOriginX(item);
      w0 = EZ_ItemAWidth(item);

      if(x0 < xoff  ||  x0 + w0 > Rw)
	{
	  if(x0 < xoff)
	    {
	      int itmp = EZ_IFListBoxXStart(widget)  + xoff - x0;
	      itmp = (itmp < 0? itmp: 0);
	      if(itmp != EZ_IFListBoxXStart(widget))
		{
		  EZ_IFListBoxXStart(widget) = itmp;
		  redraw = 1;
		}	      
	    }
	  else 
	    {
	      int th = EZ_IFListBoxXSize(widget);
	      int diff = Rw - th;
	      if(diff < 0)
		{
		  int itmp = EZ_IFListBoxXStart(widget) + Rw -x0 -w0;
		  itmp = (itmp > diff ? itmp: diff);
		  if(EZ_IFListBoxXSize(widget) != itmp)
		    {
		      EZ_IFListBoxXStart(widget) = itmp;
		      redraw = 1;
		    }	      
		}
	    }
	}
    }
  if(redraw == 0)
    {
      int bw, xoffset, yoffset;
      int Rx,Ry,Rw,Rh;

      bw = EZ_WidgetBorderWidth(widget)  + EZ_WidgetPadB(widget);
      xoffset = bw + EZ_WidgetPadX(widget);
      yoffset = bw + EZ_WidgetPadY(widget);
      
      Rx = bw;
      Ry = yoffset + (EZ_IFListBoxVSizes(widget))[0];
      Rw = EZ_WidgetWidth(widget) - (bw << 1);
      Rh = EZ_WidgetHeight(widget) - bw - Ry;

      row = data[sline];
      if(col >= 0)
	{
	  item = row[col];
	  if(item) EZ_UpdateOneItem(widget,EZ_WidgetWindow(widget),item, Rx,Ry,Rw,Rh);
	}
      item = row[ncol];
      if(item)
	{
	  unsigned long fg = EZ_IFListBoxHighlightFG(widget);
	  unsigned long bg = EZ_IFListBoxHighlightBG(widget);
	  EZ_HighlightOneItem(widget, EZ_WidgetWindow(widget),item, fg, bg, Rx,Ry,Rw,Rh);
	}
    }
  EZ_IFListBoxSelectionCol(widget) = ncol;
  if(redraw && EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
}
/***************************************************************************************/
extern ITextLine TextWidgetKillBuffer;

static void EZ_IFListBoxSetSelection(widget)
     EZ_Widget *widget;
{
  int smode = EZ_IFListBoxSelectionType(widget);
  int sline = EZ_IFListBoxSelectionIDX(widget);

  if(smode)
    {
      if(sline > 0)
	{
	  EZ_Item ***data = EZ_IFListBoxData(widget);
	  EZ_Item **row = data[sline];
	  EZ_Item *item;
	  int cols = EZ_IFListBoxColumns(widget);
	  int i, total = 0;
	  for(i = 0; i < cols; i++)
	    {
	      item = row[i];
	      if(item)
		{
		  char *str; 
		  int length;
		  EZ_GetLabelItemStringInfo(item, &str, &length);
		  if(length > 0)
		    {
		      EZ_GrowITextKillBuffer(&TextWidgetKillBuffer,(total+length+8));
		      if(i>0 && total > 0)
			{
			  char *t = TextWidgetKillBuffer.data + total;
			  *t = ' ';
			  *(t+1) = 0;
			  total++;
			}
		      (void) strncpy(TextWidgetKillBuffer.data + total, str, length);
		      total += length;
		      (TextWidgetKillBuffer.data)[total] = 0;
		    }
		}
	    }
	  if(total > 0)
	    {
	      TextWidgetKillBuffer.length = total;
	      TextWidgetKillBuffer.width = 0;
	      EZ_SetSelectionOwner(widget);
	    }
	}
    }
  else
    {
      if(sline > 0)
	{
	  int col = EZ_IFListBoxSelectionCol(widget);
	  if(col >= 0)
	    {
	      EZ_Item ***data = EZ_IFListBoxData(widget);
	      EZ_Item *item = data[sline][col];
	      if(item)
		{
		  char *str;
		  int length;
		  EZ_GetLabelItemStringInfo(item, &str, &length);
		  if(length > 0)
		    {
		      EZ_GrowITextKillBuffer(&TextWidgetKillBuffer,(length+8));
		      (void) strncpy(TextWidgetKillBuffer.data, str, length);
		      (TextWidgetKillBuffer.data)[length] = 0;

		      TextWidgetKillBuffer.length = length;
		      TextWidgetKillBuffer.width = 0;
		      EZ_SetSelectionOwner(widget);
		    }
		}
	    }
	}
    }
}
/****************************************************************************/
void  EZ_IFListBoxAllocNewStorage(wptr, nrows, ncolumns)
     EZ_Widget *wptr;
     int nrows, ncolumns;
{
  EZ_Item  ***data, **row;
  int      *iptr, *jptr, i, j;
  int aval = EZ_IFListBoxSpace(wptr);
  int col = EZ_IFListBoxColumns(wptr);

  if(nrows <= 16) nrows = 32;
  /* check if current setting is ok */
  if(aval > nrows + 2 && col == ncolumns)
    { /* ok */
      int count = EZ_IFListBoxRows(wptr);
      data = EZ_IFListBoxData(wptr);
      for(i = 1; i < count; i++)
	{
	  row = data[i];
	  for(j = 0; j < ncolumns; j++)
	    {
	      if(row[j]){ EZ_DestroyItem(row[j]); row[j] = NULL;}
	    }
	}
      (EZ_IFListBoxVSizes(wptr))[0] = 0;
    }
  else
    {
      /* get rid of the old ones */
      EZ_Item **header;
      int headerH;

      data = EZ_IFListBoxData(wptr);
      if(aval > 0)
	{
	  header = data[0];
	  headerH =  (EZ_IFListBoxVSizes(wptr))[0];
	}
      else { header = NULL; headerH = 0; }
      
      for(i = 1; i < aval; i++)
	{
	  row = data[i];
	  for(j = 0; j < col; j++)
	    {
	      if(row[j]) EZ_DestroyItem(row[j]); 
	    }
	  (void)my_free((char *)row);
	}
      if(data)   (void) my_free( (char *)data);
      if(EZ_IFListBoxHSizes(wptr))
	(void) my_free( (char *) EZ_IFListBoxHSizes(wptr));
      if(EZ_IFListBoxVSizes(wptr))
	(void) my_free( (char *) EZ_IFListBoxVSizes(wptr));
      
      data = (EZ_Item ***)  my_malloc((nrows + 16) * sizeof(EZ_Item **), _IFLISTBOX_DATA_);
      iptr = (int *)my_malloc( ncolumns * sizeof(int),  _IFLISTBOX_DATA_);
      jptr = (int *)my_malloc( (nrows + 16) * sizeof(int),  _IFLISTBOX_DATA_);

      if(jptr == NULL || iptr== NULL || data == NULL)  EZ_OutOfMemory("EZ_CreateIFListBox");
      EZ_IFListBoxHSizes(wptr) = iptr;
      EZ_IFListBoxVSizes(wptr) = jptr;
      EZ_IFListBoxData(wptr) = data;
      for(i = 0; i < ncolumns; i++)   iptr[i] = 0;

      for(i = 0; i < nrows + 16; i++)
	{
	  EZ_Item **rowptr;
	  jptr[i] = 0;
	  rowptr = data[i] = (EZ_Item **)my_malloc(ncolumns * sizeof(EZ_Item *), _IFLISTBOX_DATA_);
	  if(rowptr == NULL) EZ_OutOfMemory("EZ_CreateIFListBox");
	  {
	    int j; 
	    for(j = 0; j < ncolumns; j++) rowptr[j] = (EZ_Item *)NULL;
	  }
	}
      if(header)
	{
	  int i, mcol = (ncolumns < col ? ncolumns: col);
	  row = data[0];
	  for(i = 0; i < mcol; i++) row[i] = header[i];
	  for(i = mcol; i < col; i++)  if(row[i]) EZ_DestroyItem(row[i]);
	  jptr[0] = headerH;
	  (void)my_free((char *)header);
	}
      EZ_IFListBoxSpace(wptr) = nrows + 16;
    }
  EZ_IFListBoxColumns(wptr) = ncolumns;
  EZ_IFListBoxRows(wptr) = 1;  
  EZ_IFListBoxSelectionIDX(wptr) = -1;
  EZ_IFListBoxSelectionCol(wptr) = -1;
}
/******************************************************************************************/
static void  EZ_IFListBoxGrowStorage(widget, unit)
     EZ_Widget *widget;
     int unit;
{
  int nrows = EZ_IFListBoxRows(widget);
  int aval = EZ_IFListBoxSpace(widget);

  if(nrows + unit + 4 > aval)
    {
      EZ_Item ***data = EZ_IFListBoxData(widget);
      int *vsa = EZ_IFListBoxVSizes(widget);
      int i,j, new_aval = aval + unit + 16;
      int col = EZ_IFListBoxColumns(widget);

      data = (EZ_Item ***)my_realloc((void *)data, (new_aval)*sizeof(EZ_Item **),
				     _IFLISTBOX_DATA_);
      vsa = (int *) my_realloc((void *)vsa, new_aval * sizeof(int),_IFLISTBOX_DATA_);
      if(data == NULL || vsa == NULL) EZ_OutOfMemory("EZ_IFListBoxGrowBuffer");
      for(i = aval; i < new_aval; i++)
	{
	  EZ_Item **t = (EZ_Item **)my_malloc(col * sizeof(EZ_Item *), _IFLISTBOX_DATA_);
	  if( t == NULL) EZ_OutOfMemory("EZ_IFListBoxGrowBuffer");
	  for(j = 0; j < col; j++) t[j] = (EZ_Item *)NULL;
	  data[i] = t;
	  vsa[i] = 0;
	}
      EZ_IFListBoxData(widget) = data; 
      EZ_IFListBoxVSizes(widget) = vsa;
      EZ_IFListBoxSpace(widget) = new_aval;
    }
}
/******************************************************************************************/

void EZ_SetIFListBoxData(widget, data, nrows, ncols)
     EZ_Widget *widget;
     EZ_Item   **data;
     int nrows, ncols;
{
  int i,j;
  EZ_Item ***des, **row, **src;

  EZ_IFListBoxAllocNewStorage(widget, nrows, ncols);

  src = (EZ_Item **)data;
  des = EZ_IFListBoxData(widget);
  for(i = 0; i < nrows; i++)
    {
      row = des[i+1];
      for(j = 0; j < ncols; j++)
	row[j] = *src++;
    }
  EZ_IFListBoxColumns(widget) = ncols;
  EZ_IFListBoxRows(widget) = nrows + 1;    
  EZ_IFListBoxDirty(widget) = 1;      
  EZ_IFListBoxSelectionIDX(widget) = -1;
  EZ_IFListBoxSelectionCol(widget) = -1;

  if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
}
/******************************************************************************************/
void  EZ_InsertIFListBoxRow(widget, items, nitems, where)
     EZ_Widget *widget;
     EZ_Item **items;
     int where, nitems;
{
  EZ_IFListBoxGrowStorage(widget, 1);
  {
    int numcols = EZ_IFListBoxColumns(widget);
    int nrows = EZ_IFListBoxRows(widget);
    int i, idx;
    int ncols = (numcols < nitems? numcols: nitems);
    EZ_Item ***data =EZ_IFListBoxData(widget);
    EZ_Item **save = data[nrows];

    if(where < 1 || where >= nrows) /* insert at the end */
      idx = nrows;
    else
      {
	int sline = EZ_IFListBoxSelectionIDX(widget);
	for(i = nrows; i > where; i--)
	  data[i] = data[i-1];
	idx = where;
	if(sline >= idx) EZ_IFListBoxSelectionIDX(widget) = sline +1;
      }
    {
      int i;
      
      for(i = 0; i < numcols; i++)
	{
	  if(i < ncols)	save[i] = items[i];
	  else save[i] = NULL;
	}
      EZ_IFListBoxData(widget)[idx] = save;
    }

    EZ_IFListBoxRows(widget) = nrows + 1;
    EZ_IFListBoxDirty(widget) = 1;
  }
  if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
}
/**************************************************/
void  EZ_DeleteIFListBoxRow(widget,idx)
     EZ_Widget *widget;
     int idx;
{
  int ncols = EZ_IFListBoxColumns(widget);
  int nrows = EZ_IFListBoxRows(widget);
  int i;
  EZ_Item ***data =EZ_IFListBoxData(widget);

  if(idx < 1 || idx >= nrows)  return;
  else
    {
      int sline = EZ_IFListBoxSelectionIDX(widget);
      EZ_Item **save = data[idx];
      for(i = idx; i <= nrows; i++)
	data[i] = data[i+1];
      for(i = 0; i < ncols; i++)
	if(save[i]) { EZ_DestroyItem(save[i]); save[i] = NULL; }

      /* bug: deleted row got lost in the dark. 
       * thanks to "Elliot Turner <turnere@MimeStar.com>"
       * for finding it.
       */
      data[nrows+1] = save;

      EZ_IFListBoxRows(widget) = nrows - 1;
      EZ_IFListBoxDirty(widget) = 1;
      if(sline == idx)
	EZ_IFListBoxSelectionIDX(widget) = -1;
      else  if(sline > idx)
	EZ_IFListBoxSelectionIDX(widget) -= 1;
      if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
    }
}
void  EZ_DeleteIFListBoxSomeRows(widget,indices, cnt)
     EZ_Widget *widget;
     int *indices, cnt;
{
  int ncols = EZ_IFListBoxColumns(widget);
  int nrows = EZ_IFListBoxRows(widget);
  int i,j, idx, sline, deleted = 0;
  EZ_Item ***save, ***data =EZ_IFListBoxData(widget);

  save  = (EZ_Item ***)my_malloc( (nrows+1) * sizeof(EZ_Item **), _MISC_DATA_);

  sline = EZ_IFListBoxSelectionIDX(widget);
  for(i = 0; i < cnt; i++)
    {
      idx = indices[i];
      if(idx >= 1 && idx < nrows && data[idx] != NULL)
	{
	  EZ_Item **tmp = data[idx];
	  save[deleted++] = tmp;
	  data[idx] = NULL;
	  for(j = 0; j < ncols; j++)
	    if(tmp[j]) { EZ_DestroyItem(tmp[j]); tmp[j] = NULL; }
	  if(sline > 0)
	    {
	      if(sline == idx) sline = -1;
	      else if(sline > idx) sline -= 1;
	    }
	}
    }
  if(deleted)
    {
      int i, j, k;
      
      EZ_IFListBoxDirty(widget) = 1;
      i=1; j = 1;
      while(j < nrows)
	{
	  while(data[i] != NULL) i++;
	  j = (j > i? j: i);
	  while( j < nrows && data[j] == NULL) j++;	  
	  if(j < nrows)
	    {
	      data[i] = data[j];
	      data[j] = NULL;
	      j++;
	      i++;
	    }
	}
      
      for(k = 0, j = i; j <= nrows && k < deleted;i++)
	{
	  if(data[i] == NULL)
	    data[i] = save[k++];
	}
      k = nrows - deleted;
      EZ_IFListBoxRows(widget) = k;
      EZ_IFListBoxSelectionIDX(widget) = sline;
      if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
    }
  (void)my_free((char *)save);
}
/******************************************************************************************/
void  EZ_ClearIFListBox(widget)
     EZ_Widget *widget;
{
  EZ_Item  ***data, **row;
  int cols = EZ_IFListBoxColumns(widget);
  int i, j, nrows = EZ_IFListBoxRows(widget);

  data = EZ_IFListBoxData(widget);
  for(i = 1; i < nrows; i++)
    {
      row = data[i];
      for(j = 0; j < cols; j++)
	{
	  if(row[j]){ EZ_DestroyItem(row[j]); row[j] = NULL;}
	}
    }
  EZ_IFListBoxRows(widget) = 1;
  EZ_IFListBoxDirty(widget) = 1;      
  EZ_IFListBoxSelectionIDX(widget) = -1;
  EZ_IFListBoxSelectionCol(widget) = -1;
  EZ_IFListBoxXStart(widget) = 0;
  EZ_IFListBoxYStart(widget) = 0;
  if(EZ_WidgetMapped(widget)) EZ_DisplayWidget(widget);
}

/******************************************************************************************/
EZ_Item  **EZ_GetIFListBoxSelection(widget)
     EZ_Widget *widget;
{
  int smode = EZ_IFListBoxSelectionType(widget);

  if(smode)
    {
      int sline = EZ_IFListBoxSelectionIDX(widget);
      if(sline > 0)
	{
	  EZ_Item ***data = EZ_IFListBoxData(widget);
	  return(data[sline]);
	}
    }
  else
    {
      int sline = EZ_IFListBoxSelectionIDX(widget);
      if(sline > 0)
	{
	  int col = EZ_IFListBoxSelectionCol(widget);
	  if(col >= 0)
	    {
	      EZ_Item ***data = EZ_IFListBoxData(widget);	      
	      EZ_Item **row = data[sline];
	      return(row + col);
	    }
	}
    }
  return(NULL);
}
/******************************************************************************************/
void EZ_SetIFListBoxHeader(widget, items, nitems)
     EZ_Widget *widget;
     EZ_Item **items;
     int      nitems;
{
  int i, col, ncol = EZ_IFListBoxColumns(widget);
  EZ_Item **data = EZ_IFListBoxData(widget)[0];
  
  col = (ncol < nitems? ncol: nitems);
  for(i = 0; i < col; i++)
    {
      EZ_Item *item = data[i];
      if(item) EZ_DestroyItem(item);
      data[i] = (items == NULL ? NULL : items[i]);
    }
  EZ_IFListBoxDirty(widget) = 1;
  if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
}
/******************************************************************************************/
void EZ_DnDOutlineRow(widget, row, nelts, cx,cy,cw,ch)
     EZ_Widget *widget;
     EZ_Item **row;
     int nelts;
     int cx,cy,cw,ch;
{
  if(row && widget)
    {
      EZ_Item *item;
      int i, h, x0,y0=0;

      h = 0;
      for(i = 0 ; i < nelts; i++)
	{
	  item = row[i];
	  if(item)
	    {
	      h = EZ_ItemAHeight(item);
	      y0 = EZ_ItemOriginY(item);
	      break;
	    }
	}
      if(h > 0)
	{
	  int x_r,y_r,w_r,h_r;
	  
	  x0 = 0;
	  EZ_IntersectRectangles(cx,cy,cw,ch, 
				 x0,y0,999999,h,
				 &x_r,&y_r, &w_r, &h_r);
	  if(w_r > 0)
	    {
	      XPoint points[5];
	      Window win = EZ_WidgetWindow(widget);
	      GC gc = EZ_DNDXORGC; 
	      
	      points[0].x = x_r;       points[0].y = y_r;
	      points[1].x = x_r+w_r;   points[1].y = y_r;
	      points[2].x = x_r+w_r;   points[2].y = y_r+h_r;
	      points[3].x = x_r;       points[3].y = y_r+h_r;
	      points[4].x = x_r;       points[4].y = y_r;
	      XDrawLines(EZ_Display, win, gc, points, 5, CoordModeOrigin);
	    }
	}
    }
}
/*********************************************************************/
void  EZ_GetIFListBoxSelectionIdx(widget, row_ret, col_ret)
     EZ_Widget *widget;
     int *row_ret, *col_ret;
{
  if(widget)
    {
      int smode = EZ_IFListBoxSelectionType(widget);
      int sline =  EZ_IFListBoxSelectionIDX(widget); 
      int nrows = EZ_IFListBoxRows(widget); 
      if(smode)
	{
	  if(sline > 0 && sline < nrows)
	    {
	      if(row_ret) *row_ret = sline;
	      if(col_ret) *col_ret = 0;
	      return;
	    }
	}
      else
	{
	  if(sline > 0 && sline < nrows)
	    {
	      int col = EZ_IFListBoxSelectionCol(widget);
	      if(col >= 0 && col < (int) EZ_IFListBoxColumns(widget))
		{
		  if(row_ret) *row_ret = sline;
		  if(col_ret) *col_ret = col;		  
		  return;
		}
	    }
	}
    }
  if(row_ret) *row_ret = -1;
  if(col_ret) *col_ret = -1;		    
}
/***********************************************************/	      
void EZ_ReplaceIFListBoxItem(widget, olditem, newitem)
     EZ_Widget *widget;
     EZ_Item *olditem, *newitem;
{
  if(widget)
    {
      int nrows = EZ_IFListBoxRows(widget); 
      int ncols = EZ_IFListBoxColumns(widget);
      EZ_Item ***data = EZ_IFListBoxData(widget);
      int i,j;
      for(i = 0; i < nrows; i++)
	{
	  EZ_Item **row = data[i];
	  for(j = 0; j < ncols; j++)
	    {
	      if(row[j] == olditem)
		{
		  if(olditem) EZ_DestroyItem(olditem);
		  row[j] = newitem;
		  EZ_IFListBoxDirty(widget) = 1;
		  if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
		  return;
		}
	    }
	}
    }
}
/***********************************************************/	      
void EZ_ReplaceIFListBoxItemUsingIdx(widget, rowI, colI, newitem)
     EZ_Widget *widget;
     int rowI, colI;
     EZ_Item *newitem;
{
  if(widget)
    {
      int nrows = EZ_IFListBoxRows(widget); 
      int ncols = EZ_IFListBoxColumns(widget);
      EZ_Item ***data = EZ_IFListBoxData(widget);
      if(rowI > 0 && rowI < nrows && colI >= 0  && colI < ncols)
	{
	  EZ_Item **row = data[rowI];
	  if(row[colI]) EZ_DestroyItem(row[colI]);
	  row[colI] = newitem;
	  EZ_IFListBoxDirty(widget) = 1;
	  if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
	}
    }
}
/***********************************************************/	      
EZ_Item  *EZ_GetIFListBoxItemUsingIdx(widget, rowI, colI)
     EZ_Widget *widget;
     int rowI, colI;
{
  if(widget)
    {
      int nrows = EZ_IFListBoxRows(widget); 
      int ncols = EZ_IFListBoxColumns(widget);
      EZ_Item ***data = EZ_IFListBoxData(widget);
      if(rowI > 0 && rowI < nrows && colI >= 0  && colI < ncols)
	{
	  EZ_Item **row = data[rowI];
	  return(row[colI]);
	}
    }
  return(NULL);
}
/*************************************************************/
static void EZ_IFListBoxFindItem(widget, item, loc)
     EZ_Widget *widget; EZ_Item *item; int *loc;
{
  if(item == NULL) { *loc = -1; return;}
  if(widget)
    {
      int i, j, nrows = EZ_IFListBoxRows(widget); 
      int ncols = EZ_IFListBoxColumns(widget);
      EZ_Item ***data = EZ_IFListBoxData(widget);
      for(i = 0; i < nrows; i++)
	{
	  EZ_Item **row = data[i];
	  for(j = 0; j < ncols; j++)
	    if(row[j] == item) { loc[0] = i; loc[1] = j; return;}
	}
    }
  *loc = -1;
}
/*************************************************************/
void EZ_IFListBoxSelectItem(widget, item, location)
     EZ_Widget *widget;
     EZ_Item *item;
     int *location;
{
  if(widget)
    {
      if(item == NULL)
	{
	  EZ_IFListBoxSelectionIDX(widget) = -1;
	  if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
	}
      else
	{
	  int pos[2];  pos[0] = -1;
	  EZ_IFListBoxFindItem(widget, item, pos);
	  if(pos[0] >= 0)
	    EZ_IFListBoxSelectItemUsingIdx(widget, pos[0], pos[1], location);
	}
    }
}
/*************************************************************/

void EZ_IFListBoxSelectItemUsingIdx(widget, Srow, Scol, location)
     EZ_Widget *widget;
     int Srow, Scol;
     int *location;
{
  if(widget)
    {
      if(Srow < 0) 
	{
	  EZ_IFListBoxSelectionIDX(widget) = -1;
	  if(EZ_WidgetMapped(widget)) EZ_DrawWidget(widget);
	}
      else
	{
	  int row = Srow;
	  int col = Scol;
	  int  nrows = EZ_IFListBoxRows(widget); 
	  int  ncols = EZ_IFListBoxColumns(widget);
	  int doit = 0;
	  int smode = EZ_IFListBoxSelectionType(widget);
	  
	  doit = (row > 0 && row < nrows);
	  if(doit && smode == 0) doit = (col >= 0 && col < ncols);
	  
	  if(doit)
	    {
	      int osline = EZ_IFListBoxSelectionIDX(widget);
	      int ocol =  EZ_IFListBoxSelectionCol(widget); 
	      EZ_Item ***data = EZ_IFListBoxData(widget);  
	      EZ_Item **tmprow = data[row];
	      EZ_Item *item = tmprow[col];

	      EZ_IFListBoxSelectionIDX(widget) = row;
	      if(smode == 0) EZ_IFListBoxSelectionCol(widget) = col;
	      if(EZ_WidgetMapped(widget))
		{
		  if(location)
		    {
		      int x = EZ_ItemOriginX(item);
		      int y = EZ_ItemOriginY(item);
		      EZ_IFListBoxXStart(widget) += location[0] - x;
		      EZ_IFListBoxYStart(widget) += location[1] - y;
		      EZ_DrawWidget(widget);
		      iflistbox_vscroll_update_selection(widget, row, row, smode);
		      if(smode == 0) iflistbox_hscroll_update_selection(widget, row, col, col, 0);
		      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
		    }
		  else
		    {
		      if(smode)
			{
			  if(row != osline)
			    {
			      iflistbox_vscroll_update_selection(widget, osline, row, smode);
			      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
			      /* EZ_IFListBoxSetSelection(widget);*/
			    }
			}
		      else
			{
			  if( (row != osline || col != ocol))
			    {
			      iflistbox_vscroll_update_selection(widget, osline, row, smode);
			      iflistbox_hscroll_update_selection(widget, row, ocol, col, 0);
			      EZ_HandleMotionCallBacks(widget,EZ_IFListBoxMotionCallBack(widget));
			      /* EZ_IFListBoxSetSelection(widget);*/
			    }
			}
		    }
		}
	    }
	}
    }
}
/*************************************************************/
#undef _EZ_WIDGET_IFLIST_BOX_C_
