/* Sabot */

#include <exec/types.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/notify.h>
#include <dos/dostags.h>
#include <libraries/dos.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>

#include <proto/icon.h>
#include <proto/exec.h>
#include <proto/wb.h>
#include <proto/dos.h>

#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <wb2cli.h>

#define BIGSTRING 255
#define SMALLSTRING 128

enum args
	{
	MAIL,
	NOMAIL,
	OLDMAIL,
	MAILBOX,
	ICONNAME,
	XPOS,
	YPOS,
	CLICKCOMMAND,
	CLICKSTACK,
	MAILCOMMAND,
	MAILSTACK,
	DROPCOMMAND,
	DROPSTACK,
	BEEPLOTS,
	COUNTDELETE,
	MAILRDY
	};


void __regargs __chkabort(void) {}
int __oslibversion=37;
long __stack = 20000;
static const char VersionID[]="\0$VER:Sabot 1.7 (27.2.94) By Scott Ellis";

extern struct DosLibrary *DOSBase;
extern struct WBStartup *_WBenchMsg;
struct Library *IconBase;
struct Library *WorkbenchBase;

char *havemail;
char *nomail;
char *oldmail;
char *watch;
char *iconname;
char *clickcomname;
char *mailcomname;
char *dropcomname;
char *dropname;
char *droptemp;

BOOL mailrdy;
ULONG xpos;
ULONG ypos;

BOOL beeplots=FALSE;
ULONG clickcomstack=20000;
ULONG mailcomstack=20000;
ULONG dropcomstack=20000;

LONG mbsize=0;
LONG prevsize=0;

struct AppIcon *appicon=NULL;
struct DiskObject *image=NULL;
struct MsgPort *myport=NULL;

enum active_args
	{
	NONE,
	OLD,
	NEW
	};

USHORT active=NONE;
BOOL beeped=FALSE;
BOOL countdelete=FALSE;

BOOL addicon(struct MsgPort *, struct DiskObject *);
void killicon( void );
BOOL getimage( char * );
void killimage( void );
void changeicon( void );
void doinfo( void );
void compare( void );
BOOL parse( int, char ** );
void docommand(char *, int);
BOOL makevars( void );
void freevars( void );

int main (int argc, char **argv)
{
	struct AppMessage *appmsg;
	struct NotifyRequest *note;

	struct MsgPort *mailport=NULL;
	ULONG mailportsig=NULL;

	BOOL going=TRUE;
	ULONG mysig;
	LONG signum;
	LONG count;
	ULONG myportsig;

	if ( !makevars() )
	{
		freevars();
		return(20);
	}

	WB2CLI( _WBenchMsg , __stack , DOSBase); /* Creates Path for System()'ed commands */

	if ( !parse( argc, argv) )
	{
		freevars();
		return(5);
	}

	if (mailrdy)
	{
		if ( mailport=CreatePort("T:MailRdy",0) )
		{
			mailportsig = 1L << mailport->mp_SigBit;
		}
	}

	if ( (IconBase=OpenLibrary("icon.library",37)) && (WorkbenchBase=OpenLibrary("workbench.library",37)) )
	{
		if ( getimage(nomail) )
		{
			if ( myport=CreatePort(NULL,0) )
			{
				myportsig = 1L << myport->mp_SigBit;

				if ( addicon(myport,image) )
				{
					if ( note=AllocVec(sizeof(struct NotifyRequest),MEMF_CLEAR) )
					{
						if ( (signum=AllocSignal(-1L)) != -1)
						{
							note->nr_Name=watch;
							note->nr_Flags=NRF_SEND_SIGNAL;
							note->nr_stuff.nr_Signal.nr_Task= (struct Task *)FindTask(NULL);
							note->nr_stuff.nr_Signal.nr_SignalNum=signum;

							if ( (StartNotify(note))==DOSTRUE )
							{
								doinfo();
								if ( mbsize )		/* Show appropriate icon on startup */
								{
									active=OLD;
            						changeicon();
								}

								while ( going )
								{
									mysig = Wait( myportsig | SIGBREAKF_CTRL_C | (1L << signum) | mailportsig );

									if ( mysig & SIGBREAKF_CTRL_C )
									{
										going=FALSE;
									}

									if (mysig & mailportsig)
									{
										active=OLD;
										changeicon();
									}

									if (mysig & (1L << signum))
									{
										doinfo();
										compare();
									}

									if ( mysig & myportsig)
									{
										if ( mailrdy && (active!=NONE) )
										{
											active=NONE;
											changeicon();
										}

										while( appmsg=(struct AppMessage *)GetMsg(myport) )
										{
											if ( appmsg->am_NumArgs==0L )
											{
												if ( clickcomname )
												{
													docommand(clickcomname,clickcomstack);
												}
												prevsize=mbsize;
											}
											else if ( appmsg->am_NumArgs > 0L )
											{
												if ( dropcomname )
												{
                                            		count = appmsg->am_NumArgs;

													while ( count )
													{
														--count;

														if (NameFromLock(appmsg->am_ArgList[count].wa_Lock,dropname,BIGSTRING))
														{
															if(AddPart(dropname,appmsg->am_ArgList[count].wa_Name,BIGSTRING))
															{
																sprintf(droptemp,"%s %s",dropcomname,dropname);
                                            					docommand(droptemp,dropcomstack);
															}
														}

														strcpy(droptemp,"");
														strcpy(dropname,"");
													}
												}
											}
											ReplyMsg( (struct Message *)appmsg );
										}
									}
								}
							}
							FreeSignal(signum);
						}
						EndNotify(note);
						FreeVec(note);
					}
				}
				killicon();
			}

			while(appmsg=(struct AppMessage *)GetMsg(myport))
			{
				ReplyMsg((struct Message *)appmsg);
			}

			DeletePort(myport);
		}
		killimage();
	}

	if (mailport)
	{
		DeletePort(mailport);
	}

	CloseLibrary(WorkbenchBase);
	CloseLibrary(IconBase);

	freevars();

	return(0);
}

