/*
_____       _    _    Corso   Italia,  178
(_|__   .  (_   |_|_  56125           Pisa
(_|_) |)|(()_)()| |   tel.  +39  050 46380
  |   |               picosoft@picosoft.it

 picocpp - basic objects library for picoSQL 

 Copyright (C) Picosoft s.r.l. 1994-2002

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#include "plist.h"
static char rcsid[] = "$Id: plist.cpp 1.3 96/04/09 14:00:16 picoSoft Exp $";

PCLASSID(PList)

PList::PList ()
{
   root = (PListItem *) 0;
   current = (PListItem *) 0;
   itemNum = 0;
}

PList::PList (PList & l)
{
   PObject * p;

   root = (PListItem *) 0;
   current = (PListItem *) 0;
   itemNum = 0;

   p = l.GetFirst ();
   while (p != 0) {
      AddItem (p);
      p = l.GetNext ();
   }
}


PList::~PList ()
{
   PListItem * next;

   next = root;
   while (next != (PListItem *) 0) {
      current = next;
      next = next->right;
      delete current;
   }
   root = (PListItem *) 0;
}

void
PList::AddItem (PObject * o)
{
   PListItem * prev;

   current = root;
   while (current != (PListItem *) 0) {
      prev = current;
      current = current->right;
   }
   if (root == (PListItem *) 0) {
      root = current = new PListItem;
      root->left = root->right = (PListItem *) 0;
   }
   else {
      current = new PListItem;
      current->left = prev;
      current->right = (PListItem *) 0;
      prev->right = current;
   }
   current->obj = o;
   itemNum ++;
}

int
PList::InsertItem (PObject * o)
{
   PListItem *before = 0;
   PListItem *after = 0;
   int rctest;

   after = root;
   while (after != (PListItem *) 0) {
      if ((rctest = CollSeq (o, after->obj)) < 0)
         break;
      else if (rctest == 0)
         return 0;
      else {
         before = after;
         after = after->right;
      }
   }
   if (after == 0)
      AddItem (o);
   else {
      current = new PListItem;
      current->left = before;
      current->right = after;
      after->left = current;
      if (before != 0)
         before->right = current;
      else
         root = current;
      current->obj = o;
      itemNum ++;
   }
   return 1;
}

PObject *
PList::GetCurrent ()
{
   if (current != (PListItem *) 0)
      return current->obj;
   else
      return (PObject *) 0;
}

PObject *
PList::SetCurrent (PObject *o)
{
   PObject *Return = 0;
   if (current != (PListItem *) 0) {
      Return = current->obj;
      current->obj = o;
   }
   return Return;
}

PObject *
PList::GetFirst ()
{
   if (root != (PListItem *) 0) {
      current = root;
      return root->obj;
   }
   else
      return (PObject *) 0;
}

PObject *
PList::GetLast ()
{
   PListItem * next;

   next = root;
   while (next != (PListItem *) 0) {
      current = next;
      next = next->right;
   }

   if (current != (PListItem *) 0)
      return current->obj;
   else
      return (PObject *) 0;
}

PObject *
PList::GetNext ()
{
   if (current != (PListItem *) 0 && current->right != (PListItem *) 0) {
      current = current->right;
      return current->obj;
   }
   else
      return (PObject *) 0;
}

PObject *
PList::GetPrevious ()
{
   if (current != (PListItem *) 0 && current->left != (PListItem *) 0) {
      current = current->left;
      return current->obj;
   }
   else
      return (PObject *) 0;
}

PObject *
PList::GetAt (int indx)
{
   PListItem * next;
   int i;

   for (next = root, i = 0;
    next != (PListItem *) 0 && i < indx;
    next = next->right, i++)
      ;

   if (next != (PListItem *) 0) {
      current = next;
      return current->obj;
   }
   else
      return (PObject *) 0;
}


PObject *
PList::DeleteCurrent ()
{
   PListItem *newcurrent = 0;
   PObject * Return = 0;

   if (current != (PListItem *) 0) {
      if (current->left != 0) {
         newcurrent = current->left;
         current->left->right = current->right;
      } else
         root = current->right;

     if (current->right != 0) {
        newcurrent = current->right;
        current->right->left = current->left;
        Return = newcurrent->obj;
     }
     delete current;
     current = newcurrent;
     itemNum--;
   }
   return Return;
}

PList &
PList::operator=(PList &l)
{
   PObject * p = GetFirst ();
   while (p != 0)
      p = DeleteCurrent();

   p = l.GetFirst ();
   while (p != 0) {
      AddItem (p);
      p = l.GetNext ();
   }
   return *this;
}
