This repository has been archived on 2024-01-04. You can view files and clone it, but cannot push or open issues or pull requests.
ncsa-mosaic/libhtmlw/list.c

332 lines
6.2 KiB
C

/*
* Copyright (C) 1992, Board of Trustees of the University of Illinois.
*
* Permission is granted to copy and distribute source with out fee.
* Commercialization of this product requires prior licensing
* from the National Center for Supercomputing Applications of the
* University of Illinois. Commercialization includes the integration of this
* code in part or whole into a product for resale. Free distribution of
* unmodified source and use of NCSA software is not considered
* commercialization.
*
*/
/*
* list.c: This module contains list manipulation routines that cunstruct
* and maintain a linked list of data items. The record at the head of each
* list contains pointers to the head, tail, and current list position.
* the list itsself is doubly linked with both next and previous pointers.
*
* ddt
*/
#include <stdio.h>
#include "listP.h"
#include "../config.h"
#ifndef MALLOC
#define MALLOC malloc
#define FREE free
#endif
#define NIL 0
#ifndef DISABLE_TRACE
extern int htmlwTrace;
#endif
static void ListPrintErr(s)
char *s;
{
#ifndef DISABLE_TRACE
if (htmlwTrace) {
fprintf(stderr,"%s",s);
}
#endif
}
/*
* This function returns the data located at the head of the linked list,
* or NIL if the list is empty. As a side effect current is also set to
* the head of the list.
*/
char *ListHead(theList)
List theList;
{
if (!theList)
return(NIL);
theList->current = theList->head;
if (theList->head)
return(theList->head->value);
else
return(NIL);
}
/*
* This function returns the data located at the tail of the linked list,
* or NIL if the list is empty. As a side effect current is also set to
* the tail of the list.
*/
char *ListTail(theList)
List theList;
{
if (!theList)
return(NIL);
theList->current = theList->tail;
if (theList->tail)
return(theList->tail->value);
else
return(NIL);
}
/*
* This function returns the data located at the current position in the
* linked list, or NIL if the list is empty.
*/
char *ListCurrent(theList)
List theList;
{
if (!theList)
return(NIL);
if (theList->current)
return(theList->current->value);
else
return(NIL);
}
/*
* This function returns the data located at the next element of the linked
* list after the current position, or NIL if the list is empty, or you
* are at its end.
* As a side effect current is also set to the next entry in the list.
*/
char *ListNext(theList)
List theList;
{
if (!theList)
return(NIL);
if (theList->current) {
theList->current = theList->current->next;
return(ListCurrent(theList));
}
else
return(NIL);
}
/*
* This function returns the data located at the previous element of the linked
* list before the current position, or NIL if the list is empty.
* As a side effect current is also set to the previous entry in the list.
*/
char *ListPrev(theList)
List theList;
{
if (!theList)
return(NIL);
if (theList->current) {
theList->current = theList->current->prev;
return(ListCurrent(theList));
}
else
return(NIL);
}
/*
* Create a list head and initialize it to NIL.
*/
List ListCreate()
{
List retVal;
if (!(retVal = (List) MALLOC(sizeof(struct LISTSTRUCT)))) {
ListPrintErr("Out of Memory\n");
return((List) 0);
}
retVal->head = NIL;
retVal->tail = NIL;
retVal->current = NIL;
retVal->listCount = 0;
return(retVal);
}
/*
* Destroy a list head, and free all associated memory.
*/
void ListDestroy(theList)
List theList;
{
struct LISTINSTANCE *l;
struct LISTINSTANCE *m;
if (!theList)
return;
l = theList->head;
while(l) {
m = l;
l = l->next;
FREE(m);
}
FREE(theList);
}
/*
* Add an entry to the end of the linked list. Current is changed to point to
* the added element.
*/
int ListAddEntry(theList,v)
/* return 0 on failure */
List theList;
char *v; /* data to be added */
{
struct LISTINSTANCE *l;
if (!(l =(struct LISTINSTANCE *) MALLOC(sizeof(struct LISTINSTANCE)))){
ListPrintErr("Out of Memory\n");
return(0);
}
l->value = v;
l->next = NIL;
l->prev = NIL;
if (theList->head == NIL)
theList->tail = theList->head = l;
else {
theList->tail->next = l;
l->prev = theList->tail;
theList->tail = l;
}
theList->current = l;
theList->listCount++;
return(1);
}
/*
* Search the list for an entry with a matching value field, and return
* a pointer to that list element. Current is changed to point to the
* element returned.
*/
static struct LISTINSTANCE *SearchListByValue(theList,v)
List theList;
char *v;
{
struct LISTINSTANCE *l;
l = theList->head;
while (l != NIL) {
if (l->value == v) {
theList->current = l;
return(l);
}
else {
l = l->next;
}
}
theList->current = l;
return(NIL);
}
/*
* Find the list entry with a matching value field, and delete it
* from the list. Set current to point to the element after the deleted
* element in the list.
*/
int ListDeleteEntry(theList,v)
/* removes the first occurance of v from the list */
/* return 0 if value not in list else 1 */
List theList;
char *v;
{
struct LISTINSTANCE *l;
char *retV;
if (!(l = SearchListByValue(theList,v)))
return(0);
if (l->prev)
l->prev->next = l->next;
else
theList->head = l->next;
if (l->next)
l->next->prev = l->prev;
else
theList->tail = l->prev;
theList->current = l->next;
retV = l->value;
FREE(l);
theList->listCount--;
return(1);
}
int ListMakeEntryCurrent(theList,entry)
/* return 0 on failure */
List theList;
char *entry;
{
struct LISTINSTANCE *l;
if (theList) {
if (!(l = SearchListByValue(theList,entry)))
return(0);
theList->current = l;
return(1);
}
return(0);
}
int ListCount(theList)
/* return the number of elements in the list */
/* current position pointer is not affected */
List theList;
{
/*
char *entry;
int count;
struct LISTINSTANCE *saveCurrent;
*/
if (theList) {
return(theList->listCount);
}
else {
return(0);
}
}
/* return indexed entry. Index starts at 0 */
/* the current list pointer will be set to this entry */
/* return 0 on failure */
char *ListGetIndexedEntry(theList,number)
List theList;
int number;
{
char *entry;
register int x;
if (!theList) {
return(0);
}
entry = ListHead(theList);
for (x = 0; x < number; x++) {
if (!entry) {
return(0);
}
entry = ListNext(theList);
}
return(entry);
}