BOOL addicon(struct MsgPort *port, struct DiskObject *image)
{
	if ( appicon=AddAppIconA(0L,0L,iconname,port,NULL,image,NULL) )
	{
		return(TRUE);
	}

	return(FALSE);
}

void killicon( void )
{
	RemoveAppIcon(appicon);
}

BOOL getimage( char *name )
{
	if ( image=GetDiskObject(name) )
	{
		image->do_Type=NULL;
		image->do_CurrentX=xpos;
		image->do_CurrentY=ypos;
		return(TRUE);
	}

	return(FALSE);
}

void killimage( void )
{
	if (image)
	{
		FreeDiskObject(image);
	}
}

void changeicon( void )
{
	killicon();
	killimage();

	switch (active)
	{
		case OLD:
			getimage(oldmail);
			break;

		case NEW:
			getimage(havemail);
			break;

		case NONE:
			getimage(nomail);
			break;
	}

	addicon(myport,image);
}

void doinfo( void )
{
	BPTR lock;
	struct FileInfoBlock *fib;

	if ( lock=Lock(watch,ACCESS_READ) )
	{
		if ( fib=(struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_END) )
		{
			Examine(lock,fib);

			mbsize=fib->fib_Size;

			FreeDosObject(DOS_FIB,fib);
		}
	}
	else
	{
		if ( countdelete ) mbsize=0;
	}

	UnLock(lock);
}

void compare( void )
{
/*printf("mbsize=%i prevsize=%i active=%i\n",mbsize,prevsize,active);*/

	if (mbsize)
	{
		if ( mbsize > (prevsize+130) ) /* Allow 130 bytes of breathing room */
		{
			if (active!=NEW)
			{
				active=NEW;
				changeicon();
			}

			if ( mailcomname && ( !beeped || beeplots) )
			{
				docommand(mailcomname,mailcomstack);
				beeped=TRUE;
			}
		}
		else
		{
			active=OLD;
			changeicon();
			beeped=FALSE;
		}
	}
	else
	{
		active=NONE;
		changeicon();
		beeped=FALSE;
	}

	prevsize=mbsize;
}

