/*
 * Copyright 1994-1995 TriloBYTE Software Solutions.
 *
 * Author: Amen Zwa, TriloBYTE.
 */



// static char* sccsid = "Etc: %W%\t%G%\tAmen Zwa, TriloBYTE.";



// EList.h: singly- and doubly-linked list
  
  
  
#if !defined(ELIST_H)
#define ELIST_H

enum { list_bgn, list_end };		// link position in list

// link base class for singly linked lists
// NB:	ESLink is a link that lives on ESList's ESLink list
struct ESLink {
    ESLink* next;
    ESLink() { next = 0; }
    ESLink(ESLink* k) { next = k; }
    virtual ~ESLink() { }
    virtual char operator==(const ESLink& k) const { return &k == this; }
    char operator!=(const ESLink& k) const { return !operator==(k); }
};



// singly linked list container for ESLink
// NB:  user must manually delete elements using get()
class ESList {
protected:
    ESLink* tail;			// tail->next is head of list
    friend class ESListIter;
public:
    ESList() { tail = 0; }
    virtual ~ESList() { }
    void free();
    void put(ESLink* k, int p=list_end);	// add to tail/head of list
    ESLink* get();			// remove and return tail of list
    ESLink* del(ESLink* k);		// remove k and return
    int get_itmpos(ESLink* k);		// return position of k (begins at 0)
    int get_numitm() const;		// return number of items in the list
    virtual ESList& operator=(const ESList& l) { tail = l.tail; return *this; }
    char operator==(const ESList& l) const;
    char operator!=(const ESList& l) const { return !operator==(l); }
};



// iterator for ESList singly linked list
class ESListIter {
    ESList* clst;			// current list
    ESLink* clnk;			// current link
public:
    ESListIter() { clst = 0; clnk = 0; }
    ESListIter(ESList& l) { set_list(l); }
    void set_list(ESList& l) {
	clst = &l; clnk = clst->tail ? clst->tail->next : 0; }
    int set_link(ESLink* k);
    ESLink* head() const { return (clst&&clst->tail) ? clst->tail->next : 0; }
    ESLink* tail() const { return clst ? clst->tail : 0; }
    ESLink* current() const { return clnk; }
    ESLink* operator()();		// return next link
};



// link base class for doubly linked lists
struct EDLink {
    EDLink *prev, *next;
    EDLink() { prev = next = 0; }
    EDLink(EDLink* k) { prev = next = k; }
    virtual ~EDLink() { }
    virtual char operator==(const EDLink& k) const { return &k == this; }
    char operator!=(const EDLink& k) const { return !operator==(k); }
};

// doubly linked list container for EDLink
class EDList {
protected:
    EDLink* tail;
    friend class EDListFIter;
    friend class EDListBIter;
    friend class EDListLoop;
public:
    EDList() { tail = 0; }
    virtual ~EDList() { }
    void free();
    void put(EDLink* k);		// add to tail of list
    EDLink* get();			// remove and return tail of list
    EDLink* del(EDLink* k);		// remove k and return
    int get_itmpos(EDLink* k);		// return position of k (begins at 0)
    int get_numitm() const;		// return number of items in the list
    virtual EDList& operator=(const EDList& l) { tail = l.tail; return *this; }
    char operator==(const EDList& l) const;
    char operator!=(const EDList& l) const { return !operator==(l); }
};

// forward iterator for EDList doubly linked list
class EDListFIter {
    EDList* clst;			// current list
    EDLink* clnk;			// current link
public:
    EDListFIter(EDList& l) { clst = &l; clnk = clst->tail->next; }
    EDLink* operator()();		// return next link
};

// backward iterator for EDList doubly linked list
class EDListBIter {
    EDList* clst;			// current list
    EDLink* clnk;			// current link
public:
    EDListBIter(EDList& l) { clst = &l; clnk = clst->tail->next; }
    EDLink* operator()();		// return previous link
};

// continuously loop backward and forward on EDList doubly linked list
class EDListLoop {
    EDList* clst;			// current list
    EDLink* clnk;			// current link
public:
    EDListLoop() { clst = 0; clnk = 0; }
    EDListLoop(EDList& l) { set_list(l); }
    void set_list(EDList& l) {
	clst = &l; clnk = clst->tail ? clst->tail->next : 0; }
    int set_link(EDLink* k);
    EDLink* head() const { return clst ? clst->tail->next : 0; }
    EDLink* tail() const { return clst ? clst->tail : 0; }
    EDLink* current() const { return clnk; }
    EDLink* next() { return clnk ? (clnk=clnk->next) : 0; }
    EDLink* prev() { return clnk ? (clnk=clnk->prev) : 0; }
};

#endif	// LIST_H
