/*
 *
 *  AM --- AmigaMail
 *  (C) 1991, 1992 by Christian Riede
 *
 *  AM is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY.  No author or distributor accepts responsibility to anyone
 *  for the consequences of using it or for whether it serves any
 *  particular purpose or works at all, unless he says so in writing.
 *  Refer to the GNU General Public License, Version 1, for full details.
 *  
 *  Everyone is granted permission to copy, modify and redistribute AM,
 *  but only under the conditions described in the GNU General Public
 *  License, Version 1.  A copy of this license is supposed to have been 
 *  given to you along with AM so you can know your rights and responsi-
 *  bilities.  It should be in a file named COPYING.  Among other things,
 *  the copyright notice and this notice must be preserved on all copies.
 *
 *  
 *
 */

#include "am.h"

UBYTE *vers = (UBYTE *)("\0$VER: AM:"AMIGAMAIL_VERSION);

/* stolen from TERM by Olaf "Olsen" Barthel */
static USHORT StopwatchProto[(2 + 16) * 2] =
{
	0x0000,0x0000,

	0x0400,0x07C0,
	0x0000,0x07C0,
	0x0100,0x0380,
	0x0000,0x07E0,
	0x07C0,0x1FF8,
	0x1FF0,0x3FEC,
	0x3FF8,0x7FDE,
	0x3FF8,0x7FBE,
	0x7FFC,0xFF7F,
	0x7EFC,0xFFFF,
	0x7FFC,0xFFFF,
	0x3FF8,0x7FFE,
	0x3FF8,0x7FFE,
	0x1FF0,0x3FFC,
	0x07C0,0x1FF8,
	0x0000,0x07E0,

	0x0000,0x0000
};

USHORT *Stopwatch;

#ifdef AZTEC_C 
extern struct WBStartup *WBenchMsg;
#endif

struct TextAttr TextAttr;
struct TextFont *TextFont;

/* poer where notification messages arrive */
struct MsgPort *NotifyPort;

char Username[MAIL_FIELDLENGTH];
char Realname[MAIL_FIELDLENGTH];

char Folder[MAIL_FIELDLENGTH];

/* title of window */
static char Windowtitle[160];

/* title of the listview gadget */
static char Mailboxtitle[160];

/* contents is locked? */
int ContentsLocked = FALSE;

/* number of running subprocesses (->send.c) */
int running = 0;

/* flags for mail loop */
static int run;
static int ExitFlag;

/* the menues */

#define PROJ_ABOUT        101
#define PROJ_EXIT         102
#define PROJ_QUIT         103
#define PROJ_FOLDER       104
#define PROJ_CREATEFOLDER 105

#define AC_READ          201
#define AC_SAVE          202
#define AC_SEND          203
#define AC_REPLY         207
#define AC_REPLY_GROUP   209
#define AC_FORWARD       210
#define AC_FORWARD_MIME  211
#define AC_MARK_READ     212
#define AC_MARK_UNREAD   213
#define AC_SEARCH_TEXT   214
#define AC_PRINT         215
#define AC_MOVE          216
#define AC_DELETE        217

#define ADDR_EDIT         301
#define ADDR_PRINT        302
#define ADDR_ADDCURR      303

#define CONF_FONT         401
#define CONF_COLORS       402
#define CONF_SCREEN       404
#define CONF_MEDITOR      405
#define CONF_RFILTER      406
#define CONF_ILBMFILTER   407
#define CONF_SIGNATURE    408
#define CONF_REPLY_TO     409
#define CONF_SAVE         410
#define CONF_LOAD         411
#define CONF_BASE64       412
#define CONF_QUOTED_PRINTABLE 413
#define CONF_8BIT         414
#define CONF_7BIT         415
#define CONF_BINARY       416
#define CONF_CTE          417
#define SCR_PUBSCR        418

/* using APTR UserData as ULONG-Constant. Requires some silly casting */
static struct NewMenu NewMenu[] = {
{NM_TITLE,(STRPTR)"Project",0,0,0,0},
	{NM_ITEM,(STRPTR)"About",0,0,0,(APTR)PROJ_ABOUT},
	{NM_ITEM,(STRPTR)"Open Folder",(STRPTR)"o",0,0,(APTR)PROJ_FOLDER},
	{NM_ITEM,(STRPTR)"Create Folder",0,0,0,(APTR)PROJ_CREATEFOLDER},
	{NM_ITEM,(STRPTR)"Exit",(STRPTR)"x",0,0,(APTR)PROJ_EXIT},
	{NM_ITEM,(STRPTR)"Quit",(STRPTR)"q",0,0,(APTR)PROJ_QUIT},
{NM_TITLE,(STRPTR)"Action",0,0,0,0},
	{NM_ITEM,(STRPTR)"Move",(STRPTR)"m",0,0,(APTR)AC_MOVE},
	{NM_ITEM,(STRPTR)"Delete",(STRPTR)"d",0,0,(APTR)AC_DELETE},
	{NM_ITEM,(STRPTR)"Send",(STRPTR)"s",0,0,(APTR)AC_SEND},
	{NM_ITEM,(STRPTR)"Reply",(STRPTR)"r",0,0,(APTR)AC_REPLY},
	{NM_ITEM,(STRPTR)"Group Reply",0,0,0,(APTR)AC_REPLY_GROUP},
	{NM_ITEM,(STRPTR)"Forward",(STRPTR)"f",0,0,(APTR)AC_FORWARD},
	{NM_ITEM,(STRPTR)"Mark as Read",0,0,0,(APTR)AC_MARK_READ},
	{NM_ITEM,(STRPTR)"Mark as Unread",0,0,0,(APTR)AC_MARK_UNREAD},
	{NM_ITEM,(STRPTR)"Save",0,0,0,(APTR)AC_SAVE},
	{NM_ITEM,(STRPTR)"Print",(STRPTR)"p",0,0,(APTR)AC_PRINT},
	{NM_ITEM,(STRPTR)"Read",0,0,0,(APTR)AC_READ},
	{NM_ITEM,(STRPTR)"Search Text",0,0,0,(APTR)AC_SEARCH_TEXT},
{NM_TITLE,(STRPTR)"Addressbook",0,0,0,0},
	{NM_ITEM,(STRPTR)"Edit...",0,0,0,(APTR)ADDR_EDIT},
/*	{NM_ITEM,(STRPTR)"Print...",0,0,0,(APTR)ADDR_PRINT},*/
	{NM_ITEM,(STRPTR)"Add current from-address",0,0,0,(APTR)ADDR_ADDCURR},
{NM_TITLE,(STRPTR)"Config",0,0,0,0},
	{NM_ITEM,(STRPTR)"Font...",0,0,0,(APTR)CONF_FONT},
	{NM_ITEM,(STRPTR)"Colors...",0,0,0,(APTR)CONF_COLORS},
	{NM_ITEM,(STRPTR)"Screen",0,0,0,(APTR)CONF_SCREEN},
		{NM_SUB,(STRPTR)"PAL HIRES",0,CHECKIT,~1,(APTR)(PAL_MONITOR_ID|HIRES_KEY)},
		{NM_SUB,(STRPTR)"PAL HIRES LACE",0,CHECKIT,~2,(APTR)(PAL_MONITOR_ID|HIRESLACE_KEY)},
		{NM_SUB,(STRPTR)"NTSC HIRES",0,CHECKIT,~4,(APTR)(NTSC_MONITOR_ID|HIRES_KEY)},
		{NM_SUB,(STRPTR)"NTSC HIRES LACE",0,CHECKIT,~8,(APTR)(NTSC_MONITOR_ID|HIRESLACE_KEY)},
		{NM_SUB,(STRPTR)"PRODUCTIVITY",0,CHECKIT,~16,(APTR)(VGAPRODUCT_KEY)},
		{NM_SUB,(STRPTR)"PRODUCTIVITY LACE",0,CHECKIT,~32,(APTR)(VGAPRODUCTLACE_KEY)},
		{NM_SUB,(STRPTR)"Public Screen",0,CHECKIT,~64,(APTR)SCR_PUBSCR},
	{NM_ITEM,(STRPTR)"Mail Editor",0,0,0,(APTR)CONF_MEDITOR},
	{NM_ITEM,(STRPTR)"Text Viewer",0,0,0,(APTR)CONF_RFILTER},
	{NM_ITEM,(STRPTR)"Signature File",0,0,0,(APTR)CONF_SIGNATURE},
	{NM_ITEM,(STRPTR)"Reply-To Address",0,0,0,(APTR)CONF_REPLY_TO},
	{NM_ITEM,(STRPTR)"Content-Transfer-Encoding",0,0,0,(APTR)CONF_CTE},
		{NM_SUB,(STRPTR)"BASE64",0,CHECKIT,~1,(APTR)CONF_BASE64},
		{NM_SUB,(STRPTR)"QUOTED-PRINTABLE",0,CHECKIT,~2,(APTR)CONF_QUOTED_PRINTABLE},
		{NM_SUB,(STRPTR)"8BIT",0,CHECKIT,~4,(APTR)CONF_8BIT},
		{NM_SUB,(STRPTR)"7BIT",0,CHECKIT,~8,(APTR)CONF_7BIT},
		{NM_SUB,(STRPTR)"BINARY",0,CHECKIT,~16,(APTR)CONF_BINARY},
	{NM_ITEM,(STRPTR)"Load Config...",0,0,0,(APTR)CONF_LOAD},
	{NM_ITEM,(STRPTR)"Save Config...",0,0,0,(APTR)CONF_SAVE},
{NM_END,0,0,0,0,0}
};

