/* RecallPrefs.c
** sc link optimize nostandardio smallcode smalldata RecallPrefs.c lib:reqtools.lib boopsi.o
*/
#include <stdio.h>
#include <dos.h>
#include <proto/exec.h>
#include <proto/dos.h>

#include <libraries/reqtools.h>
#include <proto/reqtools.h>

#include "Includes/GUI.c"
#include "Includes/Date_Time.h"
#include "Includes/MyAlert.h"
#include "Includes/Globals.h"

struct Config config={CONFIGHEADER,FALSE,TRUE,0,1};

struct ReqToolsBase	*ReqToolsBase;
struct List					*eventlist=NULL;

struct rtFileRequester	*filereq;
char filename[34]				=prefsname;
APTR windowlock;

#define	SORTBY_NAME	0
#define SORTBY_DATE	1

/* MENU DEFINES */
#define menu_project						0
#define menu_new								0
#define menu_open								1
#define menu_merge							3
#define menu_save_as						4
#define menu_test								6
#define menu_about							8
#define menu_quit								10

#define menu_edit								1
#define menu_last_saved					0

#define menu_settings						2
#define	menu_centre_requesters	0
#define	menu_sort_by						1

/* PROTOS */
void new_project(void);
void about(void);
void handleIDCMP(void);
BOOL open_project(void);
BOOL open_old_project(void);
void merge_project(void);
void save_as_project(struct List *list);
void ShowEventGadgets(struct List *list, long ce);
void show_textgadgets(struct EventNode *event, BOOL on);
void fail(char *);
void CopyEvent(struct Gadget *gadget, struct List *, struct EventNode *);
void FreshStart(void);
void Purge(struct List *list);
void show_menu(BOOL);
int  TestProject(void);
void ShowTextGadgets(struct EventNode *event,long ct);

long mmax(long a,long b);
long mmin(long a,long b);

#include "Includes/exec_lists.h"
#include "Includes/RecallConfig.h"
#include "Includes/GetFile.h"

// must be declared as functions if you want to be able to call them
// with functions as parameters...
long mmin(long a,long b) {
	return (a<=(b)?(a):(b));
}

long mmax(long a,long b) {
	return (a>(b)?(a):(b));
}

