/*  dlist.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <stream.h>
#include "portable.h"
#include "dlist.h"
#include "errcode.h"

ErrCode DoubleList::Insert(Entity a)
{
	if (Last) {
		Last->Next = new DoubleLink(a,Last,Last->Next) ;
		Last->Next->Previous = Last->Next ;	
	} else {
		Last = new DoubleLink(a,0,0);
		Last->Next = Last ;
		Last->Previous = Last ;
	}
	return OK;
}

ErrCode DoubleList::Append(Entity a)
{
	if (Last) {
		Last = Last->Next = new DoubleLink(a,Last,Last->Next) ;
		Last->Next->Previous = Last ;
	} else {
		Last = new DoubleLink(a,0,0);
		Last->Next = Last ;
		Last->Previous = Last ;
	}
	return OK;
}

Entity DoubleList::Pop()
{
	if (Last == 0) return 0 ;
	DoubleLink * OldLast = Last ;
	Entity Ret = OldLast->Entry ;
	Last = Last->Previous ;
	if (Last == OldLast) Last = 0 ;
	else {
		Last->Next = OldLast->Next ;
		(Last->Next)->Previous = Last ;
	}
	delete OldLast ;
	return Ret ;
}

Entity DoubleList::Get()
{
	if (Last == 0) return 0;
	DoubleLink * First = Last->Next ;
	Entity Return = First->Entry ;
	if (First == Last) Last = 0;
	else {
		Last->Next = First->Next ;
		(First->Next)->Previous = Last ;
	}
	delete First ;
	return Return ;
}

void DoubleList::Clear()
{
	DoubleLink * link = Last ;
	if (!link) return ;
	do {
		DoubleLink * l = link ;
		link = link->Next ;
		delete l ;
	} while (link!= Last) ;
	Last = 0 ;
}

int DoubleList::Size()
{
	DoubleListIterator Iter(*this);
	int Sz = 0;
	while (Iter.Next()) Sz++;
	return Sz;
}

ErrCode DoubleList::RemoveEntry (Entity Entry)
{
	DoubleListIterator Iter(*this);
	DoubleLink * Prev = Last ;
	Entity Ent;
	while(Ent = Iter.Next()) if (Ent == Entry) {
		DoubleLink * Save = Prev->Next ;
		Prev->Next = Iter.CurrentEntry->Next ;
		if (Save == Last) Last = Prev->Next ;
		if (Save == Last) Last = 0;
		delete Save ;
		return OK ;
	} else Prev = Prev->Next ;
	return Warning ;
}
		


Entity DoubleListIterator::Next()
{
	DoubleLink * Link ;
	if (!CurrentList) return 0;
	if (!CurrentList->Last) return 0;
	if ( !CurrentEntry )
		Link = CurrentEntry = CurrentList->Last->Next ;
			// Last->Next is First in list
	else {
		CurrentEntry = CurrentEntry->Next ;
		Link = (CurrentEntry == CurrentList->Last->Next) ?
			0 : CurrentEntry ;
	}
	return Link ? Link->Entry : 0 ;
}

void DoubleList::LinkDump() const
{
	cout << "last = " << (void *) Last << "," ;
	Last->Dump();
}

void DoubleLink::Dump() const
{
	cout << "this = " << (void *) this << ", prev = " << (void *) Previous
		<< ", next = " << (void *) Next << "\n" ;
}

Entity DoubleListIterator::Previous()
{
	// cout << "CurrentEntry: " ;
	// CurrentEntry->Dump();
	// cout << "CurrentList: " ;
	// CurrentList->LinkDump();
	DoubleLink * Link ;
	if (!CurrentList) return 0;
	if (!CurrentList->Last) return 0;
	if (CurrentEntry == CurrentList->Last->Next) return 0 ;
	if ( !CurrentEntry) Link = CurrentEntry = CurrentList->Last ;
	else {
		Link = CurrentEntry->Previous ;
		CurrentEntry = Link ;
	}
	// cout << "CurrentEntry: " ;
	// CurrentEntry->Dump();
	return Link ? Link->Entry : 0 ;
}



