/*
dllist.c: doubly linked lists for selectnews;
          originally a C++ file called 'eeklist.c'

Copyright (C) 1993 Eugene Eric Kim
All rights reserved.

LAST REVISION: September 4, 1993
*/

#include <malloc.h>
#include <string.h>
#include "dllist.h"

void list_create(dllist* l)
{
  (*l).head = 0;
}

node* list_next(node* w)
{
  return (*w).next;
}

node* list_prev(node* w)
{
  return (*w).prev;
}

int list_size(dllist l)
{
  int i = 0;
  node* temp;

  temp = l.head;
  while (temp != 0) {
    temp = (*temp).next;
    i++;
  }
  return i;
}

short list_empty(dllist l)
{
  return l.head ? 0 : 1;
}

short list_first(node* w)
{
  if (w==0)
    return 1;
  else
    return (*w).prev ? 0 : 1;
}

short list_last(node* w)
{
  if (w==0)
    return 1;
  else
    return (*w).next ? 0 : 1;
}

node* list_start(dllist l)
{
  return l.head;
}

node* list_end(dllist l)
{
  node* temp;

  temp = l.head;
  if (temp != 0)
    while ((*temp).next != 0 ) temp = (*temp).next;
  return temp;
}

node* list_position(dllist l,int i)
/* if i is illegal, returns 0 */
{
  node* temp;
  int j = 0;

  temp = l.head;
  if ( (i>=0) && (i<list_size(l)) ) {
    while (j<i) {
      temp = (*temp).next;
      j++;
    }
    return temp;
  }
  else
    return 0;
}

node* list_del(dllist* l,node* w)
{
  node* p;
  node* n;

  if (w!=0) {
    p = (*w).prev;
    n = (*w).next;
    if (n!=0) (*n).prev = p;
    if (p!=0) (*p).next = n;
    else (*l).head = n; /* if p == 0 then w = head */
    (*w).prev = 0;
    (*w).next = 0;
    free(w);
  }
  if (n!=0)
    return n;
  else
    return p;
}

node* list_insafter(dllist* l, node* w, char item[LEN])
{
  node* temp = malloc(sizeof(node));
  node* n;

  strcpy((*temp).entry,item);
  if (w == 0) { /* => w==head */
    (*temp).next = (*temp).prev = 0;
    w = temp;
    (*l).head = w;
  }
  else {
    if ((*w).next != 0) {
      n = (*w).next;
      (*temp).next = n;
      (*n).prev = temp;
    }
    (*w).next = temp;
    (*temp).prev = w;
  }
  return temp;
}

node* list_insbefore(dllist* l, node* w, char item[LEN])
{
  node* temp = malloc(sizeof(node));
  node* p;
  int ishead = 0;

  strcpy((*temp).entry,item);
  if (w == 0) { /* => w==head */
    (*temp).next = (*temp).prev = 0;
    w = temp;
    (*l).head = w;
  }
  else {
    if ((*w).prev != 0) { /* if w != head */
      p = (*w).prev;
      (*temp).prev = p;
      (*p).next = temp;
    }
    else ishead = 1;
    (*w).prev = temp;
    (*temp).next = w;
    if (ishead) (*l).head = temp;
  }
  return temp;
}

void list_replace(dllist* l,node* w, char item[LEN])
{
  strcpy((*w).entry,item);
}

void list_interchange(dllist* l, node* w, node* v)
{
  char temp[LEN];

  strcpy(temp,(*w).entry);
  strcpy((*w).entry,(*v).entry);
  strcpy((*v).entry,temp);
}

void list_traverse(dllist l,void (*visit)(node* w))
{
  node* c;

  c = l.head;
  while (c != 0) {
    (*visit)(c);
    c = (*c).next;
  }
}

void list_clear(dllist* l)
{
  node* temp = list_end(*l);
  node* curr;

  while (!temp && (temp != 0)) {
    curr = (*temp).prev;
    if ((*temp).prev)
      free((*temp).prev);
    if ((*temp).next)
      free((*temp).next);
    free(temp);
    temp = curr;
  }
  (*l).head = 0;
}