/* the gadgets (dimensions adjusted later) */

static struct NewGadget ListGadget = 
{
	0,0,0,0,
	(UBYTE *)Mailboxtitle,&TextAttr,
	LIST,
	PLACETEXT_ABOVE,
	0,	
	0
};

static char *SelectLabels[] = {
"Select New","Select All","Select Last Week","Select From Me","Select To Me","Select Matching",0
};

static struct NewGadget SelectGadget =
{
	0,0,0,0,
	(UBYTE *)"Select",&TextAttr,
	SELECT,
	PLACETEXT_RIGHT,
	0,	
	0
};

static char *ShowLabels[] = {
"Show All","Show From","Show To","Show Subject","Show Date","Show MsgId",0
};

static struct NewGadget ShowGadget =
{
	0,0,0,0,
	(UBYTE *)"Select",&TextAttr,
	SHOW,
	PLACETEXT_RIGHT,
	0,	
	0
};

static char *SortLabels[] = {
"Sort Number","Sort From","Sort To","Sort Subject","Sort Date","Sort Thread",0
};

static struct NewGadget SortGadget =
{
	0,0,0,0,
	(UBYTE *)"Select",&TextAttr,
	SORT,
	PLACETEXT_RIGHT,
	0,	
	0
};

/* the mailbox list */
struct List Mailbox;

/* the list of displayed items */
struct List Selected;

/* the screen we are using */
struct Screen *Screen,*PubScreen;

/* our window */
struct Window *Window;

/* to save MyProcess->pr_WindowPtr */
static struct Window *OldProcessWindow;

/* the libraries */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Library *GadToolsBase;
struct Library *IconBase;
struct Library *AslBase;
struct Library *DiskfontBase;

/* some pointers to gadgets */
static struct Gadget *GList,*gad,*LVGadget,*SelGad;

/* the menu */
static struct Menu *Menu;

/* myself */
static struct Process *MyProcess;

/* File-/fontrequester */
struct FileRequester *FReq;
struct FontRequester *FontReq;

/* functions currently used to display the mailbox */
void (*Show)(struct List *) = ShowAll;
void (*Select)(struct List *,struct List *,
	void (*Sort)(struct List *,struct Mail *),void *) = SelectNew;
void (*Sort)(struct List *,struct Mail *) = InsertByDate;

int ActSelect = 0;
int ActShow = 0;
int ActSort = 4;

char SearchPattern[MAIL_FIELDLENGTH];

/* the last selected item */
int LastSelected = -1;

static UWORD pens = ~0;

static char Config[CONFIG_LENGTH];

/* Our windows dimensions */
int WLeft,WTop,WWidth,WHeight;

static struct RDArgs *RDArgs;

static LONG CommandLine[4];

/* show busy pointer, turn IDCMP off */
void Busy(void)
{
	SetWindowTitles(Window,(UBYTE *)Windowtitle,(UBYTE *)"AmigaMail (Busy)");
	ModifyIDCMP(Window,0L);
	SetPointer(Window,&Stopwatch[0],16,16,-6,0);
}

/* show normal pointer, turn IDCMP on */
void Ready(void)
{
	SetWindowTitles(Window,(UBYTE *)Windowtitle,(UBYTE *)"AmigaMail");
	ModifyIDCMP(Window,SIZEVERIFY|NEWSIZE|MENUPICK|CLOSEWINDOW|LISTVIEWIDCMP|MXIDCMP|VANILLAKEY|RAWKEY);
	ClearPointer(Window);
}

/* show panic-requester, cleanup, exit with given returncode */
void Panic(int ret,char *message)
{
	struct Message *Msg;

	/* TODO: free contents list */

	/* show message */
	if (message)
		if (*message)
			if (IntuitionBase) SimpleRequest(Window,message);
			else puts(message);

	/* restore MyProcess->pr_WindowPtr */
	if (OldProcessWindow) MyProcess->pr_WindowPtr = OldProcessWindow;

	/* remove menus */
	if (Menu) {ClearMenuStrip(Window); FreeMenus(Menu); Menu=0;}

	/* remove,free gadgets */
	if (GList) {RemoveGList(Window,GList,-1); FreeGadgets(GList); GList = 0;}

	/* close window */
	if (Window) {CloseWindow(Window); Window = 0;}

	/* free visual info */
	if (ListGadget.ng_VisualInfo) 
		FreeVisualInfo(ListGadget.ng_VisualInfo);

	/* close screen */
	if (Screen) {CloseScreen(Screen); Screen = 0;}
	if (PubScreen) {UnlockPubScreen(0,PubScreen); PubScreen = 0;}

	if (TextFont) {CloseFont(TextFont); TextFont = 0;}

	if (ret >= 0)
	{
		/* disable notification */
		if (NotifyPort) 
		{
			if (ServerPort)
				NotifyOff(NotifyPort,Folder);
				
			while (Msg = GetMsg(NotifyPort));
		}

		if (ContentsLocked) 
		{
			FreeMailbox(&Mailbox);
			UnLockContents(Folder);
			ContentsLocked = FALSE;
		}

		if (NotifyPort) DeletePort(NotifyPort);

		if (FReq) {FreeFileRequest(FReq); FReq = 0;}

		if (FontReq) {FreeAslRequest(FontReq); FontReq = 0;}

		if (Stopwatch) FreeMem(Stopwatch,sizeof(StopwatchProto));

		/* close libraries */
		if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
		if (GfxBase) CloseLibrary((struct Library *)IntuitionBase);
		if (GadToolsBase) CloseLibrary(GadToolsBase);
		if (DiskfontBase) CloseLibrary((struct Library *)DiskfontBase);
		if (IconBase) CloseLibrary(IconBase);
		if (AslBase) CloseLibrary(AslBase);
/*		if (SregExpBase) CloseLibrary((struct Library *)SregExpBase);*/

		/* that's it */
		exit(ret);

	}
}

