/* 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.
 */

/*
 * Reformatted, and modified to compile without warnings and errors
 * under SAS/C -6.5x by gduncan@philips.oz.au (GMD). This included
 * proto generation, renaming of some literals to avoid name collisions,
 * and Amiga Version string (also displayed in Title bar).
 * No original version number, this version arbitrarily named 1.1. 
 * - otherwise no functional changes.
 * GMD - Sep 94
 */

#include "all.h"

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


/* Inserts <element> before <position> in <list> */

void
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> */

void
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 
 */

BOOL
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) (void *, void *);
{
  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.
 */

void
Apply (fn, list)
     int (*fn) (void *);
     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.
 */

void
ClearList (list, foo)
     DLISTPTR list;
     int foo;
{
  DLISTPTR doomed;
  while ((doomed = Remove_Element (FIRST (list), list)) != list)
    {
      if (foo)
	free (doomed->contents);
      free (doomed);
    }
}
/*--*/
