/* Listing 3*/
/* --------------------- List.H------------------ */
#include <stdio.h>
#include <stdlib.h>

#define LIST_CLASS  unsigned (*at_top)(struct list*), \
             (*at_end)(struct list*), \
             (*is_empty)(struct list*), \
             (*find)(struct list *, ...); \
    void     (*prev)(struct list*), \
             (*next)(struct list *), \
             (*top)(struct list *), \
             (*seek)(struct list *, long, int), \
             (*end)(struct list *), \
             (*display)(struct list*), \
             (*add_member)(struct list*, void *), \
             (*replace_member)(struct list *, void *), \
    void     *(*current)(struct list *); \
    long     (*total_members)(struct list *), \
             (*tell)(struct list *);

typedef struct list {
    LIST_CLASS
} LIST;

LIST *new_list();
destroy_list(LIST *);

#define TRUE 1
#define FALSE 0

/* ----------------------  LIST.C ----------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "list.h"

static void not_valid() {
   fprintf(stderr,"Operation is not valid for this list\n");
   getch();
}

static unsigned is_empty(LIST *this) {
    return( this->total_members(this) == 0L);
}

static void seek(LIST *this, long where, int start) {
    long count;

    switch(start) {
        case SEEK_SET:
            this->top(this);
            for (count = 0; count < where; ++count) {
                if ( this->at_end(this) )
                    break;
                this->next(this);
            }
        break;
        case SEEK_CUR:
            if (where > 0) {
                for (count = 0; count < where; ++count) {
                    if ( this->at_end(this) )
                        break;
                    this->next(this);
                }
            }
            else {
                for(count = 0; count > where; ++count) {
                    if ( this->at_top(this) )
                       break;
                    this->prev(this);
                }
            }
    break;
    case SEEK_END:
        this->end(this);
        for(count = 0; count > where; ++count) {
            if ( this->at_top(this) )
                   break;
            this->prev(this);
        }
    break;
    }
}

static long total_members(LIST *this)
{
    long thisone, count;
    thisone = this->tell(this); this->top(this);
    count = 0;
    do {
        if ( ! this->at_end(this) ) {
            ++count;
            this->next(this);
        }
    } while( ! this->at_end(this) );
    this->seek(this,thisone,SEEK_SET);
    return(count);
}

LIST *new_list() {
LIST *this;

/* Allocate Memory for this Object */
this = calloc(1,sizeof(LIST));
if (this == NULL)
   return(NULL);

/* Assign Methods */
this->at_top = not_valid;   this->at_end = not_valid;
this->is_empty = is_empty;  this->find = not_valid;
this->prev = not_valid;     this->next = not_valid;
this->seek = seek;          this->top = not_valid;
this->end = not_valid;      this->display = not_valid;
this->replace_member = not_valid;
this->add_member = not_valid;
this->current = not_valid;
this->total_members = total_members;
this->tell = not_valid;

return(this);
}

destroy_list(LIST *this) {
    free(this);
}
