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

     FONCTION :
     ----------
        File OpenGl_ws :
 

     REMARQUES:
     ----------       

     HISTORIQUE DES MODIFICATIONS   :
     --------------------------------
       xx-xx-xx : xxx ; Creation.
       02-07-96 : FMN ; Suppression WSWSHeight, WSWSWidth et WSType
       17-07-96 : FMN ; Ajout WSZbuffer
       24-04-97 : FMN ; (PRO4063) Ajout displaylist pour le mode transient
       27-07-97 : CAL ; Portage NT (GLuint)
       28-08-97 : PCT ; ajout texture mapping
       13-03-98 : FMN ; Suppression variable WSNeedsClear
       08-07-98 : FMN ; Changement du nom de la primitive call_togl_erase_immediat_mode()
			-> call_togl_erase_animation_mode.

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

#define G003	/* EUG 11-01-00 backfacing management 
*/

#define OCC1188 /* SAV 23/12/02 background texture management */

/*----------------------------------------------------------------------*/
/*
 * Includes
 */ 


#ifndef WNT
#include <X11/X.h>
#include <GL/glx.h>
#endif

#include <OpenGl_tgl_all.h>

#include <OpenGl_tsm_ws.h>
#include <OpenGl_cmn_memory.h>
#include <OpenGl_cmn_stg_tbl.h>
#include <OpenGl_cmn_htbl.h>
#include <OpenGl_animation.h>

/*----------------------------------------------------------------------*/
/*
 * Constantes
 */ 

#define  WS_HTBL_SIZE  23
#define  BUC61044    /* 25/10/01 SAV ; added functionality to control gl depth testing
			from higher API */
#define  BUC61045    /* 25/10/01 SAV ; added functionality to control gl lighting 
			from higher API */

/*----------------------------------------------------------------------*/
/*
 * Types definitions
 */ 

#ifdef OCC1188
/* background texture properties */
typedef struct 
{
    Tuint texId;
    Tint width;
    Tint height;
    Tint style; /* 0 - centered, 1 - tiled, 2 - stretch */
} WS_BG_TEXTURE, *ws_bg_texture;
#endif

typedef  struct
{
    Tint    texture_env;
    Tint    surface_detail;
    void    *filters;
    Tint     window;
    Tint     width;
    Tint     height;
    Tint     d_buff;
    Tint     view_stid;
    void    *lights;
    void    *views;
    Tfloat   backg[3];
    void    *highlights;
    void    *depthcues;
    Tint     update_state;
    Tint     transparency;
    Tint     zbuffer;
    Tint     transient;
    Tint     retainMode;
#ifndef WNT
    Pixmap   pixmap_id;
    GLXPixmap
             glx_pixmap;
    Tint     wsdepth;
#endif
#ifdef G003
    Tint     backfacing;
#endif  /* G003 */

#ifdef BUC61044
    Tint     depth_test;
#endif
#ifdef BUC61045
    Tint     ws_gllight;
#endif
#ifdef OCC1188    
    WS_BG_TEXTURE bgTexture;
#endif /* OCC1188 */
} WS_REC, *ws_rec;

typedef struct LNODE_
{
   struct LNODE_ *next;
   Tint           ws_id;
} TEL_LNODE, *tel_lnode;


/*----------------------------------------------------------------------*/
/*
 * Variables statiques
 */ 

static  cmn_htbl       ws_htbl;
static  cmn_stg_tbl    ws_stbl;

static tel_lnode ws_list_head;

/*----------------------------------------------------------------------*/

TStatus
TsmRegisterWsid( Tint wsid )
{
    if( !ws_htbl )
    {
        ws_htbl = cmn_create_htbl( WS_HTBL_SIZE );
        if( !ws_htbl )
            return TFailure;
        ws_stbl = cmn_stg_tbl_create( WS_HTBL_SIZE, sizeof(WS_REC) );
        if( !ws_stbl )
            return TFailure;
    }

    cmn_add_in_htbl( ws_htbl, wsid, 0 );

    {
       tel_lnode n;
       n = ws_list_head;
       while( n != 0 )
       {
	  if( n->ws_id == wsid )
	      break;
	  n = n->next;
       }
       if( n == 0 )
       {
	  n = (tel_lnode)cmn_getmem( 1, sizeof(TEL_LNODE), 0 );
	  n->next = ws_list_head;
	  n->ws_id = wsid;
	  ws_list_head = n;
       }
    }

    return TSuccess;
}

