// $Source: /usr/local/SimSoft/SoftShop/Basics/Structur/List.h,v $
// $Revision: 1.20 $
// $Author: baum $
// $Date: 2001/11/29 15:52:23 $
//
// Login name of the user who locked the revision
// $Locker:  $
// Tag name used to checkout the file
// $Name: Release-20 $
// State assigned to revision
// $State: Exp $
//
//
// $Log: List.h,v $
// Revision 1.20  2001/11/29 15:52:23  baum
// -In Kalender.cpp und Kalender.h Handsteuerung eingebaut
//

#ifndef _LIST_H
#define _LIST_H 1

#if defined(_MSC_VER)
#pragma warning(disable:4251)
#endif  // _MSC_VER

#include <stddef.h>
#include "DLNode.h"

#if defined __GNUG__ || defined __hpux
#  pragma interface
#endif

template <class T>
class CursorRep;

template <class T>
class List;

//==================================================================
//		Klassen-Header
//		fuer class LCursor<T>
//==================================================================

//##ModelId=3FBCBCC50203
template <class T>
class LCursor
  {
  public:
    // constructors
	//##ModelId=3FBCBCC50214
    LCursor ();
	//##ModelId=3FBCBCC50215
    LCursor (const LCursor<T>&);
	//##ModelId=3FBCBCC50217
    LCursor (const List<T>&, int toEnd = 0);

    // destructor
	//##ModelId=3FBCBCC50224
    ~LCursor ();

    // assignment operators
	//##ModelId=3FBCBCC50225
    LCursor<T>& operator = (const LCursor<T>&);
	//##ModelId=3FBCBCC50233
    LCursor<T>& operator = (const List<T>&);

    // testing the LCursor
	//##ModelId=3FBCBCC50235
    operator void* () const;

    // negotiation operator
	//##ModelId=3FBCBCC50242
    bool operator ! () const;

    // yielding the object "under" the LCursor
	//##ModelId=3FBCBCC50244
    T* operator () () const;

    // moving the LCursor
	//##ModelId=3FBCBCC50246
    T* First ();
	//##ModelId=3FBCBCC50251
    T* Last ();
	//##ModelId=3FBCBCC50252
    T* Next ();
	//##ModelId=3FBCBCC50253
    T* Prev ();
	//##ModelId=3FBCBCC50261
    T* operator ++ ();        // Prefix-Notation  (++x)
	//##ModelId=3FBCBCC50262
    T* operator ++ (int);     // Postfix-Notation (x++)
	//##ModelId=3FBCBCC50264
    T* operator -- ();        // Prefix-Notation  (--x)
	//##ModelId=3FBCBCC50271
    T* operator -- (int);     // Postfix-Notation (x--)

  private:
    // data members
	//##ModelId=3FBCBCC50282
    CursorRep<T>* ObjRep;

  // friends
  friend class List<T>;

};	// class LCursor

//==================================================================
//		Klassen-Header
//		fuer class List<T>
//==================================================================

//##ModelId=3FBCBCC502CE
template <class T>
class List
  {
  public:
    // constructors
	//##ModelId=3FBCBCC502D0
    List ();
	//##ModelId=3FBCBCC502DE
    List (const List<T>&);

    // destructor
	//##ModelId=3FBCBCC502E0
    ~List ();

    // assignment operator
	//##ModelId=3FBCBCC502E1
    List<T>& operator = (const List<T>&);

    // retrieving
	//##ModelId=3FBCBCC502E3
    T* First () const;
	//##ModelId=3FBCBCC502EF
    T* Last () const;
	//##ModelId=3FBCBCC502F1
    T* find (const T& what) const;

    // prepending
	//##ModelId=3FBCBCC502FE
    T& prepend (const T& what);
	//##ModelId=3FBCBCC50300
    T& prepend (const T& what, const T& where);
	//##ModelId=3FBCBCC5030F
    T& prepend (const T& what, const LCursor<T>& where);
	//##ModelId=3FBCBCC50312
    List<T>& prepend (const List<T>&);

    // appending
	//##ModelId=3FBCBCC5031D
    T& append (const T& what);
	//##ModelId=3FBCBCC5031F
    T& append (const T& what, const T& where);
	//##ModelId=3FBCBCC5032E
    T& append (const T& what, const LCursor<T>& where);
	//##ModelId=3FBCBCC50331
    List<T>& append (const List<T>&);

    // removing
	//##ModelId=3FBCBCC5033D
    T* removeFirst ();
	//##ModelId=3FBCBCC5033E
    T* removeLast  ();
	//##ModelId=3FBCBCC5033F
    T* remove (const T& what);
	//##ModelId=3FBCBCC5034C
    T* remove (const LCursor<T>& what);
	//##ModelId=3FBCBCC5034E
    void removeAll ();

    // return non-0 if there are no objects on the List, 0 otherwise
	//##ModelId=3FBCBCC5034F
    bool isEmpty () const;

    // return the number of objects on the List
	//##ModelId=3FBCBCC5035C
    unsigned Count () const;

  private:
	//##ModelId=3FBCBCC5035E
    DLNode<T>* search (const T& what) const;
	//##ModelId=3FBCBCC5036B
    T& prepend (const T& what, DLNode<T>* where);
	//##ModelId=3FBCBCC5036E
    T& append (const T& what, DLNode<T>* where);
	//##ModelId=3FBCBCC5037C
    T* remove (DLNode<T>* what);

    // data members
	//##ModelId=3FBCBCC5038D
    DLNode<T>* ObjHead;
	//##ModelId=3FBCBCC5039A
    DLNode<T>* ObjTail;
	//##ModelId=3FBCBCC503AA
    mutable CursorRep<T>* ObjCursors;

  // friends
  friend class CursorRep<T>;

};	// class List

