#include "copyright.h"
/******************************************************************
 *
 * highlightclass.c --
 *
 *     Implementation of highlighted graph elements.
 *
 * $Author: mstoufer $
 * $Source: /home/g2/src/projects/NetLogger/src/nlv/highlightclass.c,v $
 * $RCSfile: highlightclass.c,v $
 * $Revision: 1.1.1.1 $
 * $Locker:  $
 * $Date: 2000/12/05 19:52:32 $
 *
 *
 ******************************************************************
 */
static char rcsid[] = "$Id: highlightclass.c,v 1.1.1.1 2000/12/05 19:52:32 mstoufer Exp $";

#include "highlightclass.h"

/*========= DATA =====================================================*/

extern Tcl_Interp *Et_Interp;
extern Nlv_err eobj;
extern Nlv_State nlvState;

struct SimpleElt {
  Element *addr;
};

#define T Nlv_hi
struct T {
  Graph            *ghandle;
  char             *symbol;
  struct SimpleElt *elts;
  int               numElts;
  int               numFull;
};

#define SIZE_JUMP 8

/*========= FUNCTIONS ================================================*/

/* Private functions */
Element *Nlv_hiMakeNewElement( T this, int idx);
Element *Nlv_hiGetElementAddr( T this, int idx );
void     Nlv_hiSetSize( T this, int sz );


/*
 *----------------------------------------------------------------------
 *
 * New -- Allocate new object.
 *
 * Calls: malloc
 *
 * Algorithm:
 *
 *----------------------------------------------------------------------
 */

T Nlv_hiNew( )
{
  T this = ( T ) malloc( sizeof( struct T ) );

  this->symbol  = NULL;
  this->elts    = NULL;
  this->numElts = 0; 
  this->numFull = 0;

  return this;
}


/*
 *----------------------------------------------------------------------
 *
 * Init -- Set up object.
 *
 *----------------------------------------------------------------------
 */
 void Nlv_hiInit( T this )
 {
   this->symbol  = strdup("scross");
   this->ghandle = Nlv_grGetGraphPtr( nlvState.gr );
 }


/*
 *----------------------------------------------------------------------
 *
 * SetSymbol -- The drawing symbol for all elements.
 *
 *----------------------------------------------------------------------
 */
 void Nlv_hiSetSymbol( T this, const char *newSymbol )
 {
   if ( this->symbol )
     free( this->symbol );
   this->symbol = strdup( newSymbol );
 }


/*
 *----------------------------------------------------------------------
 *
 * SetColor -- The drawing color for a single element.
 *
 *----------------------------------------------------------------------
 */
 void Nlv_hiSetColor( T this, int idx, const char *matchElt )
 {
   char buf[ 64 ];

   if ( idx < 0 || idx >= this->numFull )
      return;

   sprintf(buf,"ColorHighlight hi%d %s",idx,matchElt);
   Tcl_Eval( Et_Interp, buf ); 
 }


/*
 *----------------------------------------------------------------------
 *
 * SetSize -- Change array size.
 *
 * Arguments: size of data
 * Calls: Nlv_hiMakeNewElement
 *
 *----------------------------------------------------------------------
 */

 void Nlv_hiSetSize( T this, int sz )
 {
    int oldsz;
    int i;

    oldsz = this->numElts;
   
    if ( sz < oldsz ) 
      return;

    this->elts = (struct SimpleElt *) realloc( this->elts, sz * sizeof(struct SimpleElt) ); 
    this->numElts = sz;

    for ( i=oldsz; i < sz; i++ )
      this->elts[i].addr = Nlv_hiMakeNewElement( this, i );
 }


/*
 *----------------------------------------------------------------------
 *
 * MakeNewElement -- Create a new (empty) element.
 *
 * Param : index of element
 * Return: address of element in BLT
 * Calls : Nlv_hiGetElementAddr, Tcl->makeHighlight
 *
 *----------------------------------------------------------------------
 */
