/*
 * Filename: PXKList.m
 * Project:  Pascal's X Kit
 * Module:   Basic application components
 *
 * Function: Quick and dirty list class
 *
 * Author:   Pascal Forget <pascal@wsc.com>
 * Date:     August 1995
 *
 * See header file for modifications
 *
 * Copyright (C)1996 Pascal Forget. All Rights Reserved.
 */

#include "PXKList.h"

@implementation PXKList

- addObject:newObject;
{
    if (count == capacity) {
	capacity *= 2;
	if ((objects = realloc(objects, capacity * sizeof(id))) == NULL) {
	    fprintf(stderr, "Error expanding list. Exiting.\n");
	    exit(-1);
	}
    }

    objects[count++] = newObject;
    
    return self;
}

- (void)addObjectsFromArray:(id)otherArray;
{
    [self appendList:otherArray];
}

- appendList:aList;
{
    int i, newCount;

    if ((aList != nil) && ((newCount = [(PXKList *)aList count]) > 0)) {
	for (i=0; i<newCount; i++) {
	    [self addObject:[(PXKList *)aList objectAtIndex:i]];
	}
	return self;
    }
    return nil;
}

- (unsigned int)count;
{
    return count;
}

- empty;
{
    count = 0;
    capacity = 1;

    if ( (objects = (realloc(objects, capacity * sizeof(id)))) == NULL) {
	fprintf(stderr, "Error emptying list.  Exiting.\n");
	exit(-1);
    }
    return self;
}

- firstObject;
{
    if (count > 0) {
	return (id)objects[0];
    } else {
	return nil;
    }
}    

- (unsigned int)indexOfObject:object;
{
    unsigned int i = 4099999;

    for (i=0; i<count; i++) {
	if ((id)objects[i] == object) {
	    return i;
	}
    }
    return i;
}

- init;
{
    return [self initWithCapacity:1];
}

- initWithCapacity:(unsigned int)newCapacity;
{
    count = 0;
    capacity = newCapacity;

    objects = malloc(capacity * sizeof(id));

    if (objects == NULL) {
	fprintf(stderr, "PXKList: error allocating list. Exiting.\n");
	exit(-1);
    }

    return self;
}
   
- lastObject;
{
    if (count > 0) {
	return objects[count-1];
    } else {
	return nil;
    }
}

- makeObjectsPerform:(SEL)aSel;
{
#if 0
    unsigned int i;

    for (i=0; i<count; i++) {
	if ([(id)objects[i] respondsToSelector:aSel] == YES) {
	    objc_msg_send((id)objects[i], aSel);
	}
    }
#endif
    return self;
}

- objectAtIndex:(unsigned int)index;
{
    if ((index < count) && (count > 0)) {
	return (id)objects[index];
    } else {
	return nil;
    }
}
    
- removeAllObjects;
{
    return [self empty];
}

- removeLastObject;
{
    if (count > 0) {
	objects[count-1] = nil;
	count--;
	return self;
    } else {
	return nil;
    }
}   

- removeObjectAtIndex:(unsigned int)index;
{
    if ((index != PXK_NOT_IN_LIST) && (index<count)) {

	count--;
	
	for (; index<count; index++) {
	    objects[index] = objects[index+1];
	}

	objects[count] = nil;

	/* Shrink array if neccessary */
	
	if ((capacity > 256) && (capacity > (count * 3))) {

	    capacity = count * 2;
	    objects = (id *)realloc(objects, capacity * sizeof(id));

	    /* Verify that realloc() was successful */
	    
	    if (objects == NULL) {
		fprintf(stderr, "PXKList removeObjectAtIndex: "
			"error allocating memory.  Exiting.\n");
		exit(1);
	    }
	}
	
	return self;
    }
    return nil;
}

- removeObject:object;
{
    return [self removeObjectAtIndex:[self indexOfObject:object]];
}

- replaceObjectAtIndex:(unsigned int)index with:newObject;
{
    if (count < (index-1)) {
	fprintf(stderr, "PXKList error in replaceObjectAtIndex:with: "
		"invalid position (%d)\n", index);
	return nil;
    }

    objects[index] = newObject;
    return self;
}

- (void)replaceObjectAtIndex:(unsigned int)index withObject:newObject;
{
    [self replaceObjectAtIndex:index with:newObject];
}

@end





