/* The routines in this file are copyright (c) 1987 by Helene (Lee) Taran.
 * Permission is granted for use and free distribution as long as the
 * original author's name is included with the code.
 */

#include "dlist.h"

Init_List(list)
DLISTPTR list; 
{ 
 int *calloc();
 list->next = list;
 list->prev = list;
 list->contents = calloc(1,sizeof(int));
 *((int *)(list->contents)) = 0;
}


/* Inserts <element> before <position> in <list> */
Insert_Before(position, element, list)  
DLISTPTR position, element, list; 
{ 
   *((int *)(list->contents)) = LENGTH(list) + 1;
   element->next = position;
   element->prev = position->prev;
   position->prev->next = element;
   position->prev = element;
}

/* Inserts <element> after <position> in <list> */
Insert_After(position,element,list)
DLISTPTR position, element, list; 
{
   *((int *)(list->contents)) = LENGTH(list) + 1;
   element->prev = position;
   element->next = position->next;
   position->next->prev = element;
   position->next = element;
}

/* Removes <element> from <list>. Assumes the <element> is currently
 * a member of <list>. Does not deallocate <element>
 */
DLISTPTR Remove_Element(element,list)
DLISTPTR element,list;  
{
   if (ISEMPTY(list)) return(list);
   *((int *)(list->contents)) = LENGTH(list) - 1;
   element->prev->next = element->next;
   element->next->prev = element->prev;
   element->next = NULL;
   element->prev = NULL;
   return(element);
}


/* Member: Returns TRUE if element is a member of the list 
 */
Member (element, list)
DLISTPTR element,list;    
{ 
   DLISTPTR tmp = list;
   while ((tmp = tmp->next) != list) 
     if (tmp == element) return(TRUE);     
   return(FALSE);
}

/* Get_Member : returns the member of the list that contains <element>
 * returns NULL if not a member of the list.
 */
DLISTPTR GET_MEMBER(element, list) 
void *element; 
DLISTPTR list;   
{
  DLISTPTR tmp = list;
  while ((tmp = tmp->next) != list ) 
     if (tmp->contents == element) return(tmp);     
  return(FALSE);
}
  
/* Find_Element: returns the member of the list that contains some element
 * that satisfies the given test with respect to <element>.  For example:
 * you can define a function equal that returns true if two elements have
 * the exact same fields. 
 * Returns FALSE if no member of the list satifies the test. 
 */
DLISTPTR Find_Element(element,list,test)
void *element;
DLISTPTR list;                 
int (*test)(); 
{
  DLISTPTR tmp = list;
  while ((tmp = tmp->next) != list ) 
     if ((*test)(tmp->contents,element)) return(tmp);     
  return(FALSE);
}

/* Apply : applies the given function to the contents of each list
 * element.
 */
Apply(fn,list)
int (*fn)();
DLISTPTR list;
{
   DLISTPTR tmp = list;
   while ((tmp = tmp->next) != list) (*fn)(tmp->contents);

}


/* Removes and disposes of all elements in a list --- does not deallocate
 * the head of the list. if <foo> is non-zero then deallocate the contents
 * of each element.
 */
ClearList (list,foo)
DLISTPTR list; 
int foo;
{
  DLISTPTR doomed;
  while ((doomed = Remove_Element(FIRST(list),list)) != list) {
      if (foo) free(doomed->contents);
      free(doomed);
  }
}

