/*
 *	File:					Iffconfig.h
 *	Description:	Defines the structure of the configuration and events.
 *								Reads and writes the project as an V2.0 IFF-FORM.
 *
 *	(C) 1993 Ketil Hunn
 *
 */

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


#include <libraries/iffparse.h>
#include <clib/iffparse_protos.h>
#include <dos.h>
#include <exec/memory.h>
#include <string.h>

#define  ID_PREF	MAKE_ID('P','R','E','F')
#define  ID_CONF	MAKE_ID('C','O','N','F')
#define  ID_EVNT	MAKE_ID('E','V','N','T')
#define  ID_ETXT	MAKE_ID('E','T','X','T')

struct Config {
	BOOL	centrerequesters;
	BOOL	groupevents;
	BOOL	flashscreen;
	BOOL	ack_events;
	BOOL	ack_alerts;
	BOOL  ask_before_execute;
	BOOL  putoff;
	BOOL	autodelete;
	BOOL	confirm;
	BOOL	autoopencalendar;
	BOOL	usereqtools;
	int		sortby;
} config;

struct EventNode {
	struct Node nn_Node;
	char				name[30];
	short				whendate;
	short				day;
	short				month;
	int					year;
	short				whentime;
	short				hour;
	short				minutes;
	int					days;
	int					repeat;
	short				type;
	short				show;
	short				calc;
	long				datestamp;
	short				display;
	short				expansion1;
	short				expansion2;
	struct List	*textlist;
};

struct ENode {
	char				name[30];
	short				whendate;
	short				day;
	short				month;
	int					year;
	short				whentime;
	short				hour;
	short				minutes;
	int					days;
	int					repeat;
	short				type;
	short				show;
	short				calc;
	long				datestamp;
	short				display;
	short				expansion1;
	short				expansion2;
	struct List	*textlist;
};

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

	if(eventnode=AllocMem(sizeof(struct EventNode),MEMF_CLEAR))
	{
		strcpy(eventnode->name,name);
		eventnode->nn_Node.ln_Name=eventnode->name;
		eventnode->nn_Node.ln_Type=100;
		eventnode->nn_Node.ln_Pri =0;

		if(eventnode->textlist = AllocMem(sizeof(struct List),MEMF_CLEAR))
			NewList(eventnode->textlist);

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

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

	if(node=AllocMem(sizeof(struct Node),MEMF_CLEAR))
	{
		node->ln_Name = strdup(name);
		node->ln_Type = 100;
		node->ln_Pri  = 0;
		AddTail(list,node);
	}
	return node;
}

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

	while(!IsListEmpty(list))
	{
		node=list->lh_Head;
		RemHead(list);
		free(node->ln_Name);
		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));
	}
}

