/*
Library: chain 
Created: 22.10.2001
Author : Peter Turczak <p_turczak@wiwa.de>

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

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "chain.h"
#include <stdio.h>
#include <stdlib.h>


struct element* newchain()
{
 struct element *newe;

 newe=malloc(sizeof(element));
 newe->next=NULL;
 newe->prev=NULL;
 newe->cur=NULL;
 newe->head=newe;
 
 return(newe);
}

struct element* addelement(void *newp, int size, struct element* chain)
{
 struct element* newe;
 void* temp;
 
 newe=malloc(sizeof(element));
 newe->prev=chain;

 temp=chain->next;
 chain->next=newe;
 newe->next=temp;

 newe->cur=malloc(size);
 memcpy(newe->cur,newp,size);

 if (newe->prev!=NULL)
  newe->head=newe->prev->head; 
 else
  newe->head=newe->next->head;

 return(newe);
}

struct element* addelement_nocpy(void *newp, struct element* chain)
{
 struct element* newe;
 void* temp;
 
 newe=malloc(sizeof(element));
 newe->prev=chain;

 temp=chain->next;
 chain->next=newe;
 newe->next=temp;

 newe->cur=newp;

 if (newe->prev!=NULL)
  newe->head=newe->prev->head; 
 else
  newe->head=newe->next->head;

 return(newe);
}

struct element* unchain(struct element *chain)
{
 struct element *tmp1;
 struct element *tmp2;

 tmp1=chain->prev;      // Backup the two elements
 tmp2=chain->next;	// on the left and right
 if (chain->cur!=NULL)
   free(chain->cur);	// Kill the content
 free(chain);		// Kill the chain element
 if (tmp1!=NULL)
   tmp1->next=tmp2;	// Close the chain again 
 if (tmp2!=NULL)
   tmp2->prev=tmp1;	// (Cross-over the pointers..)

 if (tmp1!=NULL)
  return(tmp1);		// Return the left value...
 else
  return(tmp2);
}

struct element* unchain_nofree(struct element *chain)
{
 struct element *tmp1;
 struct element *tmp2;

 tmp1=chain->prev;      // Backup the two elements
 tmp2=chain->next;	// on the left and right
 free(chain);		// Kill the chain element
 if (tmp1!=NULL)
   tmp1->next=tmp2;	// Close the chain again 
 if (tmp2!=NULL)
   tmp2->prev=tmp1;	// (Cross-over the pointers..)

 if (tmp1!=NULL)
  return(tmp1);		// Return the left value...
 else
  return(tmp2);
}

struct element* head(struct element *chain)
{
 struct element *tmp;
 
/*
 tmp=chain;
 while (tmp->prev!=NULL)
  {
   tmp=tmp->prev;
  }
*/
 tmp=chain->head;  

 return(tmp); 
}

struct element* tail(struct element *chain)
{
 struct element *tmp;
 
 tmp=chain;
 while (tmp->next!=NULL)
  {
   tmp=tmp->next;
  }
 return(tmp); 
}

void clearlst(struct element *chain)
{
 struct element *tmp;

 tmp=head(chain);
 while (tmp->next!=NULL) 
  {
   tmp=unchain(tmp);
  } 
 unchain(tmp); 
}

struct element* e_next(struct element *chain)
{
 return(chain->next); 
}

struct element* e_prev(struct element *chain)
{
 return(chain->prev); 
}

struct element* movelement(struct element *from, struct element *to)
{
 addelement_nocpy(from->cur, to);
 return(unchain_nofree(from));
}

int chainlen(struct element *chain)
{
struct element *e=head(chain);
int r=0;
 
 while(e->next!=NULL)
  {
   e=e->next;
   r++;
  }

  return(r);
}

struct element* r_next(struct element *chain)
{
struct element *r=NULL;

 if (chain!=NULL)
  {
   r=(chain->next==NULL)?chain->head:chain->next;
  }

return(r);
}

struct element* r_prev(struct element *chain)
{
struct element *r=NULL;

 if (chain!=NULL)
  {
   r=(chain->prev==NULL)?tail(chain):chain->prev;
  }

return(r);
}


syntax highlighted by Code2HTML, v. 0.9.1