/*********************************************************************
 *
 *         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 RawXWindow                            ***
 ***                                                           ***
 ***                                                           ***
 *****************************************************************/
#define _EZ_WIDGET_RAWXWIN_C_
#include "EZ_Widget.h"

typedef struct udfwHandle_ {
  int  utype;
  void (*Setup)       MY_ANSIARGS((EZ_Widget *widget));
  void (*ComputeSize) MY_ANSIARGS(( EZ_Widget *widget, int *w, int *h));
  void (*DrawWidget)  MY_ANSIARGS((EZ_Widget *widget));
  void (*FreeData)    MY_ANSIARGS((EZ_Widget *widget));
  void (*EventHandle) MY_ANSIARGS((EZ_Widget *widget, XEvent *event));
  struct udfwHandle_  *next;
} EZ_UDFWHandle;

/*********************************************************************/
static EZ_UDFWHandle *udfhandles;
#define UdfType(ptr)                 ((ptr)->utype)
#define UdfSetup(ptr)                ((ptr)->Setup)
#define UdfComputeSize(ptr)          ((ptr)->ComputeSize)
#define UdfDraw(ptr)                 ((ptr)->DrawWidget)
#define UdfFreeData(ptr)             ((ptr)->FreeData)
#define UdfEHandle(ptr)              ((ptr)->EventHandle)
/*********************************************************************
 * 
 *  Functions implemented in this file:
 */
EZ_Widget       *EZ_CreateRawXWindow MY_ANSIARGS((EZ_Widget *parent));
void             EZ_DrawWidgetRawXWin MY_ANSIARGS((EZ_Widget *widget));
void             EZ_ComputeWidgetRawXWinSize MY_ANSIARGS((EZ_Widget *widget, int *w, int *h));
void             EZ_FreeWidgetRawXWinData MY_ANSIARGS((EZ_Widget *widget));
void             EZ_RawXWinEventHandle MY_ANSIARGS((EZ_Widget *widget, XEvent *event));

void             EZ_SetupRawXWinWidget MY_ANSIARGS(( EZ_Widget *widget,
		    void (*ComputeSize) MY_ANSIARGS(( EZ_Widget *widget, int *w, int *h)),
                    void  (*DrawWidget)  MY_ANSIARGS((EZ_Widget *widget)),
                    void  (*FreeData)    MY_ANSIARGS((EZ_Widget *widget)),
                    void  (*EventHandle) MY_ANSIARGS((EZ_Widget *widget, XEvent *event)) ));

/*********************************************************************/
GC      EZ_GetWritableGC MY_ANSIARGS((void));

void   EZ_RegisterWidget MY_ANSIARGS(( int type,
                    void  (*Setup)  MY_ANSIARGS((EZ_Widget *widget)),
		    void (*ComputeSize) MY_ANSIARGS(( EZ_Widget *widget, int *w, int *h)),
                    void  (*DrawWidget)  MY_ANSIARGS((EZ_Widget *widget)),
                    void  (*FreeData)    MY_ANSIARGS((EZ_Widget *widget)),
                    void  (*EventHandle) MY_ANSIARGS((EZ_Widget *widget, XEvent *event)) ));

void   EZ_SetupUDFWidget   MY_ANSIARGS((EZ_Widget *widget));


void   *EZ_SearchUDFWidgetHandle MY_ANSIARGS(( int type));
void   EZ_DeleteAllUDFWidgetHandles MY_ANSIARGS((void));
/*********************************************************************
 * 
 *  Local Variables.
 */
static EZ_WidgetHandle EZ_RawXWinHandle =
{ 
  EZ_ComputeWidgetRawXWinSize,
  EZ_DrawWidgetRawXWin,
  EZ_FreeWidgetRawXWinData,
  EZ_RawXWinEventHandle, 
};

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

EZ_Widget  *EZ_CreateRawXWindow(parent)
     EZ_Widget  *parent;     /* parent widget    */
{
  EZ_Widget  *tmp;
  
  tmp = EZ_CreateNewWidget(parent);
  /*--------------------------------------------------
   * Register the handling functions for label.
   *  has to be done after  EZ_CreateNewWiget.
   *-------------------------------------------------*/
  EZ_WidgetHandlingFunctions[EZ_WIDGET_RAW_XWINDOW] = &EZ_RawXWinHandle;

  EZ_SetWidgetTypeAndNames(tmp, EZ_WIDGET_RAW_XWINDOW);
  EZ_WidgetBorderStyle(tmp)  = EZ_BORDER_NONE;
  EZ_WidgetBorderWidth(tmp)  = 0;
  EZ_WidgetPadX(tmp) = EZ_WidgetPadY(tmp) = 0;
  EZ_WidgetSepX(tmp) = EZ_WidgetSepY(tmp) = 0;
  EZ_SetWidgetFocusableFlag(tmp);
  EZ_RawXWinPHandle(tmp) = NULL;
  memset(EZ_RawXWinPData(tmp), 0, sizeof(EZ_RawXWinPData(tmp)));

  return(tmp);
}

