/*
 *
 *	entry.c
 *
 *	List support code.
 *
 *	HNMS User Interface Module
 *	HNMS 2.0
 *
 *	February 1994
 *
 *	Leslie Schlecht
 *	Computer Sciences Corporation
 *	Numerical Aerodynamic Simulation Systems Division
 *	NASA Ames Research Center
 *
 *	Copyright (c) 1994 Leslie Schlecht
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 1, or (at your option)
 *	any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include	<stdio.h>
#include	<sys/types.h>

typedef		struct listentry	{
		caddr_t			data;
		struct listentry	*next;
		} LISTENTRY;

#include	"entry.h"


/*
 *	Add an entry to a list and return its position.
 */
int
AddEntry(list, data, cmp, i)
LISTENTRY	**list;		/* address of list */
caddr_t		data;		/* address of some data */
int		(*cmp)();	/* comparison routine */
int		i;		/* counter */
	{
	LISTENTRY	*p;
	int		rc;

	if (!data) return(0);
	if (!list) return(0);
	i ++;
	/* end of list */
	if (*list == NULL) {
		*list = (LISTENTRY*)myalloc(NULL, 1, sizeof(LISTENTRY));
		(*list)->data = data;
		return(i);
		}
	if (!cmp) {
		if ((*list)->data == data) return(0);
		return(AddEntry(&((*list)->next), data, cmp, i));
		}
	rc = cmp((*list)->data, data);
	if (rc < 0)
		return(AddEntry(&((*list)->next), data, cmp, i));
	else if (rc == 0) return(0);
	else {
		p = *list;
		*list = (LISTENTRY*)myalloc(NULL, 1, sizeof(LISTENTRY));
		(*list)->data = data;
		(*list)->next = p;
		return(i);
		}
	}


/*
 *	Get the data for the entry at a specific position in the list.
 */
void
EntryAtPosition(list, pos, data)
LISTENTRY	*list;
int		pos;
caddr_t		*data;
	{
	while (--pos) list=list->next;
	*data = list->data;
	}


/*
 *	Does an object list contain an object.
 */
int
EntryInEntryList(list, data)
LISTENTRY	*list;
caddr_t		data;
	{
	if (!data) return(0);
	while (list != NULL) {
		if (list->data == data) return(1);
		list = list->next;
		}
	return(0);
	}


/*
 *	Find an entry in a list and return its data and postion.
 */
int
FindEntry(list, cmp, arg1, arg2, data)
LISTENTRY	*list;
int		(*cmp)();
caddr_t		arg1, arg2;
caddr_t		*data;
	{
	LISTENTRY	*p;
	int		i, rc;

	i = 0;
	if (!list) return(0);
	if (!cmp) return(0);
	p = list;
	while (p) {
		i ++;
		rc = cmp(p->data, arg1, arg2);
		if (rc < 0)
			p = p->next;
		else if (rc == 0) {
			*data = p->data;
			return(i);
			}
		else
			return(0);
		}
	return(0);
	}


/*
 *	Get the next entry data in the list and also the next entry pointer.
 */
int
NextEntry(list, data)
LISTENTRY	**list;
caddr_t		*data;
	{
	LISTENTRY	*p;

	if (!list) {
		*data = NULL;
		return(0);
		}
	p = *list;
	if (!p) {
		*data = NULL;
		return(0);
		}
	*data = p->data;
	*list = p->next;
	return(1);
	}


/*
 *	Remove an entry from a list.
 */
int
RemoveEntry(list, data, destroy)
LISTENTRY	**list;
caddr_t		data;
void		(*destroy)();
	{
	LISTENTRY	*p;

	if (!list) return(0);
	if (!(*list)) return(0);
	if (data == (*list)->data) {
		p = *list;
		*list = (*list)->next;
		if (destroy) destroy(p->data);
		free(p);
		return(1);
		}
	else
		return(RemoveEntry(&((*list)->next), data, destroy));
	}

/*
 *	Remove an entire entry list.
 */
void
RemoveEntryList(list, destroy)
LISTENTRY	*list;
void		(*destroy)();
	{
	LISTENTRY	*p, *q;

	if (list == NULL) return;
	for (p=list; p; p=q) {
		q = p->next;
		if (destroy) destroy(p->data);
		free(p);
		}
	}


/*
 *	Walk the list performing a function on each entry.
 */
void
WalkEntryList(list, f)
LISTENTRY	*list;
void		(*f)();
	{
	LISTENTRY	*p;

	if (!list) return;
	if (!f) return;
	while (p) {
		f(p->data);
		p = p->next;
		}
	}