/* called when caught a signal */
void SigPanic(int Signal)
{
	if (Signal == SIGINT)
	{
		run=FALSE;
		ExitFlag=FALSE;
	}
	else
		Panic(100,"Caught Signal");
}

/* refresh display */
/* if Select!=0 build new display list */
/* if show!=0 generate new strings to display */
void RefreshDisplay(void (*Select)(struct List *,struct List *,
	void (*)(struct List *,struct Mail *),void *),
	void (*Show)(struct List *),void (*Sort)(struct List *,struct Mail *),
	struct List *Mailbox, struct List *Selected,int select,void *extra)
{

	/* remove list from gadget */
	GT_SetGadgetAttrs(LVGadget,Window,0,
		GTLV_Labels,0L,
		TAG_END);

	/* do the new showing/selection */
	if (Show) (*Show)(Mailbox);
	if (Select && Sort) 
	{
		DeselectAll(Selected);
		(*Select)(Mailbox,Selected,Sort,extra);
	}		

	/* put list into gadget */
	if (select!=-1)
		GT_SetGadgetAttrs(LVGadget,Window,0,
			GTLV_Labels,Selected,
			GTLV_Selected, select,
			TAG_END);
	else
		GT_SetGadgetAttrs(LVGadget,Window,0,
			GTLV_Labels,Selected,
			TAG_END);

	/* refresh all */
	RefreshGList(GList,Window,NULL,-1);

}

/* get Realname of given User */
/* look up in GETTY:passwd */
static int GetRealName(char *Realname,char *Username)
{
	FILE *passwd;
	static char InputBuffer[MAIL_FIELDLENGTH];
	static char Compare[20];

	if (!(passwd = fopen("GETTY:passwd","r")))
		return(FALSE);

	while (fgets(InputBuffer,MAIL_FIELDLENGTH,passwd))
	{
		if (InputBuffer[0]=='#') continue;
		if (InputBuffer[0]==' ') continue;
		if (InputBuffer[0]=='\n') continue;

		if (sscanf(InputBuffer,"%[^,],%*[^,],%*d,%*d,%[^,],",Compare,Realname)==2)
		{
			if (!strcmp(Compare,Username))
			{
				fclose(passwd);
				if (Realname[0]=='(' && Realname[strlen(Realname)-1]==')')
				{
					while (*(Realname+1)) 
					{
						*Realname = *(Realname+1);
						Realname++;
					}
					*(--Realname)=0;
				}
				return(TRUE); /* that's what we were looking for */
			}
		}
	}

	fclose(passwd);

	return(FALSE);
}

int main(int argc, char *argv[])
{
	struct Mail *New,*Mail;
	struct IntuiMessage *IMsg;
	struct AMMessage *Msg;
	ULONG Class;
	ULONG Code;
	APTR IAddr;
	struct DiskObject *dop=0;
	struct MenuItem *MenuItem;
	ULONG LastSecs=0,LastMicros=0;
	ULONG Secs,Micros;
	struct NewMenu *nm;
    struct DimensionInfo di;
    struct Rectangle *rect;
    unsigned long vpmid;
	char SendParms[160];
	int SearchHeader;
	ULONG Signals;
	char *s;
	struct WBStartup *WBenchMsg;
	char Buf[MAIL_FIELDLENGTH];
	BPTR MyLock;

	/* catch signals */
	signal(SIGFPE,SigPanic);
	signal(SIGILL,SigPanic);
	signal(SIGABRT,SigPanic);
	signal(SIGBUS,SigPanic);
	signal(SIGSEGV,SigPanic);

	/* print copyright notice */
	if (argc) /* startet from CLI ? */
	{
		printf("AM %s - AmigaMail\n",AMIGAMAIL_VERSION);
		puts("© 1991, 1992 by Christian Riede");
		puts("Use and distribute under the terms of the");
		puts("GNU General Public Licence, Version 1!");
	}

	/* set MyProcess->pr_WindowPtr to my window */
	MyProcess = (struct Process *) FindTask(0L);
	OldProcessWindow = MyProcess->pr_WindowPtr;
	MyProcess->pr_WindowPtr = Window;
	
	/* open libraries */
	if (!(IntuitionBase = (struct IntuitionBase *)
		OpenLibrary((UBYTE *)"intuition.library",AM_LIBRARY_VERSION)))
		Panic(20,"Can't open intuition.library!");

	if (!(GfxBase = (struct GfxBase *)
		OpenLibrary((UBYTE *)"graphics.library",AM_LIBRARY_VERSION)))
		Panic(50,"Can't open graphics.library!");

	if (!(DiskfontBase = 
		OpenLibrary((UBYTE *)"diskfont.library",AM_LIBRARY_VERSION)))
		Panic(51,"Can't open diskfont.library!");

	if (!(GadToolsBase =
		OpenLibrary((UBYTE *)"gadtools.library",AM_LIBRARY_VERSION)))
		Panic(21,"can't open gadtools.library!");

	if (!(IconBase = 
		OpenLibrary((UBYTE *)"icon.library",AM_LIBRARY_VERSION)))
		Panic(40,"can't open icon.library!");

	if (!(AslBase = 
		OpenLibrary((UBYTE *)"asl.library",AM_LIBRARY_VERSION)))
		Panic(45,"can't open asl.library!");

	/* copy Stopwatch to ChipMem */
	if (!(Stopwatch = AllocMem(sizeof(StopwatchProto),MEMF_CHIP)))
		Panic(52,"No ChipMem");
	CopyMem(StopwatchProto,Stopwatch,sizeof(StopwatchProto));

	/* get user-/realname */
	if (argc) /* started from CLI */
	{
		if (!(RDArgs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL)))
			Panic(65,"Can't get RDArgs");

		/* can check argv[1] only when it's sure */
		/* that we have at least one argument  */
		if (argc>1)
			if (*argv[1]=='?')
				goto getfromstdin;

		RDArgs->RDA_Source.CS_Buffer = GetArgStr();
		RDArgs->RDA_Source.CS_Length = (RDArgs->RDA_Source.CS_Buffer)?
			(strlen((char *)RDArgs->RDA_Source.CS_Buffer)):(0);

getfromstdin:

		if (!(ReadArgs((UBYTE *)"USERNAME,CONFIGNAME,FOLDER",CommandLine,RDArgs)))
		{
			printf("USAGE: %s [USERNAME] [CONFIG] [FOLDER]",argv[0]);
			puts("(or setenv USERNAME)");
			FreeDosObject(DOS_RDARGS, RDArgs);
			Panic(0,0);
		}

		if (CommandLine[0]) 
			strcpy(Username,(char *)CommandLine[0]);
		else
			if (!(getenv("USERNAME")))
				Panic(0,"Can't get USERNAME!");
			else
				strcpy(Username,getenv("USERNAME"));


		if (CommandLine[1]) 
			strcpy(Config,(char *)CommandLine[1]);

		if (CommandLine[2])
			strcpy(Folder,(char *)CommandLine[2]);

		FreeArgs(RDArgs);
		FreeDosObject(DOS_RDARGS, RDArgs);

		if (!GetRealName(Realname,Username))
		{
			printf("\nNo entry found for user %s\n",Username);
			Panic(0,0);
		}
	}
	else /* started from WB */
	{
		WBenchMsg = (struct WBStartup *)argv;

		if (!(dop = GetDiskObject((UBYTE *)WBenchMsg->sm_ArgList->wa_Name)))
			Panic(41,"can't get diskobject!");

		/* try to get Username from ToolTypes */
		s = (char *) FindToolType((UBYTE **)dop->do_ToolTypes ,(UBYTE *)"USERNAME");

		if (s) /* found? */
		{
			strcpy(Username,s);
			if (!GetRealName(Realname,Username))
				Panic(53,"No entry found for user!");
		}
		else if (!(getenv("USERNAME")))
			Panic(54,"Can't get USERNAME/REALNAME!");
		else
		{
			strcpy(Username,getenv("USERNAME"));
			if (!GetRealName(Realname,Username))
				Panic(55,"No entry found for user!");
		}

		/* config file given? */
		s = (char *) FindToolType((UBYTE **)dop->do_ToolTypes ,(UBYTE *)"CONFIG");

		if (s)
			strcpy(Config,s);

		/* folder given? */
		s = (char *) FindToolType((UBYTE **)dop->do_ToolTypes ,(UBYTE *)"FOLDER");

		if (s)
			strcpy(Folder,s);

		FreeDiskObject(dop);
	}

	/* default folder if none given */
	if (!Folder[0])
		sprintf(Folder,"uumail:%s.mail",Username);

	/* create NIL: filehandles for System() */
	if (!(AMSystemTags[0].ti_Data = (ULONG)
		Open((UBYTE *)"NIL:",MODE_OLDFILE)))
		Panic(48,"Can't open NIL: for read!");
	if (!(AMSystemTags[1].ti_Data = (ULONG)
		Open((UBYTE *)"NIL:",MODE_NEWFILE)))
		Panic(49,"Can't open NIL: for write!");

	/* find server */
	if (!(ServerPort = FindPort(SERVERNAME)))
		Panic(59,"server not running!");

	/* create notify port */
	if (!(NotifyPort = CreatePort(0,0)))
		Panic(60,"can't create notify port!");

	/* check version of server */
	if (!CmpVersion())
		Panic(61,"Wrong version of server!");

	/* read Config */
	if (!*Config)
		strcpy(Config,"UULIB:am.config");
	ReadConfig(Config);

	if (!*NodeName) Panic(36,"No NodeName in UULIB:Config!");
	if (!*DomainName) strcpy(DomainName,".UUCP");

	/* init the mailbox-list */
	Mailbox.lh_Head = (struct Node *)&Mailbox.lh_Tail;
	Mailbox.lh_TailPred = (struct Node *)&Mailbox.lh_Head;
	Mailbox.lh_Tail = 0;
	Mailbox.lh_Type = AMNT_MAILBOX;

	/* init Selected-list */
	Selected.lh_Head = (struct Node *)&Selected.lh_Tail;
	Selected.lh_TailPred = (struct Node *)&Selected.lh_Head;
	Selected.lh_Tail = 0;
	Selected.lh_Type = AMNT_SELECT_LIST;

	/* lock contents */
	if (!(ContentsLocked = LockContents(Folder)))
		Panic(62,"Can't lock contents");

	/* read in the mailbox */
	if (!GetContents(&Mailbox,Folder))
		Panic(63,"Can't get contents");

	/* title of listview-gadget */
	sprintf(Mailboxtitle,"User: %s (%s) --- Folder: %s",
		Username,Realname,Folder);

	/* request notification */
	if (!NotifyOn(NotifyPort,Folder))
		Panic(64,"notification request denied!");

	/* allocate asl requesters */
	if (!(FReq = (struct FileRequester *)
		AllocAslRequestTags(ASL_FileRequest,
			ASL_FuncFlags,FILF_NEWIDCMP,
			ASL_ExtFlags1,0,
			TAG_END,0)))
	{
		DeselectAll(&Selected);
		Panic(44,"Can't get Filerequester!");
	}

	if (!(FontReq = (struct FontRequester *)
		AllocAslRequestTags(ASL_FontRequest,
			ASL_FuncFlags,FONF_FIXEDWIDTH|FONF_NEWIDCMP,
			ASL_MinHeight,4,
			ASL_MaxHeight,16,
			TAG_END,0)))
	{
		DeselectAll(&Selected);
		Panic(56,"Can't get FontRequester!");
	}

