
#include <OpenGl_tgl_all.h>
#include <stddef.h>
#include <OpenGl_cmn_memory.h>
#include <OpenGl_cmn_stg_tbl.h>

#define QUAD_WORD_OFFSET sizeof(double)

static cmn_stg_elem
cmn_stg_tbl_add_page(cmn_stg_tbl tbl)
{
   register char *p;
   cmn_stg_elem   r;
   void     **q;
   register cmn_stg_elem s;
   register Tint  size , i , num , j ;

   if(tbl == 0)
      return 0;

   num   = tbl -> num  ;
   j = ( num < 0 ) ? num = -num , 0 : 1 ;
   size  = tbl -> size ;

   i     = size ;
   i    *= num ;
   i    += (2 * sizeof(void *)) ;
   p = cmn_getmem( 1 , i , j ) ;
   if( p == 0 )
      return 0;

   q = (void **)p ;

   *q = tbl -> next_page;
   tbl -> next_page = p ;

   p += ( 2 * sizeof(void *) ) ;
   r = (cmn_stg_elem)p;

   s  = r;
   for( i = 1 ; i < num ; i++                             ,
                          p += size                       ,
                          s -> next = (cmn_stg_elem)p ,
                          s -> chap = __CHAP2             ,
                          s = (cmn_stg_elem)p         ) ;
   s = (cmn_stg_elem)p ,
   s -> next = 0,
   s -> chap = __CHAP2 ;

   tbl -> tot_no_rec += num ;

   return r;
}

cmn_stg_tbl
cmn_stg_tbl_create( Tint num, Tint size )
{
   register Tint i ;
   register cmn_stg_tbl q;

   if(num == 0 || size <= 0)
      return 0;

   i = size;
   i %= QUAD_WORD_OFFSET ;
   if ( i )
       i -= QUAD_WORD_OFFSET , size -= i ;

   size += offsetof( CMN_STG_ELEM, data );

   q = cmn_getmem( 1 , sizeof( CMN_STG_TBL ) , 1 );
   if( q == 0 )
      return 0;

   q -> num  = num ;
   q -> size = size;

   return( q );

}

void *
cmn_stg_tbl_get( cmn_stg_tbl tbl )
{
   register cmn_stg_elem q;

   if(tbl == 0)
      return 0;

   q = tbl -> free_ptr;

   if( q == 0 )
   {
     q = cmn_stg_tbl_add_page( tbl ) ;
     if( q == 0 )
        return 0;
   }

   tbl  -> free_ptr = q -> next;
   (tbl -> cur_no_rec)++ ;

   q -> next =  (cmn_stg_elem)tbl;
   q -> chap =  __CHAP1;

   return( (void *)&(q -> data[0]) );
}

TStatus
cmn_stg_tbl_free( void *rec )
{
   cmn_stg_elem elem;
   register cmn_stg_tbl  tbl;

   if( rec == 0 )
      return TFailure;

   elem = (cmn_stg_elem)( (char *)rec - offsetof(CMN_STG_ELEM, data) );

   if( elem -> chap != __CHAP1 )
   {
     /* "cmn_stg_tbl_free() Invalid ptr." */
     return TFailure;
   }
   tbl = (cmn_stg_tbl)(elem -> next ) ;

   if( tbl -> num > 0 )
       cmn_memset( elem , 0 , tbl -> size ) ;

   elem -> next = tbl -> free_ptr,
   tbl  -> free_ptr = elem,

   elem -> chap = __CHAP2 ;
   (tbl -> cur_no_rec)-- ;

   return TSuccess;
}

TStatus
cmn_stg_tbl_kill( cmn_stg_tbl tbl )
{
    void  *cur_page, *nxt_page ;

    if ( tbl == 0 )
        return TFailure;

    cur_page = tbl -> next_page;

    while ( cur_page )
    {
        nxt_page = *( (void **)cur_page ) ;
        cmn_freemem( cur_page ) ;
        cur_page = nxt_page ;
    }

    cmn_freemem( tbl ) ;
    return TSuccess;
}