BOOL parse(int argc, char *argv[])
{
	struct RDArgs	*RDA;
	LONG 		ArgumentArray[17] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
	char		**ToolArrayIndex,
				*ToolStringIndex,
				*Template;
	struct DiskObject	*DiskObject;

	if (IconBase = OpenLibrary("icon.library", 36L ) )
        {

		RDA = AllocDosObjectTags(DOS_RDARGS, TAG_DONE);
		RDA->RDA_ExtHelp = NULL;

		if ( argc == 0 )
		{
			CurrentDir(_WBenchMsg->sm_ArgList->wa_Lock);

			if ( DiskObject = GetDiskObject(_WBenchMsg->sm_ArgList->wa_Name) )
			{
				for (ToolArrayIndex = DiskObject->do_ToolTypes; *ToolArrayIndex; ToolArrayIndex++ )
				{
					RDA->RDA_Source.CS_Length += (strlen(*ToolArrayIndex)+1);
				}
				RDA->RDA_Source.CS_Buffer = AllocVec(RDA->RDA_Source.CS_Length+1,MEMF_CLEAR);
				ToolStringIndex = RDA->RDA_Source.CS_Buffer;
				for (ToolArrayIndex = DiskObject->do_ToolTypes; *ToolArrayIndex; ToolArrayIndex++ )
				{
						ToolStringIndex = stpcpy(stpcpy(ToolStringIndex, *ToolArrayIndex)," ");
				}
				*(ToolStringIndex-1) = '\n';
				FreeDiskObject(DiskObject);
			}

			Template = "Mail/A,NoMail/A,OldMail/A,MB=MailBox/A,IN=IconName/K,XPos/K/N,YPos/K/N,CC=ClickCommand/K,CS=ClickStack/K/N,MC=MailCommand/K,MS=MailStack/K/N,DC=DropCommand/K,DS=DropStack/K/N,BeepLots/S,CountDelete/S,MailRdy/S,ThrowAway/M";
		}
		else
		{
			Template = "Mail/A,NoMail/A,OldMail/A,MB=MailBox/A,IN=IconName/K,XPos/K/N,YPos/K/N,CC=ClickCommand/K,CS=ClickStack/K/N,MC=MailCommand/K,MS=MailStack/K/N,DC=DropCommand/K,DS=DropStack/K/N,BeepLots/S,CountDelete/S,MailRdy/S";
		}

		if (RDA = ReadArgs(Template, ArgumentArray, RDA) )
		{
			strcpy(havemail,(char *)ArgumentArray[MAIL]);
			strcpy(nomail,(char *)ArgumentArray[NOMAIL]);
			strcpy(oldmail,(char *)ArgumentArray[OLDMAIL]);
			strcpy(watch,(char *)ArgumentArray[MAILBOX]);

			if ( ArgumentArray[ICONNAME] )
			{
				strcpy(iconname,(char *)ArgumentArray[ICONNAME]);
			}
			else
			{
				strcpy(iconname,"MailBox");
			}

			if ( ArgumentArray[XPOS] )
			{
				xpos=*(int *)ArgumentArray[XPOS];
			}
			else
			{
				xpos=NO_ICON_POSITION;
			}

			if ( ArgumentArray[YPOS] )
			{
				ypos=*(int *)ArgumentArray[YPOS];
			}
			else
			{
				ypos=NO_ICON_POSITION;
			}

			if ( ArgumentArray[CLICKCOMMAND] )
			{
				strcpy(clickcomname,(char *)ArgumentArray[CLICKCOMMAND]);
			}

			if ( ArgumentArray[CLICKSTACK] )
			{
				clickcomstack=*(int *)ArgumentArray[CLICKSTACK];
			}

			if ( ArgumentArray[MAILCOMMAND] )
			{
				strcpy(mailcomname,(char *)ArgumentArray[MAILCOMMAND]);
			}

			if ( ArgumentArray[MAILSTACK] )
			{
				mailcomstack=*(int *)ArgumentArray[MAILSTACK];
			}

			if ( ArgumentArray[DROPCOMMAND] )
			{
				strcpy(dropcomname,(char *)ArgumentArray[DROPCOMMAND]);
			}

			if ( ArgumentArray[DROPSTACK] )
			{
				dropcomstack=*(int *)ArgumentArray[DROPSTACK];
			}

			if ( ArgumentArray[BEEPLOTS] )
			{
				beeplots=TRUE;
			}

			if ( ArgumentArray[COUNTDELETE] )
			{
				countdelete=TRUE;
			}

			if ( ArgumentArray[MAILRDY] )
			{
				mailrdy=TRUE;
			}
			else
			{
				mailrdy=FALSE;
			}

		}
		else
		{
			PrintFault(IoErr(), NULL);
			return(FALSE);
		}

		FreeArgs(RDA);
		FreeDosObject(DOS_RDARGS,RDA);
        	CloseLibrary(IconBase);
	}
	else
	{
		return(FALSE);
	}
	return(TRUE);
}

void docommand(char *command, int stack)
{
    BPTR ofh,ifh;

	if ( ofh=Open("NIL:",MODE_READWRITE) )
	{
		if ( ifh=Open("NIL:",MODE_READWRITE) )
		{
			if ( SystemTags(	command,
						SYS_Input, ifh,
						SYS_Output, ofh,
						SYS_UserShell, DOSTRUE,
						SYS_Asynch, DOSTRUE,
						NP_StackSize, stack,
						NP_CopyVars, DOSTRUE,
						NP_Cli, DOSTRUE,
						TAG_END) != -1 )
			{
				return;
			}

			Close(ifh);
		}
		Close(ofh);
	}
}

BOOL makevars(void)
{
	if ( havemail=AllocVec(11*BIGSTRING,MEMF_CLEAR) )
	{
		nomail=havemail+BIGSTRING;
		oldmail=nomail+BIGSTRING;
		watch=oldmail+BIGSTRING;
		iconname=watch+BIGSTRING;
		clickcomname=iconname+BIGSTRING;
		mailcomname=clickcomname+BIGSTRING;
		dropcomname=mailcomname+BIGSTRING;
		dropname=dropcomname+BIGSTRING;
		droptemp=dropname+(2*BIGSTRING);
		return(TRUE);
	}
	return(FALSE);
}

void freevars(void)
{
	if (havemail) FreeVec(havemail);
}