void handleIDCMP() {
	struct IntuiMessage *imsg;
	UWORD 							menuNumber,menuNum,itemNum,subNum;
	struct Gadget				*gad;
	struct MenuItem			*item;
	char								*string;
	int									value;
	long								code;
	struct EventNode		*event=NULL;
	struct Node					*text=NULL;
	BOOL								quit=FALSE;
	long								current_event=~0,current_text=~0,LVEtop=0,LVTtop=0;
	USHORT flags;

	FreshStart();
	while (!quit) {
		Wait (1 << RecWnd->UserPort->mp_SigBit);
		while ((!quit) && (imsg = GT_GetIMsg(RecWnd->UserPort))) {
      code = imsg->Code;
			switch (imsg->Class) {
				case IDCMP_CLOSEWINDOW:
					quit=TRUE;
					break;
				case IDCMP_REFRESHWINDOW:
					GT_BeginRefresh(RecWnd);
					RecRender();
					GT_EndRefresh(RecWnd, TRUE);
					break;
				case IDCMP_GADGETDOWN:
				case IDCMP_GADGETUP:
					gad = (struct Gadget *)imsg->IAddress;
					string=GetString(gad);
					value=GetNumber(gad);
					switch(gad->GadgetID) {

						case GD_AddEvent:
							FreshStart();
							GT_SetGadgetAttrs(RecGadgets[GD_EventString], RecWnd, NULL,
																	GA_Disabled, FALSE,TAG_END);
							current_event=-1;
							ActivateGadget(RecGadgets[GD_EventString],RecWnd,NULL);
							show_menu(TRUE);
							break;
						case GD_CopyEvent:
							CopyEvent(RecGadgets[GD_EventList],eventlist,event);
							++current_event;
							event=(struct EventNode *)GetCurrent(eventlist,current_event);
							LVEtop=MarkSelected(RecGadgets[GD_EventList],LVEtop,current_event);
							break;
						case GD_DeleteEvent:
							DeleteEvent(eventlist,event);
							current_event=mmin(mmax(current_event,0),Count(eventlist)-1);
							if(!IsListEmpty(eventlist)) {
								event=(struct EventNode *)GetCurrent(eventlist,current_event);
								LVEtop=MarkSelected(RecGadgets[GD_EventList],LVEtop,current_event);
								AttachList(RecGadgets[GD_TextList],event->textlist);
								ShowEventGadgets(eventlist,current_event);
								show_menu(TRUE);
								}
							else {
								GT_SetGadgetAttrs(RecGadgets[GD_TextList], RecWnd, NULL,
																		GTLV_Labels, NULL,
																		TAG_END);
								event=NULL;
								current_event=-1;
								FreshStart();
								show_menu(FALSE);
							}
							break;
						case GD_UpEvent:
							Up(	RecGadgets[GD_EventList],
									eventlist,
									(struct Node *)event);
							current_event=mmax(current_event-1,0);
							LVEtop=MarkSelected(RecGadgets[GD_EventList],LVEtop,current_event);
							ShowEventGadgets(eventlist,current_event);
							break;
						case GD_DownEvent:
							current_event=mmin(current_event+1,Count(eventlist)-1);
							Down(	RecGadgets[GD_EventList],
										eventlist,
										(struct Node *)event);
							LVEtop=MarkSelected(RecGadgets[GD_EventList],LVEtop,current_event);
							ShowEventGadgets(eventlist,current_event);
							break;
						case GD_TopEvent:
							current_event=0;
							Top(RecGadgets[GD_EventList],
									eventlist,
									(struct Node *)event);
							LVEtop=MarkSelected(RecGadgets[GD_EventList],LVEtop,current_event);
							ShowEventGadgets(eventlist,current_event);
							break;
						case GD_BottomEvent:
							current_event=Count(eventlist)-1;
							Bottom(	RecGadgets[GD_EventList],
											eventlist,
											(struct Node *)event);
							LVEtop=MarkSelected(RecGadgets[GD_EventList],LVEtop,current_event);
							ShowEventGadgets(eventlist,current_event);
							break;
						case GD_PurgeEvent:
							Purge(eventlist);
							current_event=-1;
							FreshStart();
							break;
						case GD_SortEvent:
							Sort(RecGadgets[GD_EventList],eventlist,config.Sortby);
							current_event=-1;
							FreshStart();
							break;
						case GD_EventList:
							if(code!=current_event) {
								current_event=code;
								current_text=-1;
								event=(struct EventNode *)GetCurrent(eventlist,current_event);
								AttachList(RecGadgets[GD_TextList],event->textlist);
								show_textgadgets(event, TRUE);
								ShowEventGadgets(eventlist,current_event);
								ShowTextGadgets(event, current_text);
							}
							break;

						case GD_DateString:
							strcpy(event->date,string);
							GT_SetGadgetAttrs(RecGadgets[GD_PrefixDate], RecWnd, NULL,
														GTCY_Active, event->prefixdate=0,
														GA_Disabled, ((strlen(string)>0) ? FALSE:TRUE),
														TAG_END);
							show_textgadgets(event,TRUE);
							ActivateGadget(RecGadgets[GD_TimeString], RecWnd, NULL);
							strcpy(event->sort,transform(event->date));
							break;
						case GD_TimeString:
							strcpy(event->time,string);
							GT_SetGadgetAttrs(RecGadgets[GD_PrefixTime], RecWnd, NULL,
													GTCY_Active, event->prefixtime,
													GA_Disabled, ((strlen(string)>0) ? FALSE:TRUE),
													TAG_END);
							if(event->prefixdate)
								ActivateGadget(RecGadgets[GD_Days], RecWnd, NULL);
							break;
						case GD_PrefixDate:
							event->prefixdate=(short)code;
							GT_SetGadgetAttrs(RecGadgets[GD_Days], RecWnd, NULL,
																	GA_Disabled, (code ?FALSE:TRUE), TAG_END);
							GT_SetGadgetAttrs(RecGadgets[GD_Repeat], RecWnd, NULL,
																	GA_Disabled, (code ?FALSE:TRUE), TAG_END);
							if(event->prefixdate)
								ActivateGadget(RecGadgets[GD_Days], RecWnd, NULL);
							break;
						case GD_PrefixTime:
							event->prefixtime=(short)code;
							break;
						case GD_Days:
							event->days=value;
							if(event->prefixdate)
								ActivateGadget(RecGadgets[GD_Repeat], RecWnd, NULL);
							break;
						case GD_Repeat:
							event->repeat=value;
							break;
						case GD_AddText:
							current_text=-3;
							GT_SetGadgetAttrs(RecGadgets[GD_TextList], RecWnd, NULL,
																	GTLV_Selected, ~0, TAG_END);
							GT_SetGadgetAttrs(RecGadgets[GD_DeleteText], RecWnd, NULL,
																	GA_Disabled, TRUE, TAG_END);
							GT_SetGadgetAttrs(RecGadgets[GD_TextString], RecWnd, NULL,
																	GTST_String, NULL,
																	GA_Disabled, FALSE,TAG_END);
							show_textgadgets(event, TRUE);
							ActivateGadget(RecGadgets[GD_TextString],RecWnd,NULL);
							break;
						case GD_DeleteText:
							DeleteText(event->textlist,text);
							current_text=mmin(mmax(current_text,0),Count(event->textlist)-1);
							if(!IsListEmpty(event->textlist)) {
								text=GetCurrent(event->textlist,current_text);
								LVTtop=MarkSelected(RecGadgets[GD_TextList],LVTtop,current_text);
								}
							else
								current_text=-1;
							ShowTextGadgets(event,current_text);
							break;
						case GD_UpText:
							current_text=mmax(current_text-1,0);
							Up(	RecGadgets[GD_TextList],
									event->textlist,
									(struct Node *)text);
							LVTtop=MarkSelected(RecGadgets[GD_TextList],LVTtop,current_text);
							ShowTextGadgets(event,current_text);
							break;
						case GD_DownText:
							current_text=mmin(current_text+1,Count(event->textlist)-1);
							Down(	RecGadgets[GD_TextList],
										event->textlist,
										(struct Node *)text);
							LVTtop=MarkSelected(RecGadgets[GD_TextList],LVTtop,current_text);
							ShowTextGadgets(event,current_text);
							break;
						case GD_Type:
							event->type=(short)code;
							GT_SetGadgetAttrs(RecGadgets[GD_CalcType], RecWnd, NULL,
													GA_Disabled, ((code==2) ? TRUE:FALSE), TAG_END);
							break;
						case GD_CalcType:
							event->calctype=(int)code;
							break;
						case GD_Frequent:
							event->frequent=(int)code;
							break;
						case GD_GetFile:
							if((event->type)==2)
								if(current_text>-1) {
									RenameText(text,GetFile(filereq,RecWnd,text->ln_Name,"Select program.."));
									AttachList(RecGadgets[GD_TextList],event->textlist);
									ActivateGadget(RecGadgets[GD_TextString], RecWnd, NULL);
									}
								else if(current_text==-3) {
									GT_SetGadgetAttrs(RecGadgets[GD_TextString], RecWnd, NULL,
																		GTST_String, GetFile(filereq,RecWnd,"filename","Select program.."),
 																		TAG_END);
									ActivateGadget(RecGadgets[GD_TextString], RecWnd, NULL);
								}
							break;
						case GD_TextString:
							if(current_text==-1 | current_text==-3) {
								DetachList(RecGadgets[GD_TextList]);
								AddText(event->textlist,string);
								AttachList(RecGadgets[GD_TextList],event->textlist);
							} else {
								DetachList(RecGadgets[GD_TextList]);
								RenameText(text,string);
								AttachList(RecGadgets[GD_TextList],event->textlist);
							}
							GT_SetGadgetAttrs(RecGadgets[GD_TextList], RecWnd, NULL,
																	GTLV_Selected, ~0, TAG_END);
							GT_SetGadgetAttrs(RecGadgets[GD_DeleteText], RecWnd, NULL,
																	GA_Disabled, TRUE, TAG_END);
							GT_SetGadgetAttrs(RecGadgets[GD_TextString], RecWnd, NULL,
																	GTST_String, NULL,
																	GA_Disabled, TRUE, TAG_END);
							break;
						case GD_EventString:
							if(current_event!=-1) {
								RenameEvent(event,string);
								AttachList(RecGadgets[GD_EventList],eventlist);
								}
							else {
								DetachList(RecGadgets[GD_EventList]);
								event=(struct EventNode *)AddEvent(RecGadgets[GD_EventList],
																													eventlist,string);
								AttachList(RecGadgets[GD_EventList],eventlist);
								current_event=Count(eventlist)-1;
								LVEtop=MarkSelected(RecGadgets[GD_EventList],LVEtop,current_event);
								ShowEventGadgets(eventlist,current_event);
								show_textgadgets(event, TRUE);
								ActivateGadget(RecGadgets[GD_DateString], RecWnd, NULL);
							}
							break;
						case GD_TextList:
							if(current_text!=code) {
								current_text=code;
								ShowTextGadgets(event,current_text);
								GT_SetGadgetAttrs(RecGadgets[GD_TextString], RecWnd, NULL,
																			GA_Disabled, FALSE, TAG_END);
								text=GetCurrent(event->textlist,code);
							}
							break;

						case GD_Save:
							SavePrefs(eventlist,prefsdir,prefsname);
							quit=TRUE;
							break;
						case GD_Test:
							TestProject();
							break;
						case GD_Cancel:
							quit=TRUE;
							break;
					}
					break;
				case IDCMP_MENUPICK:
					menuNumber = imsg->Code;
					while ((menuNumber != MENUNULL) && (!quit)) {
						item = ItemAddress(RecMenus, menuNumber);
						menuNum = MENUNUM(menuNumber);
						itemNum = ITEMNUM(menuNumber);
						subNum  = SUBNUM(menuNumber);
				    flags		= ((struct MenuItem *)ItemAddress(RecMenus,(LONG)menuNumber))->Flags;
					if(menuNum == menu_project) {
							switch(itemNum) {
								case menu_new:
									new_project();
									break;
								case menu_open:
									open_project();
									current_event=-1;
									FreshStart();
									break;
								case menu_merge:
									merge_project();
									break;
								case menu_save_as:
									save_as_project(eventlist);
									break;
								case menu_test:
									TestProject();
									break;
								case menu_about:
									about();
									break;
								case menu_quit:
									quit=TRUE;
									break;
							}
						}
						else if(menuNum == menu_edit) {
							switch(itemNum) {
								case menu_last_saved:
									FreeEventList(eventlist);
									if(ReadPrefs(eventlist,prefsdir,prefsname)) {
										current_event=-1;
										FreshStart();
									}
									break;
							}
							show_menu(TRUE);
						}
						else if(menuNum == menu_settings) {
							switch(itemNum) {
								case menu_centre_requesters:
									if(flags & CHECKED)
										config.CentreRequesters=TRUE;
									else
										config.CentreRequesters=FALSE;
									break;
								case menu_sort_by:
									config.Sortby=subNum;
									break;
							}
						}
						menuNumber = item->NextSelect;
					}
					break;
			}
			GT_ReplyIMsg(imsg);
		}
	}
}

