#include <windows.h>
#include <stdlib.h>

/* using a windows heap for the code completion because the way I've implemented it it uses a *lot* of memory,
 * and the borland runtime gets confused...
 */
int total_size;

static void *freeblocks;

#define ALLOC_SIZE 8192
typedef struct _allocblk
{
	struct _allocblk *next;
	int size;
	int offset;
	char data[1];
} ALLOCBLK;

static HANDLE heap;
void alloc_init(void)
{
	heap = HeapCreate(0, 2 * 1024 * 1024, 256  * 1024 * 1024);
	freeblocks = 0;
}
static void *newblk(int size)
{
	ALLOCBLK *bnew;
	if (size == ALLOC_SIZE && freeblocks)
	{
		bnew = freeblocks;
		freeblocks = bnew->next;
		memset(bnew->data, 0, bnew->size);
		bnew->offset = 0;
		bnew->next = 0;
	}
	else
	{
		bnew = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(ALLOCBLK) + size - 1);
		if (!bnew)
		{
//		xprint("no memory");
		exit(1);
		}
		total_size += size;
		bnew->size = size;
		bnew->offset = 0;
	}
	return bnew;
}
void *allocate(int size, void **root1)
{
	void *rv ;
	ALLOCBLK *root = *root1;
	size += 3;
	size &= -4;
	if (!root)
	{
		*root1 = root = newblk(size > ALLOC_SIZE ? size : ALLOC_SIZE);
	}
	if (root->size - root->offset < size)
	{
		ALLOCBLK *bnew = newblk(size > ALLOC_SIZE ? size : ALLOC_SIZE);
		bnew->next = root;
		*root1 = root = bnew;
	}
	rv = &root->data[root->offset];
	root->offset += size;
	return rv;
}
void allocfreeall(void **root1)
{
	int donesome = FALSE;
	ALLOCBLK *root = *root1;
	*root1 = NULL;
	
	while (root)
	{
		ALLOCBLK *next = root->next;
#ifdef XXXXX
		if (root->size == ALLOC_SIZE)
		{
			root->next = freeblocks;
			freeblocks = root;
			memset(root->data,0x5a, root->size);
		}
		else
#endif
			total_size -= root->size;
			HeapFree(heap, 0, root);
		root = next;
		donesome = TRUE;
	}
	if (donesome)
		HeapCompact(heap, 0);
}