//==================================================================
//		Klassen-Header
//		fuer class CursorRep<T>
//==================================================================

// a CursorRep is the internal representation of a LCursor
//##ModelId=3FBCBCC60000
template <class T>
class CursorRep
  {
  public:
    // constructors
	//##ModelId=3FBCBCC60010
    CursorRep ();
	//##ModelId=3FBCBCC60011
    CursorRep (const CursorRep<T>&);
	//##ModelId=3FBCBCC60013
    CursorRep (const List<T>&, int toEnd);

    // destructor
	//##ModelId=3FBCBCC60021
    ~CursorRep ();

    // assignment operators
	//##ModelId=3FBCBCC60022
    CursorRep<T>& operator = (const CursorRep<T>&);
	//##ModelId=3FBCBCC6002E
    CursorRep<T>& operator = (const List<T>&);

    // testing the CursorRep
	//##ModelId=3FBCBCC60030
    operator void* () const;

    // yielding the object "under" the CursorRep
	//##ModelId=3FBCBCC60032
    T* Object () const;

    // moving the CursorRep
	//##ModelId=3FBCBCC6003E
    T* First ();
	//##ModelId=3FBCBCC6003F
    T* Last ();
	//##ModelId=3FBCBCC60040
    T* Next ();
	//##ModelId=3FBCBCC6004E
    T* Prev ();

  private:
    // connect to and return the given List
	//##ModelId=3FBCBCC6004F
    List<T>* tie (List<T>*);

    // disconnect from the associated List and return NULL
	//##ModelId=3FBCBCC60051
    List<T>* untie ();

    // data members
	//##ModelId=3FBCBCC6005E
    CursorRep<T>* ObjPrev;
	//##ModelId=3FBCBCC6006E
    CursorRep<T>* ObjNext;
	//##ModelId=3FBCBCC60139
    List<T>* ObjHost;
	//##ModelId=3FBCBCC60158
    DLNode<T>* ObjPos;
	//##ModelId=3FBCBCC6015C
    int ObjMoved;

  // friends
  friend class List<T>;
};	// class CursorRep

//==================================================================
//		Inline-Quellcode
//		fuer class LCursor<T>
//==================================================================

//##ModelId=3FBCBCC50214
template <class T>
inline LCursor<T>::LCursor () : ObjRep (new CursorRep<T>) { }

//##ModelId=3FBCBCC50215
template <class T>
inline LCursor<T>::LCursor (const LCursor<T>& c)
: ObjRep (new CursorRep<T> (*c.ObjRep)) { }

//##ModelId=3FBCBCC50217
template <class T>
inline LCursor<T>::LCursor (const List<T>& l, int toEnd /*= 0*/)
: ObjRep (new CursorRep<T> (l, toEnd)) { }

//##ModelId=3FBCBCC50224
template <class T>
inline LCursor<T>::~LCursor () {
  delete ObjRep;
}

//##ModelId=3FBCBCC50225
template <class T>
inline LCursor<T>& LCursor<T>::operator = (const LCursor<T>& c) {
  *ObjRep = *c.ObjRep;
  return *this;
}