restart: /* reentry when window must be opened again */

	/* uncheck all checkit-items */
	for (nm=NewMenu;nm->nm_Type!=NM_END;++nm)
		if (nm->nm_Flags & CHECKIT)
			nm->nm_Flags &= ~CHECKED;

	/* check menuitem for screendata */
	if (AMDisplayID)
	{
		for (nm=NewMenu;nm->nm_Type!=NM_END;++nm)
			if (nm->nm_UserData == (APTR)AMDisplayID)
			{
				nm->nm_Flags |= CHECKED;
				break;
			}
	}
	else
		for (nm=NewMenu;nm->nm_Type!=NM_END;++nm)
			if (nm->nm_UserData == (APTR)SCR_PUBSCR)
			{
				nm->nm_Flags |= CHECKED;
				break;
			}

	/* check menuitem for CTE default */
	for (nm=NewMenu;nm->nm_Type!=NM_END;++nm)
		if (((ULONG)nm->nm_UserData) - CONF_BASE64 == AMCTE)
			nm->nm_Flags |= CHECKED;

	/* look for other AM's public screen */
	if (PubScreen = LockPubScreen((UBYTE *)PUBSCREENNAME))
		strncpy(AMPubScreen,PUBSCREENNAME,CONFIG_LENGTH);
	else
	{
		/* open screen */
		if (*AMPubScreen)
		{
			if (!(PubScreen = LockPubScreen((UBYTE *)AMPubScreen)))
			{
				SimpleRequest(Window,"Can't Lock Public Screen");
				if (!(PubScreen = LockPubScreen(0)))
					Panic(48,"can't lock default public screen!");
			}
		}
		else if (AMDisplayID)
		{
			if (!(Screen = OpenScreenTags(0,
				SA_Depth,2L,
				SA_DisplayID,AMDisplayID,
				SA_Overscan,OSCAN_TEXT,
				SA_Width,STDSCREENWIDTH,
				SA_Height,STDSCREENHEIGHT,
				SA_Pens,&pens,
				SA_PubName,PUBSCREENNAME,
				TAG_END)))
				SimpleRequest(Window,"Can't open Customscreen");
			PubScreenStatus(Screen,0); /* make screen public */
		}
		else
		{
			if (!(PubScreen = LockPubScreen(0)))
				Panic(48,"can't lock default public screen!");
		}
	}

	if (Screen)
	{
		/* if we have our own screen, then set colors */
		LoadRGB4(&(Screen->ViewPort),AMColors+1,(long)AMColors[0]);

		/* enable color changing */
		for (nm=NewMenu;nm->nm_Type!=NM_END;++nm)
			if (nm->nm_UserData == (APTR)CONF_COLORS)
			{
				nm->nm_Flags &= ~NM_ITEMDISABLED;
				break;
			}

		if ((vpmid = GetVPModeID(&Screen->ViewPort )) != INVALID_ID) 
		{
			GetDisplayInfoData(0, (UBYTE *)&di, sizeof(struct DimensionInfo), DTAG_DIMS, vpmid);
			rect = &di.TxtOScan;
			if (!WTop) WTop = Screen->BarHeight+2L;
			if (!WWidth || WWidth>rect->MaxX) WWidth = rect->MaxX;
			if (!WHeight || WHeight>rect->MaxY-(Screen->BarHeight+2L)) 
				WHeight = rect->MaxY-(Screen->BarHeight+2L);
		}
		else 
			Panic(57,"Can't Get VPModeID!");
	}
	else
	{

		/* disable color changing */
		for (nm=NewMenu;nm->nm_Type!=NM_END;++nm)
			if (nm->nm_UserData == (APTR)CONF_COLORS)
			{
				nm->nm_Flags |= NM_ITEMDISABLED;
				break;
			}

		if ((vpmid = GetVPModeID(&PubScreen->ViewPort )) != INVALID_ID) 
		{
			GetDisplayInfoData(0, (UBYTE *)&di, sizeof(struct DimensionInfo), DTAG_DIMS, vpmid);
			rect = &di.TxtOScan;
			if (!WTop) WTop = PubScreen->BarHeight+2L;
			if (!WWidth || WWidth>rect->MaxX) WWidth = rect->MaxX;
			if (!WHeight || WHeight>rect->MaxY-(PubScreen->BarHeight+2L)) 
				WHeight = rect->MaxY-(PubScreen->BarHeight+2L);
		}
		else 
			Panic(58,"Can't Get VPModeID!");
	}

	/* open window */
	if (Screen) /* custom screen requested */
	{
		if (!(Window = OpenWindowTags(0,
			/*WA_DetailPen,0x00,
			WA_BlockPen,0x01,*/
			WA_CustomScreen,Screen,
			WA_Left,0L,
			WA_Top,WTop,
			WA_Width,WWidth,
			WA_Height,WHeight,
			WA_MinWidth,640L,
			WA_MinHeight,180L,
			WA_MaxWidth,1024L,
			WA_MaxHeight,1024L,
			WA_DragBar,TRUE,
			WA_DepthGadget,TRUE,
			WA_CloseGadget,TRUE,
			WA_SizeGadget,TRUE,
			WA_Activate,TRUE,
			WA_SmartRefresh,TRUE,
			WA_GimmeZeroZero,TRUE,
			TAG_END)))
			Panic(24,"Can't open Window!");

		/* get the screens's textattr */
		TextAttr = *(Screen->Font);
	}
	else if (PubScreen) /* public screen requested */
	{
		if (!(Window = OpenWindowTags(0,
			WA_PubScreen,(UBYTE *)PubScreen,
			WA_Left,0L,
			WA_Top,WTop,
			WA_Width,WWidth,
			WA_Height,WHeight,
			WA_MinWidth,640L,
			WA_MinHeight,180L,
			WA_MaxWidth,1024L,
			WA_MaxHeight,1024L,
			WA_DragBar,TRUE,
			WA_DepthGadget,TRUE,
			WA_CloseGadget,TRUE,
			WA_SizeGadget,TRUE,
			WA_Activate,TRUE,
			WA_SmartRefresh,TRUE,
			WA_GimmeZeroZero,TRUE,
			TAG_END)))
			Panic(24,"Can't open Window!");
		

		/* get the screens's textattr */
		TextAttr = *(PubScreen->Font);
	}

	Busy();

	/* open font */
	if (*AMFont.ta_Name)
	{
		if (TextFont = OpenDiskFont(&AMFont))
			TextAttr = AMFont;
		else
			if (TextFont = OpenFont(&AMFont))
				TextAttr = AMFont;
			else 
				SimpleRequest(Window,"Can't open font, using screen's default font!");
	}
	else
		if (!(TextFont = OpenDiskFont(&TextAttr)))
			if (!(TextFont = OpenFont(&TextAttr)))
				SimpleRequest(Window,"Can't open screen's default font!");

	if (TextFont->tf_Flags & FPF_PROPORTIONAL)
		SimpleRequest(Window,"Warning: Font is proportional");

	/* set window-/screeentitle */
	sprintf(Windowtitle,
		"AM %s - AmigaMail © 1991, 1992 by Christian Riede %s",
		AMIGAMAIL_VERSION,(PubScreen)?("(V)"):(""));