/*----------------------------------------------------------------------*/

TStatus
TsmSetWSAttri( Tint wsid, TWSAttri  attri, cmn_key_data data )
{
    cmn_htbl_elem  rec;
    ws_rec         wsr;

    if( !ws_htbl )
	return TFailure;

    rec = cmn_find_in_htbl( ws_htbl, wsid, (void**)&wsr );
    if( !rec )
	return TFailure;

    if( !wsr )
    {
	wsr = cmn_stg_tbl_get( ws_stbl );
	if( !wsr )
	    return TFailure;
        cmn_add_in_htbl( ws_htbl, wsid, wsr );
    }
    switch( attri )
    {
        case WSTextureEnv:
            wsr->texture_env = data->ldata;
	    break;

        case WSSurfaceDetail:
	    wsr->surface_detail = data->ldata;
	    break;

	case  WSFilters:
	    wsr->filters = data->pdata;
	    break;

	case  WSWindow:
	    wsr->window = data->ldata;
	    break;

	case  WSWidth:
	    wsr->width = data->ldata;
	    break;

	case  WSHeight:
	    wsr->height = data->ldata;
	    break;

	case  WSDbuff:
	    wsr->d_buff = data->ldata;
	    break;

	case  WSViewStid:
	    wsr->view_stid = data->ldata;
	    break;

	case  WSLights:
	    wsr->lights = data->pdata;
	    break;

	case  WSViews:
	    wsr->views = data->pdata;
	    break;

	case  WSBackground:
	    wsr->backg[0] = ((Tfloat*)data->pdata)[0],
	    wsr->backg[1] = ((Tfloat*)data->pdata)[1],
	    wsr->backg[2] = ((Tfloat*)data->pdata)[2];
	    break;

	case  WSHighlights:
	    wsr->highlights = data->pdata;
	    break;

	case  WSDepthCues:
	    wsr->depthcues = data->pdata;
	    break;

	case  WSTransparency:
	    wsr->transparency = data->ldata;
	    break;

	case  WSZbuffer:
	    wsr->zbuffer = data->ldata;
	    break;

	case  WSTransient:
	    wsr->transient = data->ldata;
	    break;

	case  WSRetainMode:
	    wsr->retainMode = data->ldata;
	    break;

	case  WSUpdateState:
	    wsr->update_state = data->ldata;
	    break;

#ifndef WNT
	case  WSPixmap:
	    wsr->pixmap_id = data->pixmap;
	    break;

	case  WSGLXPixmap:
	    wsr->glx_pixmap = data->glxpixmap;
	    break;

	case  WSDepth:
	    wsr->wsdepth = data->ldata;
	    break;
#endif
#ifdef G003
    	case WSBackfacing:
     	    wsr -> backfacing = data -> ldata;
    	    break;
#endif  /* G003 */

#ifdef BUC61044
	case WSDepthTest:
	    wsr->depth_test = data->ldata;
	    break;
#endif
#ifdef BUC61045
	case WSGLLight:
	    wsr->ws_gllight = data->ldata;
	    break;
#endif
#ifdef OCC1188
        case WSBgTexture : 
	  wsr->bgTexture.texId = ((Tuint*)data->pdata)[0],
	  wsr->bgTexture.width = ((Tint*)data->pdata)[1],
	  wsr->bgTexture.height = ((Tint*)data->pdata)[2];
            wsr->bgTexture.style = ((Tint*)data->pdata)[3];
            break;
#endif
    	default:
	    break;
    }

    return TSuccess;
}

/*----------------------------------------------------------------------*/