//##ModelId=3FBCBCC50233
template <class T>
inline LCursor<T>& LCursor<T>::operator = (const List<T>& l) {
  *ObjRep = l;
  return *this;
}

//##ModelId=3FBCBCC50235
template <class T>
inline LCursor<T>::operator void* () const {
  return (*ObjRep);
}

//##ModelId=3FBCBCC50242
template <class T>
inline bool LCursor<T>::operator ! () const {
  return !(*ObjRep);
}

//##ModelId=3FBCBCC50244
template <class T>
inline T* LCursor<T>::operator () () const {
  return ObjRep->Object ();
}

//##ModelId=3FBCBCC50246
template <class T>
inline T* LCursor<T>::First () {
  return ObjRep->First ();
}

//##ModelId=3FBCBCC50251
template <class T>
inline T* LCursor<T>::Last () {
  return ObjRep->Last ();
}

//##ModelId=3FBCBCC50252
template <class T>
inline T* LCursor<T>::Next () {
  return ObjRep->Next ();
}

//##ModelId=3FBCBCC50253
template <class T>
inline T* LCursor<T>::Prev () {
  return ObjRep->Prev ();
}

//##ModelId=3FBCBCC50261
template <class T>
inline T* LCursor<T>::operator ++ () {
  return ObjRep->Next ();
}

//##ModelId=3FBCBCC50262
template <class T>
inline T* LCursor<T>::operator ++ (int) {
  T* t = ObjRep->Object ();
  ObjRep->Next ();
  return t;
}

//##ModelId=3FBCBCC50264
template <class T>
inline T* LCursor<T>::operator -- () {
  return ObjRep->Prev ();
}

//##ModelId=3FBCBCC50271
template <class T>
inline T* LCursor<T>::operator -- (int) {
  T* t = ObjRep->Object ();
  ObjRep->Prev ();
  return t;
}

//==================================================================
//		Inline-Quellcode
//		fuer class List<T>
//==================================================================

//##ModelId=3FBCBCC502D0
template <class T>
inline List<T>::List () : ObjHead (NULL), ObjTail (NULL), ObjCursors (NULL) { }

//##ModelId=3FBCBCC502DE
template <class T>
List<T>::List (const List<T>& l)
  : ObjHead (NULL), ObjTail (NULL), ObjCursors (NULL) {
  for (DLNode<T>* n = l.ObjHead; n; n = n->Next)  append (*n->Object);
}

//##ModelId=3FBCBCC502E0
template <class T>
List<T>::~List () {
  for (CursorRep<T>* c = ObjCursors; c; c = c->ObjNext) {
    c->ObjPos = NULL;
    c->ObjHost = c->untie ();
  }
  for (DLNode<T>* n; (n = ObjHead) != NULL; ObjHead = ObjHead->Next, delete n);
}

//##ModelId=3FBCBCC502E1
template <class T>
List<T>& List<T>::operator = (const List<T>& l) {
  for (CursorRep<T>* c = ObjCursors; c; c = c->ObjNext)  c->ObjPos = NULL;
  DLNode<T>* n;
  for ( ; (n = ObjHead) != NULL; ObjHead = ObjHead->Next, delete n);
  ObjTail = NULL;
  for (n = l.ObjHead; n; n = n->Next)  append (*n->Object);
  return *this;
}

//##ModelId=3FBCBCC502E3
template <class T>
inline T* List<T>::First () const {
  return (ObjHead) ? ObjHead->Object : (T*) NULL;
}

//##ModelId=3FBCBCC502EF
template <class T>
inline T* List<T>::Last () const {
  return (ObjHead) ? ObjTail->Object : (T*) NULL;
}

//##ModelId=3FBCBCC502F1
template <class T>
inline T* List<T>::find (const T& what) const {
  DLNode<T>* n = search (what);
  return (n) ? n->Object : (T*) NULL;
}

//##ModelId=3FBCBCC502FE
template <class T>
inline T& List<T>::prepend (const T& what) {
  DLNode<T>* n = new DLNode<T> ((T*) &what);
  return *(ObjHead = (ObjHead) ? n->prelink (ObjHead) : (ObjTail = n))->Object;
}

//##ModelId=3FBCBCC50300
template <class T>
inline T& List<T>::prepend (const T& what, const T& where) {
  DLNode<T>* n = search (where);
  return (n) ? prepend (what, n) : append (what);
}

