;/* Lists - Execute me to compile me with Lattice.
LC -b0 -cfistq -v -y Lists.c
Blink with Make
quit
*/

/*** ******************************** ***/
/***								  ***/
/***  Generic List Handling Routines  ***/
/***								  ***/
/***				 by STIGG // NVX  ***/
/***								  ***/
/***			Version 1.0			  ***/
/***								  ***/
/*** ******************************** ***/



#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include <exec/exec.h>
#include <exec/lists.h>
#include <exec/nodes.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <proto/exec.h>
#include <proto/dos.h>

/* Expand this structure to suit specific program */

struct MyNode
	{
	struct	Node	mn_Node;	/* A node structure */
	APTR			mn_Entry;	/* Reference Pointer */
	};

/* Function Prototypes */

struct Node *AddANodeAlpha( struct List *list, char *Name );
void ClearList( struct List *Start );
BOOL FindNodeA( struct Node *Start, char *String, struct Node **Insert );
struct Node *FindOrd( struct List *list, UWORD ordinal );
WORD OrdNode( struct Node *node );
void RemoveANode( struct Node *Bye );
APTR Allocvec( ULONG size, LONG type );
void Freevec( APTR addr );

	/* ******************************************************** */
	/* 					Add A Node Alphabetically				*/
	/* ******************************************************** */

struct Node *AddANodeAlpha( struct List *list, char *Name )
{

struct Node *NewNode,*temp,*Posn;

/* Allocate memory for node */

if ( NewNode=(struct Node *)Allocvec( sizeof(struct MyNode), MEMF_CLEAR))
	{
	/* Allocate memory for copy of title */
	
	if ( NewNode->ln_Name=(char *)Allocvec( 1+strlen(Name), MEMF_CLEAR))
		{
		strcpy( NewNode->ln_Name, Name );

		/* Add this node to the list after the specified node */

		FindNodeA( (struct Node *)list, Name, &Posn );
		
		NewNode->ln_Succ=Posn->ln_Succ;
		NewNode->ln_Pred=Posn;
		temp=(struct Node *)Posn->ln_Succ;
		Posn->ln_Succ=NewNode;
		temp->ln_Pred=NewNode;
		
		}
	else
		{
		Freevec(NewNode);
		NewNode=NULL;
		}
	}
return NewNode;
}

	/* ******************************************************** */
	/* 				Clear All Nodes From A List					*/
	/* ******************************************************** */

void ClearList( struct List *Start )
{
struct Node *this_node;
struct Node *next_node;

if( Start )
	{
	this_node=((struct Node *)Start)->ln_Succ;  /* -> to 1st node */

	while( next_node=(struct Node *)( this_node->ln_Succ ) )
		{
		if( this_node->ln_Name ) Freevec( this_node->ln_Name );
		Freevec( this_node );
		this_node=next_node;
		}
	NewList( Start );
	}
}

	/* ******************************************************** */
	/* 					Find A Node Given Name					*/
	/* ******************************************************** */

/* Returns TRUE if node found, returns pointer to node with name ordinaly
   lower than one we require for insertion */

BOOL FindNodeA( struct Node *Start, char *String, struct Node **Insert )
{

int i;
BOOL RetVal=FALSE;

*Insert=Start;
while( (Start->ln_Succ)->ln_Succ )
	{
	Start=(struct Node *)( Start->ln_Succ );
	i=strcmpi( String, Start->ln_Name );
	if ( !i ) RetVal=TRUE;
	if( i>=0 ) *Insert=Start;
	}

return RetVal;
}

	/* ******************************************************** */
	/* 				Find A Node Given Ordinal Number			*/
	/* ******************************************************** */

struct Node *FindOrd( struct List *list, UWORD ordinal )
{

struct Node *node;
UWORD i;

node = (struct Node *)list;
ordinal++;

for( i=0; (i<ordinal) && (node); i++ )
	node = node->ln_Succ;

if( node->ln_Succ==NULL )node=NULL;

return node;
}

	/* ******************************************************** */
	/* 			Return Ordinal Number of Given Node				*/
	/* ******************************************************** */

/* Will return ordinal number of given node, -1 for start of list */

WORD OrdNode( struct Node *node )
{

register WORD ord=-1;

while( node = node->ln_Pred ) ord++;
return ord;
}

	/* ******************************************************** */
	/* 				Remove And Free A Node						*/
	/* ******************************************************** */

void RemoveANode( struct Node *Bye )
{

((struct Node *)(Bye->ln_Pred))->ln_Succ=Bye->ln_Succ;
((struct Node *)(Bye->ln_Succ))->ln_Pred=Bye->ln_Pred;

if( Bye->ln_Name ) Freevec( Bye->ln_Name );
Freevec( Bye );

}

	/* ******************************************************** */
	/* 		Memory Allocation Routines Missing From WB1.3		*/
	/* ******************************************************** */

/* The following two routines have been written so that some of my code
   written for WB2+ machines will run on WB1.3 as well. These are direct
   substitutes for AllocVec() and FreeVec(), plug in and go.... */

APTR Allocvec( ULONG size, LONG type )
{
ULONG *buf;

size += 4;			/* allow for our magic bit */

if( buf=(ULONG *)AllocMem( size, type ) ) *buf++=size;

return (APTR)buf;
}

void Freevec( APTR addr )
{
LONG *buf;
ULONG size;

if( addr )
	{
	buf = (LONG *)addr;
	buf--;
	size = *buf;
	FreeMem( (APTR)buf, size );
	}
}