TStatus
TsmGetWSAttri( Tint wsid, TWSAttri attri, cmn_key_data data )
{
    cmn_htbl_elem  rec;
    ws_rec         wsr;

    if( !ws_htbl )
	return TFailure;

    rec = cmn_find_in_htbl( ws_htbl, wsid, (void**)&wsr );
    if( !rec )
	return TFailure;

    if( !wsr )
    {
	wsr = cmn_stg_tbl_get( ws_stbl );
	if( !wsr )
	    return TFailure;
        cmn_add_in_htbl( ws_htbl, wsid, wsr );
    }

    switch( attri )
    {
        case WSTextureEnv:
	  data->ldata = wsr->texture_env;
	  break;

        case WSSurfaceDetail:
	  data->ldata = wsr->surface_detail;
	  break;

	case  WSFilters:
	    data->pdata = wsr->filters;
	    break;

	case  WSWindow:
	    data->ldata = wsr->window;
	    break;

	case  WSWidth:
	    data->ldata = wsr->width;
	    break;

	case  WSHeight:
	    data->ldata = wsr->height;
	    break;

	case  WSDbuff:
	    data->ldata = wsr->d_buff;
	    break;

	case  WSViewStid:
	    data->ldata = wsr->view_stid;
	    break;

	case  WSLights:
	    data->pdata = wsr->lights;
	    break;

	case  WSViews:
	    data->pdata = wsr->views;
	    break;

	case  WSBackground:
	    data->pdata = wsr->backg;
	    break;

	case  WSHighlights:
	    data->pdata = wsr->highlights;
	    break;

	case  WSDepthCues:
	    data->pdata = wsr->depthcues;
	    break;

	case  WSTransparency:
	    data->ldata = wsr->transparency;
	    break;

	case  WSZbuffer:
	    data->ldata = wsr->zbuffer;
	    break;

	case  WSTransient:
	    data->ldata = wsr->transient;
	    break;

	case  WSRetainMode:
	    data->ldata = wsr->retainMode;
	    break;

	case  WSUpdateState:
	    data->ldata = wsr->update_state;
	    break;

#ifndef WNT
	case  WSPixmap:
	    data->pixmap = wsr->pixmap_id;
	    break;

	case  WSGLXPixmap:
	    data->glxpixmap = wsr->glx_pixmap;
	    break;

	case  WSDepth:
	    data->ldata = wsr->wsdepth;
	    break;
#endif
#ifdef G003
    	case WSBackfacing:
     	    data -> ldata = wsr -> backfacing;
    	    break;
#endif  /* G003 */

#ifdef BUC61044
	case WSDepthTest:
	    data->ldata = wsr->depth_test;
	    break;
#endif
#ifdef BUC61045
	case WSGLLight:
	    data->ldata = wsr->ws_gllight;
	    break;
#endif
#ifdef OCC1188
        case WSBgTexture : 
    	    data->pdata = &wsr->bgTexture;
            break;
#endif

        default:
	    break;
    }

    return TSuccess;
}

/*----------------------------------------------------------------------*/

TStatus
TsmGetWSPosted( Tint struct_id, Tint size, Tint *ws, Tint *actual_size )
{
    cmn_htbl_elem  rec;
    ws_rec         wsr;
    Tint           i=0;
    tel_lnode      n;

    if( !ws_htbl )
	return TFailure;

    n = ws_list_head;

    *actual_size = 0;

    while( n != 0 )
    {
       rec = cmn_find_in_htbl( ws_htbl, n->ws_id, (void**)&wsr );
       if( !rec )
	   return TFailure;

       if( !wsr )
       {
	  n = n->next;
	  continue;
       }

       if( wsr->view_stid == struct_id )
       {
	   (*actual_size)++;
	   if( size > i )
	       ws[i++] = n->ws_id;
       }

       n = n->next;
   }

   return TSuccess;
}

/*----------------------------------------------------------------------*/

TStatus
TsmUnregisterWsid( Tint wsid )
{
    ws_rec wsr;

    cmn_delete_from_htbl( ws_htbl, wsid, (void **)&wsr );
    cmn_stg_tbl_free( wsr );

    {
       tel_lnode n, prev;
       prev = ws_list_head;

       /* traitement de la tete de liste */
       if( prev->ws_id == wsid )
       {
           ws_list_head = prev->next;
           cmn_freemem( prev );
           return TSuccess;
       }

       n = prev->next;
       while( n != 0 )
       {
	  if( n->ws_id == wsid )
          {
             prev->next = n->next;
             cmn_freemem( n );
             return TSuccess;
          }
          prev = n;
	  n = n->next;
       }
    }
    return TSuccess;
}

/*----------------------------------------------------------------------*/

TStatus
TsmInitUpdateState()
{
    cmn_htbl_elem  rec;
    ws_rec         wsr;
    tel_lnode      n;

    if( !ws_htbl )
	return TFailure;

    n = ws_list_head;
    while( n != 0 )
    {
       rec = cmn_find_in_htbl( ws_htbl, n->ws_id, (void**)&wsr );
       if( !rec )
	   return TFailure;

       if( !wsr )
	  n = n->next;
       else
       {
	  wsr->update_state = TNotDone;
	  (void) call_togl_erase_animation_mode();
	  n = n->next;
       }
    }
    return TSuccess;
}

/*----------------------------------------------------------------------*/