/*************************************************************************/
void EZ_SetupRawXWinWidget(wptr, csize, draw, freedata, ehandle)
     EZ_Widget *wptr;
     void  (*csize)  MY_ANSIARGS(( EZ_Widget *widget, int *w, int *h));
     void  (*draw)  MY_ANSIARGS((EZ_Widget *widget));
     void  (*freedata) MY_ANSIARGS((EZ_Widget *widget));
     void  (*ehandle)  MY_ANSIARGS((EZ_Widget *widget, XEvent *event));
{
  if(wptr && EZ_WidgetType(wptr) == EZ_WIDGET_RAW_XWINDOW)
    {
      EZ_UDFWHandle *ptr = (EZ_UDFWHandle *) &EZ_RawXWinPData(wptr);
      ptr->ComputeSize = csize;
      ptr->DrawWidget = draw;
      ptr->FreeData = freedata;
      ptr->EventHandle = ehandle;
      EZ_RawXWinPHandle(wptr) = ptr;
    }
}
/*************************************************************************/
void EZ_FreeWidgetRawXWinData(widget)
     EZ_Widget *widget;
{
  if(widget)
    {
      EZ_UDFWHandle *ptr = EZ_RawXWinPHandle(widget);
      if(ptr && UdfFreeData(ptr)) UdfFreeData(ptr)(widget);
    }
}
 
/********************************************************************
 *
 *  Figure out the dimension of a label widget.
 */

void EZ_ComputeWidgetRawXWinSize(widget, w, h)
    EZ_Widget *widget;
    int             *w, *h;
{
  int ch= 4, cw=4;
  EZ_UDFWHandle *ptr = EZ_RawXWinPHandle(widget);
  if(ptr && UdfComputeSize(ptr) ) (UdfComputeSize(ptr))(widget, &cw, &ch);

  *w = cw;
  *h = ch;
  EZ_SetWidgetSizeComputedFlag(widget);	
}

/*******************************************************************
 *
 *  Draw does nothing
 */
void  EZ_DrawWidgetRawXWin(wptr)
     EZ_Widget *wptr;
{
  if(wptr)
    {
      EZ_UDFWHandle *ptr = EZ_RawXWinPHandle(wptr);
      if(ptr && UdfDraw(ptr)) UdfDraw(ptr)(wptr);
    }
}

/*******************************************************************
 *
 *  Handle no events;
 */
void EZ_RawXWinEventHandle(widget, event)
     EZ_Widget *widget;
     XEvent *event;
{
  if( EZ_GetWidgetDisabledFlag(widget) && event->type != Expose )  return;
  {
    EZ_UDFWHandle *ptr = EZ_RawXWinPHandle(widget);
    if(ptr && UdfEHandle(ptr)) UdfEHandle(ptr)(widget,event);
  }
}

/****************************************************************************/
void EZ_SetupUDFWidget(widget)
     EZ_Widget *widget;
{
  if(widget && EZ_WidgetType(widget) == EZ_WIDGET_RAW_XWINDOW)
    {
      EZ_UDFWHandle *ptr = EZ_RawXWinPHandle(widget);
      if(ptr && UdfSetup(ptr)) UdfSetup(ptr)(widget);
    }
}

/****************************************************************************/
void EZ_RegisterWidget(type,setup, csize, draw, freedata, ehandle)
     int   type;
     void  (*setup) MY_ANSIARGS((EZ_Widget *widget));
     void  (*csize)  MY_ANSIARGS(( EZ_Widget *widget, int *w, int *h));
     void  (*draw)  MY_ANSIARGS((EZ_Widget *widget));
     void  (*freedata) MY_ANSIARGS((EZ_Widget *widget));
     void  (*ehandle)  MY_ANSIARGS((EZ_Widget *widget, XEvent *event));
{
  EZ_UDFWHandle *udf = NULL, **ptr = &udfhandles;
  int found = 0;

  if(type < 65536)
    {
      fprintf(stderr, "EZ_RegisterWidget: type '%d' is invalid, must be bigger than 65536.\n",type);
      return;
    }

  while(*ptr != NULL)
    {
      if( (*ptr)->utype == type)
	{
	  udf = *ptr;
	  found = 1;
	  break;
	}
      ptr = &((*ptr)->next);
    }
  if(udf == NULL)
    udf = (EZ_UDFWHandle *)my_malloc(sizeof(EZ_UDFWHandle), _MISC_DATA_);
  if(udf == NULL) EZ_OutOfMemory("EZ_RegisterWidget");
  udf->utype = type;
  udf->Setup = setup;
  udf->ComputeSize = csize;
  udf->DrawWidget = draw;
  udf->FreeData = freedata;
  udf->EventHandle = ehandle;
  if(found == 0)
    {
      udf->next = udfhandles;
      udfhandles = udf;
    }
}
/************************************************************************/
void *EZ_SearchUDFWidgetHandle(type)
     int type;
{
  EZ_UDFWHandle **ptr = &udfhandles;
  while(*ptr != NULL)
    {
      if( (*ptr)->utype == type)
	{
	  return(*ptr);
	  break;
	}
      ptr = &((*ptr)->next);
    }
  return(NULL);
}
/************************************************************************/
void EZ_DeleteAllUDFWidgetHandles()
{
  EZ_UDFWHandle *tmp, *ptr = udfhandles;  
  while(ptr)
    {
      tmp = ptr->next;
      (void)my_free((char *)ptr);
      ptr = tmp;
    }
  udfhandles = NULL;
}
/**************************************************************************/
GC    EZ_GetWritableGC()
{
  return (EZ_WRITABLEGC);
}
/**************************************************************************/
#undef _EZ_WIDGET_RAWXWIN_C_
