#include <exec/memory.h>
#include <string.h>

#define	every_node	node=list->lh_Head;node->ln_Succ;node=node->ln_Succ

/* PROTOTYPES */
struct Node *AddEvent(struct Gadget *gadget,struct List *list, char *name);
void RenameEvent(struct EventNode *eventnode, char *name);
void RenameText(struct Node *node, char *name);
struct Node *AddText(struct List *list, char *name);
void FreeTextList(struct List *);
void FreeEventList(struct List *);
UWORD Count(struct List *list);
void DeleteText(struct List *list, struct Node *node);
void DeleteEvent(struct List *list, struct EventNode *eventnode);
void Up(struct Gadget *gadget,struct List *list,struct Node *node);
void Down(struct Gadget *gadget,struct List *list,struct Node *node);
void Top(struct Gadget *gadget,struct List *list,struct Node *node);
void Bottom(struct Gadget *gadget,struct List *list,struct Node *node);
void DetachList(struct Gadget *gadget);
void AttachList(struct Gadget *gadget,struct List *list);
void Sort(struct Gadget *gadget, struct List *list, int sortby);
long MarkSelected(struct Gadget *gadget,long top,long current);
struct Node *GetCurrent(struct List *,long);
char *transform(char indate[6]);

struct Node *AddEvent(struct Gadget *gadget,struct List *list, char *name) {
	struct EventNode	*eventnode;

	if (!( eventnode = AllocMem(sizeof(struct EventNode),MEMF_CLEAR) ))
		fail("Out of memory");
	else {
		strcpy(eventnode->eventname,name);
		eventnode->nn_Node.ln_Name=eventnode->eventname;
		eventnode->nn_Node.ln_Type=EVENTNODE_ID;
		eventnode->nn_Node.ln_Pri =0;

		if (!( eventnode->textlist = AllocMem(sizeof(struct List),MEMF_CLEAR)) )
			fail("Out of memory");
		else
			NewList(eventnode->textlist);

		AddTail(list,(struct Node *)eventnode);
	}
	return (struct Node *)eventnode;
}

struct Node *AddText(struct List *list, char *name) {

	struct Node *node;

	if (!( node = AllocMem(sizeof(struct Node),MEMF_CLEAR) ))
		fail("Out of memory");
	else {
		node->ln_Name = strdup(name);
		node->ln_Type = EVENTNODE_ID;
		node->ln_Pri  = 0;
		AddTail(list,node);
	}
	return node;
}

void RenameEvent(struct EventNode *eventnode, char *name) {
	strcpy(eventnode->eventname,name);
}

void RenameText(struct Node *node, char *name) {
	node->ln_Name = strdup(name);
}

void FreeTextList(struct List *list) {
	struct Node *node;

	while(!IsListEmpty(list)) {
		node=list->lh_Head;
		RemHead(list);
		FreeMem(node,sizeof(struct Node));
	}
}

void FreeEventList(struct List *list) {
	struct EventNode *current;

	while(!IsListEmpty(list)) {
		current=(struct EventNode *)(list->lh_Head);
		FreeTextList(current->textlist);
		FreeMem(current->textlist,sizeof(struct List));
		RemHead(list);
		FreeMem(current,sizeof(struct EventNode));
	}
}

UWORD Count(struct List *list) {
	struct Node *node;
	UWORD				i=0;

	for(every_node)
		++i;
	return i;
}

void DetachList(struct Gadget *gadget) {
	GT_SetGadgetAttrs(gadget,RecWnd,NULL,GTLV_Labels,~0,TAG_END);
}

void AttachList(struct Gadget *gadget,struct List *list) {
	GT_SetGadgetAttrs(gadget,RecWnd,NULL,GTLV_Labels,&list->lh_Head,TAG_END);
}

void DeleteEvent(struct List *list, struct EventNode *eventnode) {
	DetachList(RecGadgets[GD_EventList]);
	FreeTextList(eventnode->textlist);
	FreeMem(eventnode->textlist,sizeof(struct List));
	Remove((struct Node *)eventnode);
	FreeMem(eventnode,sizeof(struct EventNode));
	AttachList(RecGadgets[GD_EventList],list);
}

void DeleteText(struct List *list, struct Node *node) {
	DetachList(RecGadgets[GD_TextList]);
	Remove(node);
	FreeMem(node,sizeof(struct Node));
	AttachList(RecGadgets[GD_TextList],list);
}

void Up(struct Gadget *gadget,struct List *list,struct Node *node) {
	struct Node *pred=node->ln_Pred->ln_Pred;

	DetachList(gadget);
	Remove(node);
	Insert(list,node,pred);
	AttachList(gadget,list);
}

void Down(struct Gadget *gadget,struct List *list,struct Node *node) {
	struct Node *succ=node->ln_Succ;

	DetachList(gadget);
	Remove(node);
	Insert(list,node,succ);
	AttachList(gadget,list);
}

void Top(struct Gadget *gadget,struct List *list,struct Node *node) {
	DetachList(gadget);
	Remove(node);
	AddHead(list,node);
	AttachList(gadget,list);
}

void Bottom(struct Gadget *gadget,struct List *list,struct Node *node) {
	DetachList(gadget);
	Remove(node);
	AddTail(list,node);
	AttachList(gadget,list);
}

char *transform(char indate[7]) {
	char *p=strdup(indate);

	if(strlen(p)) {
		*p    =indate[4];
		*(p+1)=indate[5];
		*(p+4)=indate[0];
		*(p+5)=indate[1];
		*(p+6)='\0';
		}
	else
		p		="\0";

	return p;
}

void Sort(struct Gadget *gadget, struct List *list, int sortby) {
	BOOL done=FALSE;

	windowlock=rtLockWindow(RecWnd);
	DetachList(gadget);
	while(!done) {
		struct Node *first=list->lh_Head, *second;
		done=TRUE;

		while(first!=list->lh_TailPred) {
			second=first->ln_Succ;
			if(sortby==SORTBY_NAME) {
				if(stricmp(first->ln_Name,second->ln_Name)>0) {
					Remove(first);
					Insert(list,first,second);
					done=FALSE;
					}
				else
					first=second;
				}
			else {
				if(stricmp(	((struct EventNode *)first)->sort,
										((struct EventNode *)second)->sort)>0) {
					Remove(first);
					Insert(list,first,second);
					done=FALSE;
					}
				else
					first=second;
			}
		}
	}
	AttachList(gadget,list);
	rtUnlockWindow(RecWnd,windowlock);
}

long MarkSelected(struct Gadget *gadget,long LVtop,long current_event) {
	LVtop=(current_event>6) ? current_event-6 : 0;
	GT_SetGadgetAttrs(gadget, RecWnd, NULL,
										GTLV_Selected, current_event,
										GTLV_Top, LVtop,
										TAG_END);
	return LVtop;
}

struct Node * GetCurrent(struct List *list, long code) {
	struct Node *node=list->lh_Head;
	long i;

	for(i=0 ; i<code ; ++i)
		node=node->ln_Succ;
	return node;
}
