// This may look like C code, but it is -*- C++ -*-

//
//  Copyright (c) University of Aizu 1994
//
//  [# Edit, Date, User, Module #]\


// System includes
#include <stdlib.h>
#include <stream.h>

// Local includes
#include <List.h>


//  Lists are implemented as double linked lists.

//  part of  "intelligence" is in  list elements:
Listable::Listable(void)
{
  next_ = prev_ = this;
  list_ = 0;
}

Listable::Listable(Listable& listable)
{
  next_ = prev_ = this;
  list_ = 0;
}

virtual Listable::~Listable(void)
{
  // when deleting a listable, remove it from the list where it is contained
  if (list_) {
    Listable *succ = next_;
    Listable *pred = prev_;

    pred->next_ = succ;
    succ->prev_ = pred;
    if (this == list_->head_) list_->head_ = succ;
    if (this == list_->head_) list_->head_ = 0;
  }
}

Listable *Listable::next(void)  
{ return list_->head_ == next_ ? 0 : next_; }

Listable *Listable::prev(void)
{ return list_->head_ == this  ? 0 : prev_; }

List     *Listable::list(void)
{ return list_; }

Listable *Listable::insertBefore(Listable& listable)
{
  // now make a copy of the element to be inserted
  Listable *copy = listable.duplicate();
  if (copy == 0) return 0;

  // link it in...
  copy->list_  = list_;
  copy->next_  = this;
  copy->prev_  = prev_;
  prev_->next_ = copy;
  prev_ = copy;

  if (list_->head_ == this) list_->head_ = copy;
  // done!
  return copy;
}

//  another part is in the list "headers"
List::List(Listable *sample)
{
  head_   = 0;
  sample_ = sample;
}

//  The destructor deletes all list members 
virtual List::~List(void)
{
  clear();
  if (sample_) delete sample_;
}

virtual char *List::classname(void) 
{
  return "List";
}

//  This adds a *copy* of the listable to the list
Listable *List::add(Listable& aListable)
{
  // Is this is the first element of the list?
  if (head_ == 0) {
    Listable *copy = aListable.duplicate();
    head_  = copy;
    copy->list_    = this;
    // The copy may contain junk...
    copy->next_ = copy->prev_ = copy;
    return copy;
  } else 
    // Use the already defined function
    return head_->prev_->insertAfter(aListable);
}

void List::clear(void)
{
  while (head_ != 0)
    delete head_;
}


// End of file