redraw: /* entry when window must be redrawed (for example after resize ) */

	LastSelected = -1;

	/* adjust gadgets to window dimensions */
	ListGadget.ng_TopEdge = 5+ListGadget.ng_TextAttr->ta_YSize;
	ListGadget.ng_LeftEdge = 5;
	ListGadget.ng_Width = Window->GZZWidth-10;
	SelectGadget.ng_TopEdge = 
		ShowGadget.ng_TopEdge = 
		SortGadget.ng_TopEdge = 
		Window->GZZHeight-6*(TextAttr.ta_YSize+1)-2;
	ListGadget.ng_Height = SelectGadget.ng_TopEdge-5-5-ListGadget.ng_TextAttr->ta_YSize;
	SelectGadget.ng_LeftEdge = 5;
	ShowGadget.ng_LeftEdge = Window->GZZWidth/3;
	SortGadget.ng_LeftEdge = (Window->GZZWidth*2)/3;

	/* Get Visual info */
	if(!(ListGadget.ng_VisualInfo = GetVisualInfo(Window->WScreen,TAG_END)))
		Panic(25,"Can't get Visual Info!");
	SelectGadget.ng_VisualInfo = ListGadget.ng_VisualInfo;
	ShowGadget.ng_VisualInfo = ListGadget.ng_VisualInfo;
	SortGadget.ng_VisualInfo = ListGadget.ng_VisualInfo;
	
	/* create menues */
	if (!(Menu = CreateMenus(NewMenu,TAG_END)))
		Panic(42,"Can't create menu!");

	if (!LayoutMenus(Menu,ListGadget.ng_VisualInfo,TAG_END))
		Panic(43,"Can't layout menu!");

	SetMenuStrip(Window,Menu);

	/* initial show/select */
	(*Show)(&Mailbox);
	(*Select)(&Mailbox,&Selected,Sort,0);

	/* create context */
	if (!(gad = CreateContext(&GList)))
	{
		DeselectAll(&Selected);
		Panic(26,"Can't create Gadget!");
	}

	/* create select-gadget */
	if(!(SelGad = gad = CreateGadget(MX_KIND,gad,&SelectGadget,
		GTMX_Labels,SelectLabels,
		GTMX_Active,ActSelect,
		GTMX_Spacing,1L,
		TAG_END)))
	{
		DeselectAll(&Selected);
		Panic(28,"Can't create Gadget!");
	}

	/* create show-gadget */
	if(!(gad = CreateGadget(MX_KIND,gad,&ShowGadget,
		GTMX_Labels,ShowLabels,
		GTMX_Active,ActShow,
		GTMX_Spacing,1L,
		TAG_END)))
	{
		DeselectAll(&Selected);
		Panic(29,"Can't create Gadget!");
	}

	/* create sort-gadget */
	if(!(gad = CreateGadget(MX_KIND,gad,&SortGadget,
		GTMX_Labels,SortLabels,
		GTMX_Active,ActSort,
		GTMX_Spacing,1L,
		TAG_END)))
	{
		DeselectAll(&Selected);
		Panic(30,"Can't create Gadget!");
	}

	/* create listview gadget */
	if (!(LVGadget = gad = CreateGadget(LISTVIEW_KIND,gad,&ListGadget,
		GTLV_Labels,&Selected,
		GTLV_ShowSelected,0L,
		TAG_END)))
	{
		DeselectAll(&Selected);
		Panic(27,"Can't create Gadget!");
	}

	/* show up gadgets */
	AddGList(Window,GList,-1,-1,NULL);
	RefreshGList(GList,Window,NULL,-1);
	GT_RefreshWindow(Window,0);
	ScreenToFront(Window->WScreen);
	ActivateWindow(Window);

	/* turn on IDCMP */
	Ready();

	/* main loop */
	run = TRUE;
	ExitFlag = TRUE;
	while (run)
	{
		/* wait for messages */
		Signals = Wait(1L<<Window->UserPort->mp_SigBit | 1L<<NotifyPort->mp_SigBit);

		/* handle notification events */
		if (Signals & 1L<<NotifyPort->mp_SigBit) while (Msg = (struct AMMessage *)GetMsg(NotifyPort))
		{
			switch(Msg->Action)
			{
				case NOTIFY_NEWITEM:
					if (!GetNum(&Mailbox,Msg->Number))
					{
						System((UBYTE *)"sys:rexxc/rx \"address play \'id\' \'am_newmail\'\"",
							AMSystemTags);
						DeselectAll(&Selected);
						AddTail(&Mailbox,&(Msg->NewMail->m_Node));
						RefreshDisplay(Select,Show,Sort,&Mailbox,
							&Selected,LastSelected,(void *)SearchPattern);
					}
					break;					

				case NOTIFY_ITEM_DELETED:
					DeselectAll(&Selected);
					if (New = GetNum(&Mailbox,Msg->Number))
					{
						Remove(&(New->m_Node));
						FreeMail(New);
					}
					RefreshDisplay(Select,Show,Sort,&Mailbox,
						&Selected,LastSelected,(void *)SearchPattern);
					break;					
				
				case NOTIFY_ITEM_CHANGED:
					RefreshDisplay(0,Show,0,&Mailbox,
						&Selected,LastSelected,(void *)SearchPattern);
					break;					
			}
			FreeMem(Msg,sizeof(struct AMMessage));
		}
		
		/* handle Intuition events */
		if (Signals & 1L<<Window->UserPort->mp_SigBit) while (IMsg = GT_GetIMsg(Window->UserPort))
		{
			/* remember values */
			Class = IMsg->Class;
			Code  = IMsg->Code;	
			IAddr = IMsg->IAddress;
			Secs = IMsg->Seconds;
			Micros = IMsg->Micros;

			/* replay message */
			GT_ReplyIMsg(IMsg);

			/* dispatch */
			switch(Class)
			{
				case REFRESHWINDOW:
					GT_BeginRefresh(Window);
					GT_EndRefresh(Window,TRUE);
					break;

				case CLOSEWINDOW:
					if (running)
						SimpleRequest(Window,"There are running subprocesses");
					else
						if (TwoGadRequest(Window,"Really Quit?"))
							run = FALSE;
					break;

				case MENUPICK:
					if (Code==MENUNULL) break;
					if (!(MenuItem = ItemAddress(Menu,Code))) break;
					switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
					{
						case PROJ_QUIT:
							if (running)
								SimpleRequest(Window,"There are running subprocesses");
							else
								if (TwoGadRequest(Window,"Really Quit?"))
									run = FALSE;
							break;

						case PROJ_EXIT:
							if (running)
								SimpleRequest(Window,"There are running subprocesses");
							else
								if (TwoGadRequest(Window,"Really Exit?"))
									run = ExitFlag = FALSE;
							break;

						case PROJ_ABOUT:
							Busy();
							SimpleRequest(Window,"AM %s (AmigaMail)\n© 1991, 1992 by Christian Riede\nUse and distribute under the terms of\nthe GNU General Public License Version 1",
								AMIGAMAIL_VERSION);
							Ready();
							break;

						case PROJ_FOLDER:
							Busy();
							if (AslRequestTags(FReq,
								ASL_Window,Window,
								ASL_FuncFlags,FILF_NEWIDCMP,
								ASL_ExtFlags1,FIL1F_NOFILES,
								ASL_File,"",
								ASL_Dir,Folder,
								ASL_Hail,"Select Folder Name",
								TAG_END,0)) 
							{
								if (!LockContents((char *)FReq->rf_Dir))
									SimpleRequest(Window,"Can't open folder!");
								else
								{
									/* throw away the old folder */
									NotifyOff(NotifyPort,Folder);
									DeselectAll(&Selected);
									FreeMailbox(&Mailbox);
									UnLockContents(Folder);
									/* new folder */
									strcpy(Folder,(char *)FReq->rf_Dir);
									/* read in the mailbox */
									if (!GetContents(&Mailbox,Folder))
										Panic(63,"Can't get contents");
									if (!NotifyOn(NotifyPort,Folder))
										Panic(64,"notification request denied!");
									/* title of listview-gadget */
									sprintf(Mailboxtitle,"User: %s (%s) --- Folder: %s",
										Username,Realname,Folder);
									Panic(-1,0);
									goto restart;
								}
							}
							Ready();
							break;

						case PROJ_CREATEFOLDER:
							Busy();
							if (AslRequestTags(FReq,
								ASL_Window,Window,
								ASL_FuncFlags,FILF_NEWIDCMP,
								ASL_File,"",
								ASL_Dir,Folder,
								ASL_ExtFlags1,0,
								ASL_Hail,"Select Folder Name to Create",
								TAG_END,0)) 
							{
								/* filename is name of new folder */

								strncpy(Buf,(char *)FReq->rf_Dir,MAIL_FIELDLENGTH);
								AddPart((UBYTE *)Buf,(UBYTE *)FReq->rf_File,MAIL_FIELDLENGTH);

								if (MyLock = Lock((UBYTE *)Buf,ACCESS_READ))
								{
									UnLock(MyLock);
									SimpleRequest(Window,"File or Directory exists!");
								}
								else
									/* create directory */
									if (!(MyLock = CreateDir((UBYTE *)Buf)))
										SimpleRequest(Window,"Can't create folder!");
									else
										UnLock(MyLock);
								
							}
							Ready();
							break;

						case AC_READ:
							ActionRead(LastSelected,&Selected);
							break;

						case AC_SAVE:
							ActionSave(LastSelected,&Selected);
							break;

						case AC_SEND:
							Busy();
							sprintf(SendParms,"%ld %lx %s",
								SFLAGS_SEND,
								0,
								Folder);
							CreateNewProcTags(
								NP_Entry,SendMail,
								NP_StackSize,32768,
								NP_Arguments,SendParms,
								NP_Name,"AM_SendMail",
								TAG_END,0);
							Ready();
							break;

						case AC_REPLY:
							Busy();
							ActionReply(LastSelected,&Selected,SFLAGS_QUOTE);
							Ready();
							break;

						case AC_REPLY_GROUP:
							Busy();
							ActionReply(LastSelected,&Selected,SFLAGS_QUOTE|SFLAGS_GROUP);
							Ready();
							break;

						case AC_FORWARD:
							Busy();
							ActionForward(LastSelected,&Selected,0);
							Ready();
							break;

						case AC_MARK_READ:
							if (LastSelected>=0)
							{
								if (Mail = GetMail(LastSelected,&Selected))
								{
									Mail->read |= MAIL_READ;
									if (!MarkRead(Mail->Number,Folder))
										SimpleRequest(Window,"Can't mark mail as read");
									/* refresh will be done on notification */								}
							}
							else
								SimpleRequest(Window,"No item selected");
							break;

						case AC_MARK_UNREAD:
							if (LastSelected>=0)
							{
								if (Mail = GetMail(LastSelected,&Selected))
								{
									Mail->read &= ~MAIL_READ;
									if (!MarkUnread(Mail->Number,Folder))
										SimpleRequest(Window,"Can't mark mail as unread");
									/* refresh will be done on notification */								}
							}
							else
								SimpleRequest(Window,"No item selected");
							break;

						case AC_PRINT:
							Busy();
							ActionPrint(LastSelected,&Selected);
							Ready();
							break;

						case AC_SEARCH_TEXT:
							Busy();
							if (SearchHeader = RequestSearchString(SearchPattern))
							{
								Select = (SearchHeader-1)?
									(SelectSearchText):(SelectSearchTextH);
								RefreshDisplay(Select,0,Sort,&Mailbox,
									&Selected,-1,(void *)SearchPattern);
								GT_SetGadgetAttrs(SelGad,Window,0,
									GTMX_Active,5L,
									TAG_END,0);
							}
							else
								SearchPattern[0]=0;

							Ready();
							break;
							
						case AC_DELETE:
							Busy();
							ActionDelete(LastSelected,&Selected);
							Ready();
							break;

						case AC_MOVE:
							Busy();
							ActionMove(LastSelected,&Selected);
							Ready();
							break;

						case ADDR_EDIT:
							Busy();
							EditAddressBook();
							Ready();
							break;

						case ADDR_PRINT:
							Busy();
							SimpleRequest(Window,"not yet implemented");
							Ready();
							break;

						case ADDR_ADDCURR:
							Busy();
							ActionAddAddress(LastSelected,&Selected);
							Ready();
							break;

						case CONF_FONT:
							Busy();

							if (AslRequestTags(FontReq,
								ASL_Window,Window,
								ASL_Hail,(ULONG)"AM Font",
								ASL_MaxHeight,30,
/*								ASL_ModeList,(ULONG)&ModeList,
*/								ASL_FontName,AMFont.ta_Name,
								ASL_FontHeight,AMFont.ta_YSize,
								ASL_FontFlags,AMFont.ta_Flags,
								ASL_FontStyles,AMFont.ta_Style,
								ASL_Hail,"Select Font",
								TAG_END,0)) 
							{
								DeselectAll(&Selected);
								Panic(-1,0);
								strncpy((char *)AMFont.ta_Name,
									(char *)FontReq->fo_Attr.ta_Name,
									CONFIG_LENGTH);
								AMFont.ta_YSize = FontReq->fo_Attr.ta_YSize;
								AMFont.ta_Style = FontReq->fo_Attr.ta_Style;
								AMFont.ta_Flags = FontReq->fo_Attr.ta_Flags;
								if (TextFont = OpenDiskFont(&AMFont))
									TextAttr = AMFont;
								else
									if (TextFont = OpenFont(&AMFont))
										TextAttr = AMFont;
									else 
									{
										SimpleRequest(Window,"Can't open font, using screen's default font!");
										TextAttr = *(Screen->Font);
										if (!(TextFont = OpenDiskFont(&TextAttr)))
											if (!(TextFont = OpenFont(&TextAttr)))
												SimpleRequest(Window,"Can't open screen's default font!");
									}
								goto restart;
							}

							Ready();
							break;

						case CONF_COLORS:
							Busy();
							if (AMDisplayID)
							{
								if (Screen)
									colorreq(PUBSCREENNAME,"Change Colors",(unsigned short)0x00);
								else if (*AMPubScreen)
									colorreq(AMPubScreen,"Change Colors",(unsigned short)0x00);
								else 
									colorreq(0,"Change Colors",(unsigned short)0x00);
							}
							Ready();
							break;

						case CONF_SCREEN:
							/* not handled here */
							break;

						case CONF_MEDITOR:
							Busy();
							if (AslRequestTags(FReq,
								ASL_ExtFlags1,0,
								ASL_Window,Window,
								ASL_File,FilePart((UBYTE *)MailEditor),
								ASL_Dir,strncpy(Buf,MailEditor,
									(char *)PathPart((UBYTE *)MailEditor)-MailEditor),
								ASL_Hail,"Select Mail Editor",
								TAG_END,0)) 
							{
								strncpy(MailEditor,(char *)FReq->rf_Dir,CONFIG_LENGTH);
								AddPart((UBYTE *)MailEditor,(UBYTE *)FReq->rf_File,CONFIG_LENGTH);
							}
							Ready();
							break;

						case CONF_RFILTER:
							Busy();
							if (AslRequestTags(FReq,
								ASL_ExtFlags1,0,
								ASL_Window,Window,
								ASL_File,FilePart((UBYTE *)RFilter),
								ASL_Dir,strncpy(Buf,RFilter,
									(char *)PathPart((UBYTE *)RFilter)-RFilter),
								ASL_Hail,"Select Text Viewer",
								TAG_END,0)) 
							{
								strcpy(RFilter,(char *)FReq->rf_Dir);
								AddPart((UBYTE *)RFilter,(UBYTE *)FReq->rf_File,CONFIG_LENGTH);
							}
							Ready();
							break;

						case CONF_SIGNATURE:
							Busy();
							if (AslRequestTags(FReq,
								ASL_ExtFlags1,0,
								ASL_Window,Window,
								ASL_File,FilePart((UBYTE *)Signature),
								ASL_Dir,strncpy(Buf,Signature,
									(char *)PathPart((UBYTE *)Signature)-Signature),
								ASL_Hail,"Select Signature File",
								TAG_END,0)) 
							{
								strcpy(Signature,(char *)FReq->rf_Dir);
								AddPart((UBYTE *)Signature,(UBYTE *)FReq->rf_File,CONFIG_LENGTH);
							}
							Ready();
							break;

						case CONF_SAVE:
							Busy();
							if (Screen)
							{
								AMColors[0]=4;
								AMColors[1]=GetRGB4(Screen->ViewPort.ColorMap,0L);
								AMColors[2]=GetRGB4(Screen->ViewPort.ColorMap,1L);
								AMColors[3]=GetRGB4(Screen->ViewPort.ColorMap,2L);
								AMColors[4]=GetRGB4(Screen->ViewPort.ColorMap,3L);
							}
							if (AslRequestTags(FReq,
								ASL_ExtFlags1,0,
								ASL_Window,Window,
								ASL_File,FilePart((UBYTE *)Config),
								ASL_Dir,strncpy(Buf,Config,
									(char *)PathPart((UBYTE *)Config)-Config),
								ASL_Hail,"Save Config To...",
								TAG_END,0)) 
							{
								strcpy(Config,(char *)FReq->rf_Dir);
								AddPart((UBYTE *)Config,(UBYTE *)FReq->rf_File,CONFIG_LENGTH);
								WriteConfig(Config);
							}
							Ready();
							break;

						case CONF_LOAD:
							Busy();
							if (AslRequestTags(FReq,
								ASL_ExtFlags1,0,
								ASL_Window,Window,
								ASL_File,FilePart((UBYTE *)Config),
								ASL_Dir,strncpy(Buf,Config,
									(char *)PathPart((UBYTE *)Config)-Config),
								ASL_Hail,"Load Config From...",
								TAG_END,0)) 
							{
								Panic(-1,0);
								strcpy(Config,(char *)FReq->rf_Dir);
								AddPart((UBYTE *)Config,(UBYTE *)FReq->rf_File,CONFIG_LENGTH);
								ReadConfig(Config);
								goto restart;
							}
							Ready();
							break;

						case CONF_REPLY_TO:
							Busy();
							RequestString("Reply-To Address",ReplyTo,MAIL_FIELDLENGTH);
							Ready();
							break;

						case SCR_PUBSCR:
							Busy();	
							if (RequestString(
								"Public Screen Name (none for default Public Screen):",
								AMPubScreen,CONFIG_LENGTH))
							{
								AMDisplayID = 0;
								DeselectAll(&Selected);
								Panic(-1,0);
								goto restart;
							}
							Ready();
							break;

						case PAL_MONITOR_ID|HIRES_KEY:
						case PAL_MONITOR_ID|HIRESLACE_KEY:
						case NTSC_MONITOR_ID|HIRES_KEY:
						case NTSC_MONITOR_ID|HIRESLACE_KEY:
						case VGAPRODUCT_KEY:
						case VGAPRODUCTLACE_KEY:
							*AMPubScreen=0;
							AMDisplayID = (ULONG)GTMENUITEM_USERDATA(MenuItem);
							DeselectAll(&Selected);
							Panic(-1,0);
							goto restart;
							break;

						case CONF_BASE64:
						case CONF_QUOTED_PRINTABLE:
						case CONF_7BIT:
						case CONF_8BIT:
						case CONF_BINARY:
							AMCTE = (ULONG)GTMENUITEM_USERDATA(MenuItem) - CONF_BASE64;
							break;

						default:
							break;
					}
					break;

				case GADGETUP:
					switch(((struct Gadget *)IAddr)->GadgetID)
					{
						case LIST: /* user selected item */
							if (DoubleClick(LastSecs,LastMicros,Secs,Micros) &&
								(Secs!=LastSecs || Micros-LastMicros>300)) 
									/* against chattering mousebuttons */
							{
								ActionRead(Code,&Selected);
								/* refresh will be done on notification */
							}
							LastSelected = Code;
							LastSecs = Secs;
							LastMicros = Micros;
							break;
						default:
							puts("unknown gadget released");
					}
					break;

				case GADGETDOWN:
					switch(((struct Gadget *)IAddr)->GadgetID)
					{
						case SELECT:
							switch(Code)
							{
								case 0: Select = SelectNew; break; 
								case 1: Select = SelectAll; break; 
								case 2: Select = SelectLastWeek; break; 
								case 3: Select = SelectFromMe; break; 
								case 4: Select = SelectToMe; break; 
								case 5: 
									if (SearchHeader = RequestSearchString(SearchPattern))
									{
										Select = (SearchHeader-1)?
											(SelectSearchText):(SelectSearchTextH);
									}
									else
									{
										Select = SelectSearchTextH;
										SearchPattern[0]=0;
									}
								break;
								default: 
									puts("unknown item in select-gadget");
							}
							ActSelect = Code;
							RefreshDisplay(Select,0,Sort,&Mailbox,
								&Selected,LastSelected,(void *)SearchPattern);
							break;

						case SHOW:
							switch (Code)
							{
								case 0: Show = ShowAll; break;
								case 1: Show = ShowFrom; break;
								case 2: Show = ShowTo; break;
								case 3: Show = ShowSubject; break;
								case 4: Show = ShowDate; break;
								case 5: Show = ShowMsgId; break;
								default: puts("unknown item in show-gadget");
							}
							ActShow = Code;
							RefreshDisplay(0,Show,0,&Mailbox,
								&Selected,LastSelected,(void *)SearchPattern);
							break;

						case SORT:
							switch (Code)
							{
								case 0: Sort = InsertByNumber; break;
								case 1: Sort = InsertByFrom; break;
								case 2: Sort = InsertByTo; break;
								case 3: Sort = InsertBySubject; break;
								case 4: Sort = InsertByDate; break;
								case 5: Sort = InsertByInReplyTo; break;
								default: puts("unknown item in sort-gadget");
							}
							ActSort = Code;
							RefreshDisplay(Select,0,Sort,&Mailbox,
								&Selected,-1,(void *)SearchPattern);
							break;
						default:
							puts("unknown gadget pressed");
					}
					break;

				case MOUSEBUTTONS:
					break;

				case INTUITICKS:
					break;

				case SIZEVERIFY:
					break;

				case NEWSIZE:
					DeselectAll(&Selected);
					WLeft = Window->LeftEdge;
					WTop = Window->TopEdge;
					WWidth = Window->Width;
					WHeight = Window->Height;
					/* remove,free gadgets */
					RemoveGList(Window,GList,-1); 
					FreeGadgets(GList); 
					GList = 0;
					/* remove menus */
					ClearMenuStrip(Window); 
					FreeMenus(Menu); 
					Menu=0;
					/* clear Window */
					SetRast(Window->RPort,0L);
					goto redraw;
					break;

				case VANILLAKEY:
					switch(Code)
					{
						case ' ': /* space */
						case 13: /* return */
							if (LastSelected==-1) LastSelected = 0;
							ActionRead(LastSelected,&Selected);
							if (Code == ' ') 
							{
								LastSelected++;
								RefreshDisplay(0,0,0,&Mailbox,
									&Selected,LastSelected,(void *)SearchPattern);
							}
							break;

						case 'r':
							Busy();
							ActionReply(LastSelected,&Selected,SFLAGS_QUOTE);
							Ready();
							break;

						case 'R':
							Busy();
							ActionReply(LastSelected,&Selected,SFLAGS_GROUP|SFLAGS_QUOTE);
							Ready();
							break;

						case 'f':
							Busy();
							ActionForward(LastSelected,&Selected,0);
							Ready();
							break;

						case 'F':
							Busy();
							ActionForward(LastSelected,&Selected,0);
							Ready();
							break;

						case 'd':
						/*case 'D':*/
							Busy();
							ActionDelete(LastSelected,&Selected);
							Ready();
							break;

						case 's':
						/*case 'S':*/
							Busy();
							sprintf(SendParms,"%ld %lx %s",
								SFLAGS_SEND,
								0,
								Folder);
							CreateNewProcTags(
								NP_Entry,SendMail,
								NP_StackSize,32768,
								NP_Arguments,SendParms,
								NP_Name,"AM_SendMail",
								TAG_END,0);
							Ready();
							break;

						case 'p':
						/*case 'P':*/
							Busy();
							ActionPrint(LastSelected,&Selected);
							Ready();
							break;


							
					}
					break;

				case RAWKEY:
					switch(Code)
					{
						case 76: /* cursor up */
							if (LastSelected>0)
							{
								LastSelected--;
								RefreshDisplay(0,0,0,&Mailbox,
									&Selected,LastSelected,(void *)SearchPattern);
							}
							break;

						case 77: /* cursor down */
							LastSelected++;
							RefreshDisplay(0,0,0,&Mailbox,
								&Selected,LastSelected,(void *)SearchPattern);
							break;
					}
					break;

				
				default:
					printf("Unknkown IntuiMessage->Class:%x\n",Class);
					break;
			}
		}

		/* if run == FALSE, check if there are visitor windows on our public screen */
		if (!run)
			if (Screen)
				if (!(PubScreenStatus(Screen,PSNF_PRIVATE)&1))
				{
					run = TRUE;
					SimpleRequest(Window,"Cant close public screen:\n close all visitor windows first");
				}
	}

	Busy();

	DeselectAll(&Selected);

	if (ExitFlag) /* mark mail as old */
		for (Mail=(struct Mail *)Mailbox.lh_Head;
			Mail->m_Node.ln_Succ;
			Mail=(struct Mail *)Mail->m_Node.ln_Succ)
			if (Mail->read & MAIL_NEW)
				MarkOld(Mail->Number,Folder);

	FreeMailbox(&Mailbox);

	/* everything OK */
	Panic(0,"");
}