int TestProject(void) {
	BOOL success=FALSE;

	SavePrefs(eventlist,"ram:","test.script");
	if(System("Rec:Recall ram:test.script >NIL:", NULL)==NULL) {
	 	rtEZRequestTags("End of script",
										"OK",NULL,NULL,
										RTEZ_ReqTitle, recall,
										TAG_END);
		success=TRUE;
		}
	else {
	 	rtEZRequestTags("Could not run 'Recall'",
										"OK",NULL,NULL,
										RTEZ_ReqTitle, recall,
										TAG_END);
		success=FALSE;
	}
	return success && DeleteFile("ram:test.script");
}

void ShowEventGadgets(struct List *list, long ce) {
	UWORD count=Count(list);

	GT_SetGadgetAttrs(RecGadgets[GD_EventString], RecWnd, NULL,
										GA_Disabled, ((ce>-1) ? FALSE:TRUE), TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_CopyEvent], RecWnd, NULL,
										GA_Disabled, ((ce>-1) ? FALSE:TRUE), TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_DeleteEvent], RecWnd, NULL,
										GA_Disabled, ((ce>-1) ? FALSE:TRUE), TAG_END);

	GT_SetGadgetAttrs(RecGadgets[GD_UpEvent], RecWnd, NULL,
										GA_Disabled, ((ce>-1 & ce!=0) ? FALSE:TRUE), TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_DownEvent], RecWnd, NULL,
										GA_Disabled, ((ce>-1 & ce!=count-1) ? FALSE:TRUE), TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_TopEvent], RecWnd, NULL,
										GA_Disabled, ((ce>-1 & ce!=0) ? FALSE:TRUE), TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_BottomEvent], RecWnd, NULL,
										GA_Disabled, ((ce>-1 & ce!=count-1) ? FALSE:TRUE), TAG_END);

	GT_SetGadgetAttrs(RecGadgets[GD_SortEvent], RecWnd, NULL,
										GA_Disabled, ((count<2) ? TRUE:FALSE), TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_PurgeEvent], RecWnd, NULL,
										GA_Disabled, ((count<1) ? TRUE:FALSE), TAG_END);

	GT_SetGadgetAttrs(RecGadgets[GD_Test], RecWnd, NULL,
										GA_Disabled, ((count<1) ? TRUE:FALSE), TAG_END);
}