BOOL ReadIFF(struct List *list, char source[256])
{
	struct IFFHandle		*iff;
	struct ContextNode	*cn;
	struct ENode				enode;
	struct EventNode    *node;
	long								error;
	char 								tmp[FNSIZE];
	BOOL success=FALSE;

	if(iff=AllocIFF())
	{
		if(iff->iff_Stream=Open(source, MODE_OLDFILE))
		{
			InitIFFasDOS (iff);
			if(!(error=OpenIFF(iff, IFFF_READ)))
			{
				ParseIFF(iff, IFFPARSE_RAWSTEP);
				cn=CurrentChunk(iff);
				if(cn->cn_ID!=ID_FORM && cn->cn_Type!=ID_PREF)
					MyAlert(RECOVERY_ALERT, GetString(&li, MSG_NOTIFF));
				else
				{
					ParseIFF(iff, IFFPARSE_RAWSTEP);
					cn=CurrentChunk(iff);
					if(cn->cn_ID!=ID_CONF)
						MyAlert(RECOVERY_ALERT, GetString(&li, MSG_NOTIFF));
					else
					{
						ReadChunkBytes(iff,(APTR)&config, cn->cn_Size);
						while(TRUE)
						{
							error=ParseIFF(iff, IFFPARSE_RAWSTEP);
							if(error==IFFERR_EOC)
								continue;
							else if(error)
								break;

							success=TRUE;
							if(cn=CurrentChunk(iff))
							{
								switch(cn->cn_ID)
								{
									case ID_EVNT:
										if(ReadChunkBytes(iff,(APTR)&enode,cn->cn_Size)==cn->cn_Size) {
											node=AddEvent(list, enode.name);
											node->whendate	=enode.whendate;
											node->day				=enode.day;
											node->month			=enode.month;
											node->year			=enode.year;
											node->whentime	=enode.whentime;
											node->hour			=enode.hour;
											node->minutes		=enode.minutes;
											node->days			=enode.days;
											node->repeat		=enode.repeat;
											node->type			=enode.type;
											node->show			=enode.show;
											node->calc			=enode.calc;
											node->datestamp	=enode.datestamp;
										}
										break;

									case ID_ETXT:
										if(ReadChunkBytes(iff,(APTR)&tmp,cn->cn_Size)==cn->cn_Size)
											AddText(node->textlist, tmp);
										break;
								}
							}
						}
						if(error!=IFFERR_EOF)
							MyAlert(RECOVERY_ALERT, GetString(&li, MSG_IFFERROR));
					}
				}
				CloseIFF (iff);
			}
			Close (iff->iff_Stream);
		}
		else
			MyAlert(RECOVERY_ALERT, GetString(&li, MSG_COULDNOTFIND));
		FreeIFF (iff);
	}
	return success;
}

void WriteIFFTexts(struct IFFHandle *iff, struct List *list)
{
	struct Node *node;

	for(every_node)
	{
		PushChunk(iff, 0, ID_ETXT, IFFSIZE_UNKNOWN);
		WriteChunkBytes(iff, node->ln_Name, strlen(node->ln_Name)+1);
		PopChunk(iff);
	}
}

BOOL WriteIFF(struct List *list, char *destination)
{
	struct EventNode		*eventnode;
	struct ENode				*enode;
	struct Node					*node;
	struct IFFHandle		*iff;

	iff=AllocIFF();
	iff->iff_Stream=Open(destination, MODE_NEWFILE);
	InitIFFasDOS(iff);
	OpenIFF(iff,IFFF_WRITE);

	PushChunk(iff, ID_PREF, ID_FORM, IFFSIZE_UNKNOWN);

	PushChunk(iff, 0, ID_CONF, IFFSIZE_UNKNOWN);
	WriteChunkBytes(iff, &config, sizeof(struct Config));
	PopChunk(iff);

	enode=AllocMem(sizeof(struct ENode), MEMF_CLEAR);
	for(every_node)
	{
		eventnode=(struct EventNode *)node;
		strcpy(enode->name,eventnode->name) ;
		enode->whendate	=eventnode->whendate;
		enode->day			=eventnode->day;
		enode->month		=eventnode->month;
		enode->year			=eventnode->year;
		enode->whentime	=eventnode->whentime;
		enode->hour			=eventnode->hour;
		enode->minutes	=eventnode->minutes;
		enode->days			=eventnode->days;
		enode->repeat		=eventnode->repeat;
		enode->type			=eventnode->type;
		enode->show			=eventnode->show;
		enode->calc			=eventnode->calc;
		enode->datestamp=eventnode->datestamp;

		PushChunk(iff, 0, ID_EVNT, IFFSIZE_UNKNOWN);
		WriteChunkBytes(iff, enode, sizeof(struct ENode));
		PopChunk(iff);

		WriteIFFTexts(iff, eventnode->textlist);
	}
	PopChunk(iff);

	CloseIFF(iff);
	Close(iff->iff_Stream);
	FreeIFF(iff);
	FreeMem(enode, sizeof(struct ENode));
	return TRUE;
}
