/* $Id: select.cpp 1.2 1995/02/27 12:22:03 leon Exp leon $
*/

#include "select.h"

#include <malloc.h>



#undef DEBUG



static void (*inOrderFunc)(ads_name name);


/**
 ** Naredi prazen izbor
 **/
Selection::Selection()
{
  root = NULL;
}

/** {duh} **/
Selection::~Selection()
{
  typedef void (*DELFUNC) (void *);
  if (root)
    AVLrelease(&root, (DELFUNC) del);
}

/**
 ** Izbere gradnike iz ACAD baze podane s filtrom /xFilter/, nato pa
 ** z uporabo funkcije /getKey/ izbere kljuc /key/ iz gradnika in zgradi
 ** AVL drevo, ki za vsak element poleg kljuca hrani se ime gradnika /name/.
 ** Kljuc se lahko nahaja tudi v extended data, za kar je potrebno podati
 ** se /apps/ za ads_entgetx(). Funkcija /getKey/ mora vrniti 0, ce je nasla
 ** kljuc.
 **/
Selection::Select(struct resbuf *xFilter, 
                  int (*getKey)(struct resbuf *rb, int *key),
                  struct resbuf *apps)
{
  struct resbuf *rb;
  ads_name ss;
  long ssLength, i;
  int status, key;
  

  status = ads_ssget("X", NULL, NULL,  xFilter, ss);

  if (status != RTNORM)
    return -1;

  ads_sslength(ss, &ssLength);
#ifdef DEBUG

  ads_printf ("Stevilo izbranih elementov: %ld\n", ssLength);
#endif


  for (i = 0; i < ssLength; i++)
    {
      ads_name ent;
      status = ads_ssname(ss, i, ent);
      if (status != RTNORM)
        return status;
      rb = ads_entgetx(ent, apps);
      if (rb == NULL)
        continue;
      if ( (getKey)(rb, &key) == 0)
        Insert(key, ent);

      ads_relrb (rb);
    }

  ads_ssfree (ss);

  return 0;
}

/**
 ** Vrine en element v seznam
 **/
int Selection::Insert(int key, ads_name name)
{
  typedef int (*COMPAREFUNC) (void *, void *);
  struct ELEMENT *element;

  element = (struct ELEMENT *) malloc (sizeof (struct ELEMENT));
  if (!element)
    return AVL_NO_MEM;
  element->number = key;
  element->name[0] = name[0];
  element->name[1] = name[1];
  return AVLinsert(element, &root, (COMPAREFUNC) compare);
}


/**
 ** Zbrise element iz izbora
 **/
int Selection::Delete(int key)
{
  typedef int (*COMPAREFUNC) (void *, void *);
  typedef void (*DELFUNC) (void *);
  struct ELEMENT element;
  element.number = key;
  return AVLdelete(&element, &root, (COMPAREFUNC)compare, (DELFUNC)del);
}

/**
 ** Poisce element v izboru in vrne ACL_OK, ce je vse v redu ter 
 ** /name/ gradnika. Ob napaki vrne -1;
 **/
int Selection::Find(int key, ads_name name)
{
  typedef int (*COMPAREFUNC) (void *, void *);
  struct ELEMENT element, *e;

  element.number = key;
  if (( e = (ELEMENT *)AVLfind(&element, root, 
                               (COMPAREFUNC) compare)) == NULL)
    return -1;
  name[0] = e->name[0];
  name[1] = e->name[1];
  return AVL_OK;
}

/**
 ** Samo za razhroscevanje in testiranje. Izpise drevo v urejenem vrstnem
 ** redu po kljucih.
 **/
void Selection::Print()
{
  typedef void (*PRINTFUNC) (void *);
  ads_printf("Seznam elementov, ki so v seznamu:\n");
  AVLinorder(root, (PRINTFUNC) print);
  ads_printf("\n");
}

/**
 ** V pravilnem vrstnem redu za vse gradnike izbora izvrsi to funkcijo
 **/

void Selection::ForAll(void (*func)(ads_name name))
{
  typedef void (*INORDERFUNC) (void *);
  inOrderFunc = func;
  AVLinorder(root, (INORDERFUNC) inOrder);
}



/**
 ** Zbrise en element, tako da sprosti spomin zanj.
 **/
void Selection::del(struct ELEMENT *element)
{
  free (element);
}


/**
 ** Primerja dva elementa v drevesu AVL glede na velikost
 **/
int  Selection::compare(struct ELEMENT *el1, struct ELEMENT *el2)
{
  if (el1->number > el2->number)
    return 1;
  if (el1->number < el2->number)
    return -1;
  return 0;
}


/**
 ** Izpise en element na zaslon
 **/
void Selection::print(struct ELEMENT *element)
{
  ads_printf("[%d]", element->number);
}

void Selection::inOrder(struct ELEMENT *element)
{
  (*inOrderFunc)(element->name);
}



syntax highlighted by Code2HTML, v. 0.9.1