//##ModelId=3FBCBCC5030F
template <class T>
inline T& List<T>::prepend (const T& what, const LCursor<T>& where) {
  return (where && (where.ObjRep->ObjHost == this))
            ? prepend (what, where.ObjRep->ObjPos) : append (what);
}

//##ModelId=3FBCBCC50312
template <class T>
List<T>& List<T>::prepend (const List<T>& l) {
  for (LCursor<T> c (*((List<T>*) &l), 1); c; c--)  prepend (*c ());
  return *((List<T>*) &l);
}

//##ModelId=3FBCBCC5031D
template <class T>
inline T& List<T>::append (const T& what) {
  DLNode<T>* n = new DLNode<T> ((T*) &what);
  return *(ObjTail = (ObjHead) ? n->postlink (ObjTail) : (ObjHead = n))->Object;
}

//##ModelId=3FBCBCC5031F
template <class T>
inline T& List<T>::append (const T& what, const T& where) {
  DLNode<T>* n = search (where);
  return (n) ? append (what, n) : prepend (what);
}

//##ModelId=3FBCBCC5032E
template <class T>
inline T& List<T>::append (const T& what, const LCursor<T>& where) { 
  return (where && where.ObjRep->ObjHost == this) 
            ? append (what, where.ObjRep->ObjPos) : prepend (what);
}

//##ModelId=3FBCBCC50331
template <class T>
List<T>& List<T>::append (const List<T>& l) { 
  for (LCursor<T> c (*((List<T>*) &l)); c; c++)  append (*c ());
  return *((List<T>*) &l);
}

//##ModelId=3FBCBCC5033D
template <class T>
inline T* List<T>::removeFirst () {
  return (ObjHead) ? remove (ObjHead) : (T*) NULL;
}

//##ModelId=3FBCBCC5033E
template <class T>
inline T* List<T>::removeLast () {
  return (ObjTail) ? remove (ObjTail) : (T*) NULL;
}

//##ModelId=3FBCBCC5033F
template <class T>
inline T* List<T>::remove (const T& what) {
  DLNode<T>* n = search (what);
  return (n) ? remove (n) : (T*) NULL;
}

//##ModelId=3FBCBCC5034C
template <class T>
inline T* List<T>::remove (const LCursor<T>& what) {
  return (what && what.ObjRep->ObjHost == this)
            ? remove (what.ObjRep->ObjPos) : (T*) NULL;
}

//##ModelId=3FBCBCC5034E
template <class T>
void List<T>::removeAll () {
  for (CursorRep<T>* c = ObjCursors; c; c = c->ObjNext)  c->ObjPos = NULL;
  for (DLNode<T>* n; (n = ObjHead) != NULL; ObjHead = ObjHead->Next, delete n);
  ObjTail = NULL;
}

//##ModelId=3FBCBCC5034F
template <class T>
inline bool List<T>::isEmpty () const {
  return !ObjHead;
}

//##ModelId=3FBCBCC5035C
template <class T>
unsigned List<T>::Count () const {
  unsigned count = 0;
  for (DLNode<T>* n = ObjHead; n; n = n->Next)  count++;
  return count;
}

//##ModelId=3FBCBCC5035E
template <class T>
DLNode<T>* List<T>::search (const T& what) const {
  for (DLNode<T>* n = ObjHead; n; n = n->Next)
    if (n->Object == &what)  return n;
  return NULL;
}

//##ModelId=3FBCBCC5036B
template <class T>
inline T& List<T>::prepend (const T& what, DLNode<T>* where) {
  DLNode<T>* n = new DLNode<T> ((T*) &what);
  if (ObjHead == where)  ObjHead = n;
  return *(n->prelink (where))->Object;
}

//##ModelId=3FBCBCC5036E
template <class T>
inline T& List<T>::append (const T& what, DLNode<T>* where) {
  DLNode<T>* n = new DLNode<T> ((T*) &what);
  if (ObjTail == where)  ObjTail = n;
  return *(n->postlink (where))->Object;
}

//##ModelId=3FBCBCC5037C
template <class T>
T* List<T>::remove (DLNode<T>* what) {
  for (CursorRep<T>* c = ObjCursors; c; c = c->ObjNext)
    if (c->ObjPos == what)
      if (what->Next) {
        c->ObjPos = what->Next;
        c->ObjMoved = 1;
      }
      else {
        c->ObjPos = what->Prev;
        c->ObjMoved = -1;
      }
  if (what == ObjHead)  ObjHead = ObjHead->Next;
  if (what == ObjTail)  ObjTail = ObjTail->Prev;
  T* retVal = what->Object;
  delete what->unlink ();
  return retVal;
}