void show_textgadgets(struct EventNode *event, BOOL on) {
	GT_SetGadgetAttrs(RecGadgets[GD_AddText], RecWnd, NULL,
										GA_Disabled, !on, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_DateString], RecWnd, NULL,
										GTST_String, event->date,
										GA_Disabled, !on, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_TimeString], RecWnd, NULL,
										GTST_String, event->time,
										GA_Disabled, !on, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Type], RecWnd, NULL,
										GTCY_Active, event->type,
										GA_Disabled, !on, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Frequent], RecWnd, NULL,
										GTCY_Active, event->frequent,
										GA_Disabled, !on, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_CalcType], RecWnd, NULL,
										GTCY_Active, event->calctype,
										GA_Disabled, ((event->type==2) ? TRUE:FALSE), TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_PrefixDate], RecWnd, NULL,
										GTCY_Active, event->prefixdate,
										GA_Disabled, ((strlen(event->date)>0 && on==TRUE) ? FALSE:TRUE),
										TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_PrefixTime], RecWnd, NULL,
										GTCY_Active, event->prefixtime,
										GA_Disabled, ((strlen(event->time)>0 && on==TRUE) ? FALSE:TRUE),
										TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Days], RecWnd, NULL,
										GTIN_Number, event->days,
										GA_Disabled, ((event->prefixdate>0) ? FALSE:TRUE),
										TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Repeat], RecWnd, NULL,
										GTIN_Number, event->repeat,
										GA_Disabled, ((event->prefixdate>0) ? FALSE:TRUE),
										TAG_END);
}

