/***********************************************
 (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************************
 $Log: clrAT.c,v $
 * Revision 2.5  1993/09/20  14:16:40  eps
 * new function: ATcp
 *
 * Revision 2.4  1993/01/12  16:34:50  eps
 * portability issues
 *
 * Revision 2.3  1992/11/17  11:48:08  eps
 * fix definition of *alloc for PC portability
 *
 * Revision 2.2  1992/01/14  15:43:22  eps
 * distribution issues
 *
 * Revision 2.1  90/10/30  08:34:14  eps
 * hardwired colours added
 * new colours I2, IAT, AT
 * ! is no longer used as colour delimiter
 * still some bugs are known w.r.t. colour deallocation
 * 
 **********************************************/

#ifndef lint
static char rcsid[]= "$Id: clrAT.c,v 2.5 1993/09/20 14:16:40 eps Exp $";
#endif

/***********************************************************************
	Jose A. Manas
        dpt. Ingenieria Telematica
        E.T.S.I. Telecomunicacion
        Ciudad Universitaria
        E-28040  MADRID
        jmanas@dit.upm.es

        Tables of Attributes
 **********************************************************************/

/* LINTLIBRARY */

# define cast_IMP
# include "cast.hh"

# include <stdio.h>
# include <string.h>

PRIVATE TNODE node={0, NULL, NULL, NULL, NULL, NULL, NULL};

PUBLIC AT*
ATcreate (size, incr)
  int size, incr;
{
  AT* tbl;
  int s;

  tbl= (AT*) malloc (sizeof (AT));
  if (tbl == NULL)
    fatal ("ATcreate: run out of memory");
  tbl->size= 0;
  if (incr < 0)
    s= size;
  else if (incr == 0)
    for (s= 4; s < size; s*= 2)
      ;
  else
    for (s= incr; s < size; s+= incr)
      ;
  tbl->max= s;
  tbl->incr= incr;
  tbl->data= (ATdata*) malloc (s * sizeof (ATdata));
  if (tbl->data == NULL)
    fatal ("ATcreate: run out of memory for data");
  return tbl;
}

PUBLIC int
ATinc (tbl)
  AT* tbl;
{
  int s;

  if (tbl->size >= tbl->max) {
    if (tbl->incr < 0) {
      (void) fprintf (stderr, "AT colour: cannot expand fixed table\n");
      exit (1);
    }
    else if (tbl->incr == 0)
      for (s= 4; s < tbl->max+1; s*= 2)
	;
    else
      for (s= tbl->incr; s < tbl->max+1; s+= tbl->incr)
	;
    tbl->data= (ATdata*) realloc (tbl->data, s * sizeof (ATdata));
    if (tbl->data == NULL)
      fatal ("colour AT cannot get memory for expansion");
    tbl->max= s;
  }
  tbl->data[tbl->size].value0= NULL;
  tbl->data[tbl->size].value1= NULL;
  tbl->data[tbl->size].attrs= NULL;
  return tbl->size++;
}

/* similar to cp_node () */

PUBLIC int
ATcp (tbl, i, shr)
  AT* tbl;
  int i;
  short shr;
{
  static TNODE old= {0, NULL, NULL, NULL, NULL, NULL, NULL};
  static TNODE new= {0, NULL, NULL, NULL, NULL, NULL, NULL};
  int n;

  n= ATinc (tbl);
  if (shr)
  { old.value0= tbl->data[i].value0;
    old.value1= tbl->data[i].value1;
    old.attrs= tbl->data[i].attrs;
    copyattrs (&new, &old);
    tbl->data[n].value0= new.value0;
    tbl->data[n].value1= new.value1;
    tbl->data[n].attrs= new.attrs;
    new.value0= NULL;
    new.value1= NULL;
    new.attrs= NULL;
  }
  return n;
}

PUBLIC CLR_TYPE
getAT (fp)
    FILE* fp;
{
  AT* tbl;
  int i;

  tbl= (AT*) malloc (sizeof (AT));
  if (tbl == NULL)
    fatal ("ATcreate: run out of memory");
  (void) fscanf (fp, "%d %d\n",
		 &(tbl->size), &(tbl->incr));
  tbl->max= tbl->size;
  tbl->data= (ATdata*) malloc (tbl->size * sizeof (ATdata));
  if (tbl->data == NULL)
    fatal ("getAT: run out of memory for data");
  for (i= 0; i < tbl->size; i++) {
    node.value0= NULL;
    node.value1= NULL;
    node.attrs= NULL;
    getattrs (fp, &node);
    tbl->data[i].value0= node.value0;
    tbl->data[i].value1= node.value1;
    tbl->data[i].attrs= node.attrs;
  }
  return (CLR_TYPE) tbl;
}

PUBLIC void
putAT (fp, val)
    FILE* fp;
    CLR_TYPE val;
{
  AT* tbl= (AT*) val;
  int i;

  fprintf (fp, "%d %d\n", tbl->size, tbl->incr);
  for (i= 0; i < tbl->size; i++) {
    node.value0= tbl->data[i].value0;
    node.value1= tbl->data[i].value1;
    node.attrs= tbl->data[i].attrs;
    putattrs (fp, &node);
  }
}

PUBLIC TATTR*
ATadd (tbl, i, attr)
     AT* tbl;
     int i;
     int attr;
{
  TATTR* lclattr;

  node.attrs= tbl->data[i].attrs;
  lclattr= add_attr (attr, &node);
  tbl->data[i].attrs= node.attrs;
  return lclattr;
}

PUBLIC void
ATset (tbl, i, attr, value)
     AT* tbl;
     int i;
     int attr;
     CLR_TYPE value;
{
  node.attrs= tbl->data[i].attrs;
  set_attr (attr, &node, value);
  tbl->data[i].attrs= node.attrs;
}

PUBLIC TATTR*
ATfind (tbl, i, attr)
     AT* tbl;
     int i;
     int attr;
{
  node.attrs= tbl->data[i].attrs;
  return find_attr (attr, &node);
}

PUBLIC TATTR*
ATfadd (tbl, i, attr)
     AT* tbl;
     int i;
     int attr;
{
  TATTR* lclattr;

  node.attrs= tbl->data[i].attrs;
  lclattr= fadd_attr (attr, &node);
  tbl->data[i].attrs= node.attrs;
  return lclattr;
}

PUBLIC TATTR*
ATtake (tbl, i, attr)
     AT* tbl;
     int i;
     int attr;
{
  TATTR* lclattr;

  node.attrs= tbl->data[i].attrs;
  lclattr= take_attr (attr, &node);
  tbl->data[i].attrs= node.attrs;
  return lclattr;
}