//==================================================================
//		Inline-Quellcode
//		fuer class CursorRep<T>
//==================================================================

//##ModelId=3FBCBCC60010
template <class T>
inline CursorRep<T>::CursorRep ()
  : ObjPrev (NULL), ObjNext (NULL), ObjHost (NULL), ObjPos (NULL), ObjMoved (0)
  { }

//##ModelId=3FBCBCC60011
template <class T>
inline CursorRep<T>::CursorRep (const CursorRep<T>& c)
  : ObjHost (tie (c.ObjHost)), ObjPos (c.ObjPos), ObjMoved (0)
  { }

//##ModelId=3FBCBCC60013
template <class T>
inline CursorRep<T>::CursorRep (const List<T>& l, int toEnd)
  : ObjHost (tie ((List<T>*) &l)), ObjPos (toEnd ? ObjHost->ObjTail : ObjHost->ObjHead), ObjMoved (0)
  { }

//##ModelId=3FBCBCC60021
template <class T>
inline CursorRep<T>::~CursorRep () {
  untie ();
}

//##ModelId=3FBCBCC60022
template <class T>
CursorRep<T>& CursorRep<T>::operator = (const CursorRep<T>& c) {
  if (ObjHost != c.ObjHost) {
    untie ();
    ObjHost = tie (c.ObjHost);
  }
  ObjPos = c.ObjPos;
  ObjMoved = c.ObjMoved;
  return *this;
}

//##ModelId=3FBCBCC6002E
template <class T>
CursorRep<T>& CursorRep<T>::operator = (const List<T>& l) {
  if (ObjHost != &l) {
    untie ();
    ObjHost = tie ((List<T>*) &l);
  }
  ObjPos = ObjHost->ObjHead;
  ObjMoved = 0;
  return *this;
}

//##ModelId=3FBCBCC60030
template <class T>
inline CursorRep<T>::operator void* () const {
  return (void*) ObjPos;
}

//##ModelId=3FBCBCC60032
template <class T>
inline T* CursorRep<T>::Object () const {
  return (ObjPos) ? ObjPos->Object : (T*) NULL;
}

//##ModelId=3FBCBCC6003E
template <class T>
inline T* CursorRep<T>::First () {
  ObjPos = (ObjHost) ? ObjHost->ObjHead : (DLNode<T>*) NULL;
  ObjMoved = 0;
  return (ObjPos) ? ObjPos->Object : (T*) NULL;
}

//##ModelId=3FBCBCC6003F
template <class T>
inline T* CursorRep<T>::Last () {
  ObjPos = (ObjHost) ? ObjHost->ObjTail : (DLNode<T>*) NULL;
  ObjMoved = 0;
  return (ObjPos) ? ObjPos->Object : (T*) NULL;
}

//##ModelId=3FBCBCC60040
template <class T>
inline T* CursorRep<T>::Next () {
  if (ObjPos && (ObjMoved <= 0))  ObjPos = ObjPos->Next;
  ObjMoved = 0;
  return (ObjPos) ? ObjPos->Object : (T*) NULL;
}

//##ModelId=3FBCBCC6004E
template <class T>
inline T* CursorRep<T>::Prev () {
  if (ObjPos && (ObjMoved >= 0))  ObjPos = ObjPos->Prev;
  ObjMoved = 0;
  return (ObjPos) ? ObjPos->Object : (T*) NULL;
}

//##ModelId=3FBCBCC6004F
template <class T>
List<T>* CursorRep<T>::tie (List<T>* l) {
  if (!l)  return (List<T>*) (ObjNext = ObjPrev = NULL);
  if ((ObjNext = l->ObjCursors) != NULL)  ObjNext->ObjPrev = this;
  l->ObjCursors = this;
  ObjPrev = NULL;
  return l;
}

//##ModelId=3FBCBCC60051
template <class T>
List<T>* CursorRep<T>::untie () {
  if (!ObjHost)  return NULL;
  if (ObjPrev)  ObjPrev->ObjNext = ObjNext;
  else          ObjHost->ObjCursors = ObjNext;
  if (ObjNext)  ObjNext->ObjPrev = ObjPrev;
  return NULL;
}

#endif	// !defined _LIST_H
