/***********************************************
 (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************************
 $Log: clrbsc.c,v $
 * Revision 2.6  1994/06/02  17:18:26  eps
 * minor bug
 *
 * Revision 2.5  1993/01/12  16:34:10  eps
 * portability issues
 *
 * Revision 2.4  1992/11/17  11:47:11  eps
 * fix definition of *alloc for PC portability
 *
 * Revision 2.3  1992/01/14  15:42:49  eps
 * distribution issues
 *
 * Revision 2.2  91/04/10  09:55:13  eps
 * table driven rag phases
 * 
 * Revision 2.1  90/10/30  08:32:21  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
 * 
 * Revision 1.7  90/06/21  15:24:38  eps
 * change calloc for chunk malloc
 * recode type2clr to use a linear array rather than a hash table
 * 
 * Revision 1.6  90/06/04  15:14:25  eps
 * optimize type2clr for OTHERS
 * 
 * Revision 1.5  90/05/10  17:11:22  eps
 * new global variable befussy
 * that complaints for non explicitly declared colours in TIOCOLOURS
 * 
 * Revision 1.4  90/03/16  15:43:33  eps
 * *2clr returns OTHERS if name/type unknown
 * hash table are traversed modulus their size
 * 
 * Revision 1.3  90/02/19  19:08:09  eps
 * internal hashing for TIOCOLOURS, type and keyword
 * 
 * Revision 1.2  90/01/29  14:51:38  eps
 * fixing license details
 * 
 * Revision 1.1  90/01/25  17:59:27  eps
 * Initial revision
 * 
 **********************************************/

#include "version.h"
#ifndef lint
static char rcsid[]= "$Id: clrbsc.c,v 2.6 1994/06/02 17:18:26 eps Exp $";
#endif

/***********************************************************************
        Tomas P. de Miguel Moro
	Jose A. Manas
        dpt. Ingenieria Telematica
        E.T.S.I. Telecomunicacion
        Ciudad Universitaria
        E-28040  MADRID

        tmiguel@dit.upm.es
        jmanas@dit.upm.es

        colouring basics
 **********************************************************************/

/* LINTLIBRARY */

# define cast_IMP
# include "cast.hh"

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

PRIVATE TIOCOLOURS* iocolours= NULL;
PRIVATE int hsize;
PRIVATE TIOCOLOURS** htype;
PRIVATE int maxtype;
PRIVATE TIOCOLOURS** hname;
PRIVATE TIOCOLOURS*  TIOothers;

int befussy= FALSE;
int* ragphase= NULL;

PRIVATE int
ihn (name)
     char* name;
{
  int h;

  h= 0;
  while (*name)
    h= 4*h + *(name++);
  h%= hsize;
  if (h < 0)
    h+= hsize;
  return h;
}

PUBLIC	void
cast_init (table)
     TIOCOLOURS*	table;
{
  int tsize;
  int i, h;
  
  iocolours= table;
  maxtype= 0;
  for (tsize= 0;
       iocolours[tsize].keyword != NULL;
       tsize++)
    if (iocolours[tsize].atype > maxtype)
      maxtype= iocolours[tsize].atype;
  TIOothers= iocolours + tsize;
  tsize++;
		/* I wish something that is neither
		 * a multiple of 2 or
		 * a multiple of 3
		 * but rougthly expects a 30% of filling
		 */
  hsize= 6*(tsize/2) + 1;
  
  htype= (TIOCOLOURS**) malloc ((maxtype+1) * sizeof (TIOCOLOURS*));
  if (htype == NULL)
    fatal ("cast_init run out of memory");
  for (i= 0; i <= maxtype; i++)
    htype[i]= NULL;
  for (i= 0; i < tsize; i++) {
    h= iocolours[i].atype;
    if (htype[h] != NULL) {
      fprintf (stderr, "cast_init: duplicated colour (%d)\n", h);
      exit (1);
    }
    htype[h]= iocolours+i;
  }
  
  hname= (TIOCOLOURS**) malloc (hsize * sizeof (TIOCOLOURS*));
  if (hname == NULL)
    fatal ("cast_init run out of memory");
  for (i= 0; i < hsize; i++)
    hname[i]= NULL;
  for (i= 0; i < tsize-1; i++) {
    h= ihn (iocolours[i].keyword);
    while (hname[h] != NULL)
      h= (h+1)%hsize;
    hname[h]= iocolours+i;
  }
/*
  (void) fprintf (stderr, "htype[%d]:\n", hsize);
  for (i= 0; i < hsize; i++)
    if (htype[i] != NULL && i != ((htype[i]->atype*3)%hsize))
      (void) fprintf (stderr, "htype[%2d]= %3d\n", i, htype[i]->atype);
  (void) fprintf (stderr, "hname[%d]:\n", hsize);
  for (i= 0; i < hsize; i++)
    if (hname[i] != NULL)
      if (hname[i]->keyword == NULL)
	(void) fprintf (stderr, "hname[%2d]= <others>\n", i);
      else
	if (i != ihn (hname[i]->keyword))
	  (void) fprintf (stderr, "hname[%2d]= %s\t(%3d)\n", i,
		   hname[i]->keyword, ihn (hname[i]->keyword));
*/

  ragphase= (int*) malloc ((maxtype+1) * sizeof (int));
  if (ragphase == NULL)
    fatal ("cast_init run out of memory");
}

PUBLIC	TIOCOLOURS*
name2clr (name)
     char* name;
{
  int i;

  if (iocolours == NULL) {
    fprintf (stderr, "cast_init must be used before name2clr\n");
    exit (1);
  }
  for (i= ihn (name); hname[i] != NULL; i= (i+1)%hsize) {
    if (hname[i]->keyword != NULL &&
        strcmp (hname[i]->keyword, name) == 0)
      return hname[i];
  }
  if (befussy)
    fprintf (stderr, "name2clr (%s): unknown colour\n", name);
  return TIOothers;
}

PUBLIC TIOCOLOURS*
type2clr (type)
     int type;
{
  TIOCOLOURS* tio;

  if (iocolours == NULL) {
    fprintf (stderr, "cast_init must be used before type2clr\n");
    exit (1);
  }
  if (type > maxtype)
    tio= NULL;
  else
    tio= htype[type];
  if (tio == NULL) {
    if (befussy)
      fprintf (stderr, "type2clr (%d): unknown colour\n", type);
    return htype[others];
  }
  return tio;
}

PUBLIC void
dr_node (nodep)
     TNODE*  nodep;
{
  if (nodep) {
    (void) fprintf (stderr, "< %d >", nodep->type);
    putattrs (stderr, nodep);
  }
}

PRIVATE void
it_tree (indent, nodep, deep)
     int indent;
     TNODE* nodep;
     int deep;
{
  int i;
  
  if (nodep != NULL && deep != 0) {
    for (i= indent; i > 0; i--)
      (void) fprintf (stderr, "  ");
    dr_node (nodep);
    it_tree (indent+1, nodep->sons,     deep-1);
    it_tree (indent,   nodep->brothers, deep);
  }
}

PUBLIC void
dr_tree (tree)
     TNODE* tree;
{
  it_tree (0, tree, -1);
}

PUBLIC void
drn_tree (tree, depth)
     TNODE* tree;
     int depth;
{
  dr_node (tree);
  it_tree (1, tree->sons, depth-1);
}