void ShowTextGadgets(struct EventNode *event,long ct) {
	if(ct==-1) {
		GT_SetGadgetAttrs(RecGadgets[GD_TextList], RecWnd, NULL,
											GTLV_Selected, ~0, TAG_END);
		GT_SetGadgetAttrs(RecGadgets[GD_TextString], RecWnd, NULL,
											GTST_String, NULL,
											GA_Disabled, TRUE, TAG_END);
		GT_SetGadgetAttrs(RecGadgets[GD_DeleteText], RecWnd, NULL,
											GA_Disabled, TRUE, TAG_END);
		GT_SetGadgetAttrs(RecGadgets[GD_UpText], RecWnd, NULL,
											GA_Disabled, TRUE, TAG_END);
		GT_SetGadgetAttrs(RecGadgets[GD_DownText], RecWnd, NULL,
											GA_Disabled, TRUE, TAG_END);
		}
	else {
		GT_SetGadgetAttrs(RecGadgets[GD_DeleteText], RecWnd, NULL,
											GA_Disabled, FALSE, TAG_END);
		GT_SetGadgetAttrs(RecGadgets[GD_UpText], RecWnd, NULL,
											GA_Disabled, ((ct==0) ? TRUE:FALSE), TAG_END);
		GT_SetGadgetAttrs(RecGadgets[GD_DownText], RecWnd, NULL,
											GA_Disabled, ((ct==Count(event->textlist)-1) ? TRUE:FALSE),
											TAG_END);
	}
}