Element *
Nlv_hiMakeNewElement( T this, int idx)
{
  char buf[256];
  Element * e;
  Nlv_EInfo einfo;
  
  sprintf( buf, "MakeHighlight \"%s\" hi%d", this->symbol, idx); 

  if ( TCL_OK != Tcl_Eval( Et_Interp, buf )) {
    NLV_SET_EINFO( einfo, 100, 0 );
    Nlv_errReport( eobj, &einfo,"Tcl error '%s' "
		   "while evaluating '%s'", Et_Interp->result, buf );
    return NULL;
  }

  e = Nlv_hiGetElementAddr( this, idx );

  if ( e == NULL ) {
    NLV_SET_EINFO( einfo, 100, 0 );
    Nlv_errReport( eobj, &einfo,"Null hashtable entry for element "
		   "'hi%d'", idx );
    return NULL;
  }
  e->x.numValues = e->y.numValues = 2;
  e->x.min = e->y.min = 0;
  e->x.valueArr = (double *) malloc( 2 * sizeof(double) );
  e->y.valueArr = (double *) malloc( 2 * sizeof(double) );
  
  return e;
}


/*
 *----------------------------------------------------------------------
 *
 * GetElementAddr -- Ask BLT for the address of the element
 *                   which is highlight #i
 *
 * Param : index of element
 * Return: address of element in BLT
 * Calls : Tcl_Eval
 *
 *----------------------------------------------------------------------
 */
Element *
Nlv_hiGetElementAddr( T this, int idx )
{
  int status;
  char buf[16];
  Nlv_EInfo einfo;
  Element *elementPtr = NULL;

  sprintf( buf, "hi%d", idx );
  status = Blt_NameToElement( this->ghandle, buf, &elementPtr );
  if ( status != TCL_OK ) {
    NLV_SET_EINFO( einfo, 100, 0 );
    Nlv_errReport( eobj, &einfo,"Cannot find element in graph "
                     "'hi%d'", idx );
    return NULL;
  }

  return elementPtr;
}


/*
 *----------------------------------------------------------------------
 *
 * AddCoords -- Set the x,y of next un-set element. 
 *
 * Param : x,y of element
 * Return: # of elements added ( 0=failure ).
 *
 *----------------------------------------------------------------------
 */
int Nlv_hiAddCoords( T this, double x, double y )
{
  Element * e;
  int       i;
  
  if ( this->numFull >= this->numElts )
    Nlv_hiSetSize( this, this->numElts + SIZE_JUMP );
  
  /* If element addr is uninitialized, fetch it from BLT */
  if ( NULL == (e = this->elts[ this->numFull ].addr) ) { 
    e = Nlv_hiGetElementAddr( this, this->numFull );
 /* fprintf(stderr,"<dbg> AddCoords: set elt[%d].addr=%p\n", this->numFull, e); */
    this->elts[ this->numFull ].addr = e;
  }
 
  if ( e != NULL ) { 
    /* fprintf(stderr, "<dbg> AddCoords: numFull=%d\n",this->numFull); */
    for ( i=0; i < 2; i++ ) {
      e->x.valueArr[i] = x;
      e->y.valueArr[i] = y;
    }
    e->x.numValues = e->y.numValues = 2;
    return this->numFull++;
  }
  else {
    /* fprintf(stderr,"<dbg> AddCoords: !e\n"); */
    return this->numFull;
  }
}


/*
 *----------------------------------------------------------------------
 *
 * ClearAll -- Clear the array, but do not change size.
 *
 * Return: none
 *
 *----------------------------------------------------------------------
 */
void Nlv_hiClearAll( T this )
{
  int i,j;
  
  for ( i=0; i < this->numFull; i++ ) {
    if ( this->elts[i].addr != NULL ) {
      for ( j=0; j < 2; j++ ) {
        this->elts[i].addr->x.valueArr[j] = -1;
        this->elts[i].addr->y.valueArr[j] = -1;
      }
      /* fprintf(stderr,"<dbg>clear highlight %d\n",i); */
      this->elts[i].addr = NULL;
    }
  }
  this->numFull = 0;
}


/*
 *----------------------------------------------------------------------
 *
 * Get -- Retrieve 1 element in array (or NULL).
 *
 * Return: Pointer to element.
 *
 *----------------------------------------------------------------------
 */
Element * Nlv_hiGet( T this, int idx )
{
  return NULL;

  if ( idx < 0 || idx >= this->numFull )
    return NULL;
  
  return this->elts[idx].addr;
}


/*
 *----------------------------------------------------------------------
 *
 * Draw -- Draw/redraw all elements on the graph.
 *
 * Return: none.
 *
 *----------------------------------------------------------------------
 */
void Nlv_hiDraw( T this )
{
  Blt_EventuallyRedrawGraph( this->ghandle );
}