void FreshStart() {
	ShowEventGadgets(eventlist,-1);
	GT_SetGadgetAttrs(RecGadgets[GD_EventList], RecWnd, NULL,
										GTLV_Selected, ~0,TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_TextList], RecWnd, NULL,
										GTLV_Labels, NULL,TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_DeleteText], RecWnd, NULL,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_TextString], RecWnd, NULL,
										GTST_String, NULL,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_EventString], RecWnd, NULL,
										GTST_String, NULL,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_DateString], RecWnd, NULL,
										GTST_String, NULL,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_TimeString], RecWnd, NULL,
										GTST_String, NULL,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_PrefixDate], RecWnd, NULL,
										GTCY_Active, 0,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_PrefixTime], RecWnd, NULL,
										GTCY_Active, 0,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Days], RecWnd, NULL,
										GTIN_Number, 0,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Repeat], RecWnd, NULL,
										GTIN_Number, 0,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Type], RecWnd, NULL,
										GTCY_Active, 0,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_Frequent], RecWnd, NULL,
										GTCY_Active, 0,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_CalcType], RecWnd, NULL,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_UpText], RecWnd, NULL,
										GA_Disabled, TRUE, TAG_END);
	GT_SetGadgetAttrs(RecGadgets[GD_DownText], RecWnd, NULL,
										GA_Disabled, TRUE, TAG_END);
}

void Purge(struct List *list) {
	if(rtEZRequestTags(	"All expired events will be removed!",
											"Continue|Cancel",NULL,NULL,
											RTEZ_ReqTitle, recall,
											TAG_END)) {

		struct Node				*node;
		struct EventNode	*event;
		struct Date				datenow,date;
		struct Time				timenow,time;
		char							buf[8];
		BOOL							remove=FALSE;

		windowlock=rtLockWindow(RecWnd);
		DetachList(RecGadgets[GD_EventList]);
		getclk(buf);
		datenow.DD=buf[3];
		datenow.MM=buf[2];
		datenow.YY=buf[1]+80;
		timenow.HH=buf[4];
		timenow.MM=buf[5];

		for(every_node) {
			remove=FALSE;
			event=(struct EventNode *)node;
			date=to_date(event->date,DDMMYY);
			time=to_time(event->time);

			if(date.YY && date.YY<datenow.YY & date.YY>-1 & event->prefixdate!=After)
				remove=TRUE;
			else if(date.YY==datenow.YY)
				if(date.MM<datenow.MM & event->prefixdate!=After)
					remove=TRUE;
				else if(date.MM==datenow.MM)
					if(date.DD<datenow.DD & date.MM>-1 & event->prefixdate!=After)
						remove=TRUE;
					else if(date.DD==datenow.DD)
						if(time.HH<timenow.HH & event->prefixtime!=After)
							remove=TRUE;
						else if(time.HH==timenow.HH)
							if(event->prefixdate==Before)
									remove=TRUE;
			if(remove) {
				node=node->ln_Pred;
				DeleteEvent(list,event);
			}
		}
		AttachList(RecGadgets[GD_EventList],list);
		rtUnlockWindow(RecWnd,windowlock);
	}
}

void about(void) {
 	rtEZRequestTags(RECALL "  © 1993 Ketil Hunn\n\n"
								"The ultimate utility for absent-minded persons!\n\n"
								"This program is Public Domain",
								"OK",NULL,NULL,
						 		RTGS_Flags, GSREQF_CENTERTEXT,
								RTEZ_ReqTitle, recall,
								RT_Window, RecWnd,
								RT_ReqPos, REQPOS_CENTERWIN,
								TAG_END);
}

void CopyEvent(struct Gadget *gadget,struct List *list, struct EventNode *event) {
	struct Node				*node;
	struct EventNode	*copy;

	DetachList(RecGadgets[GD_EventList]);
	copy=(struct EventNode *)AddEvent(gadget,list,event->nn_Node.ln_Name);

	copy->prefixdate=(event->prefixdate);
	strcpy(copy->date,event->date);
	copy->prefixtime=(event->prefixtime);
	strcpy(copy->time,event->time);
	copy->type=(event->type);
	copy->frequent=(event->frequent);
	copy->calctype=(event->calctype);

	for(node=(struct Node *)(event->textlist->lh_Head);node->ln_Succ; node = node->ln_Succ)
		AddText(copy->textlist,node->ln_Name);

	Remove((struct Node *)copy);
	Insert(list,(struct Node *)copy,(struct Node *)event);
	AttachList(RecGadgets[GD_EventList],list);
}

BOOL open_project(void) {
	if(rtFileRequest(filereq, filename,
									"Select project to open...",
									RT_Window, RecWnd,
									RT_LockWindow, TRUE,
									TAG_END)) {
		FreeEventList(eventlist);
		ReadPrefs(eventlist,filereq->Dir,filename);
		show_menu(TRUE);
		return TRUE;
	}
}

void merge_project(void) {
	if(rtFileRequest(filereq, filename,
									"Select project to merge...",
									RT_Window, RecWnd,
									RT_LockWindow, TRUE,
									TAG_END)) {
		ReadPrefs(eventlist,filereq->Dir,filename);
	}
}

void save_as_project(struct List *list) {
	if(rtFileRequest(filereq, filename,
										"Save project as...",
										RT_Window, RecWnd,
										RT_LockWindow, TRUE,
										TAG_END)) {
		SavePrefs(list,filereq->Dir,filename);
	}
}

void new_project(void) {
	if(rtEZRequestTags(	"Clear all events?",
											"OK|Cancel", NULL, NULL,
											RTEZ_ReqTitle, recall,
											TAG_END)) {
		FreeEventList(eventlist);
		AttachList(RecGadgets[GD_EventList],eventlist);
		GT_SetGadgetAttrs(RecGadgets[GD_TextList], RecWnd, NULL,
											GTLV_Labels, NULL,
											TAG_END);
		FreshStart();
		show_menu(FALSE);
	}
}

void show_menu(BOOL on) {
	if(on) {
		OnMenu(RecWnd,FULLMENUNUM(0,0,0));
		OnMenu(RecWnd,FULLMENUNUM(0,3,0));
		OnMenu(RecWnd,FULLMENUNUM(0,4,0));
		OnMenu(RecWnd,FULLMENUNUM(0,6,0));
		}
	else {
		OffMenu(RecWnd,FULLMENUNUM(0,0,0));
		OffMenu(RecWnd,FULLMENUNUM(0,3,0));
		OffMenu(RecWnd,FULLMENUNUM(0,4,0));
		OffMenu(RecWnd,FULLMENUNUM(0,6,0));
	}
}

void fail(char *message) {
	char *add="\n\nPress mouse button to continue";
	MyAlert(RECOVERY_ALERT, strcat(message,add));
}

BOOL openlibs(void) {
	if((IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",36))) {
		if((GadToolsBase=OpenLibrary("gadtools.library",36))!= NULL) {
			if((ReqToolsBase=(struct ReqToolsBase *)OpenLibrary(REQTOOLSNAME,REQTOOLSVERSION))!=NULL) {
				return TRUE;
			} else
				fail("This program needs reqtools.library V38+");
		} else
			fail("Could not open gadtools.library V36+");
	}
	return FALSE;
}

void closelibs(void) {
	if(ReqToolsBase) {
		rtFreeRequest(filereq);
		CloseLibrary((struct Library *)ReqToolsBase);
	}
	if(GadToolsBase)	CloseLibrary(GadToolsBase);
	if(IntuitionBase)	CloseLibrary((struct Library *)IntuitionBase);
}

main() {
	if(openlibs()) {
		if(!( filereq=rtAllocRequestA(RT_FILEREQ, NULL) ))
			fail("Out of memory");
		else {
			if (!( eventlist=AllocMem(sizeof(struct List),MEMF_CLEAR)) )
				fail("Out of memory");
			else {
				NewList(eventlist);
	
				SetupScreen();
				OpenRecWindow();
				if(ReadPrefs(eventlist,prefsdir,prefsname))
					show_menu(TRUE);
				rtChangeReqAttr(filereq,
												RTFI_Dir, prefsdir,
												TAG_END);
				handleIDCMP();
				CloseRecWindow();
				CloseDownScreen();

				FreeEventList(eventlist);
				FreeMem(eventlist,sizeof(struct List));
			}
		}
	}
	closelibs();
}
