/* NoDelete V2.01 (C) HooverSoft 1992

	cc NoDelete +L
	ln NoDelete -la -lc32


*/


#ifdef AZTEC_C					/* Works under Manx, convert it to Lattice */
									/* if you don't mind the hassle...			 */

#include<libraries/arpbase.h>
#include<intuition/intuition.h>
#include<intuition/intuitionbase.h>
#include<libraries/dos.h>
#include<libraries/dosextens.h>
#include<stdio.h>

/*#define DEBUG 1*/

void *AllocMem();
char bodystring[80], *patterns[50], titlebak[80], title[80];
ULONG answer, PAT_SET = 0L,  howmany = 0L, rvalue=0L;
ULONG OVERRIDE = 0L, SILENT = 0L, deletefile;
ULONG IS2_0=0; /* 1.2 & 1.3 still more common than 2.0 */
ULONG ACTIVE;
char *what=(char *)"NoDelete V2.01 © HooverSoft 1992";
struct NewWindow mywindow = {
	100,0,	/* window XY origin relative to TopLeft of screen */
	350,10,	/* window width and height */
	0,1,	/* detail and block pens */
	CLOSEWINDOW+VANILLAKEY,	/* IDCMP flags */
	WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+SIMPLE_REFRESH,	/* other window flags */
	NULL,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	(UBYTE *)title,	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	5,5,	/* minimum width and height */
	640,110, /* maximum width and height */
	WBENCHSCREEN	/* destination screen type */
	};



char *patgadsibuff;
char *undobuff;

struct StringInfo patgadsinfo = {
	(UBYTE *) NULL,	/* buffer where text will be edited */
	(UBYTE *) NULL,	/* optional undo buffer */
	0,	/* character position in buffer */
	255,	/* maximum number of characters to allow */
	0,	/* first displayed character buffer position */
	0,0,0,0,0,	/* Intuition initialized and maintained variables */
	0,	/* Rastport of gadget */
	0,	/* initial value for integer gadgets */
	NULL	/* alternate keymap (fill in if you set the flag) */
};

SHORT BorderVectors1[] = {
	0,0,
	179,0,
	179,9,
	0,9,
	0,0
};
struct Border Border1 = {
	-1,-1,	/* XY origin relative to container TopLeft */
	3,0,JAM1,	/* front pen, back pen and drawmode */
	5,	/* number of XY vectors */
	BorderVectors1,	/* pointer to XY vectors */
	NULL	/* next border in list */
};

struct Gadget patgad = {
	NULL,	/* next gadget */
	4,11,	/* origin XY of hit box relative to window TopLeft */
	178,8,	/* hit box width and height */
	NULL,	/* gadget flags */
	RELVERIFY,	/* activation flags */
	STRGADGET,	/* gadget type flags */
	(APTR)&Border1,	/* gadget border or image to be rendered */
	NULL,	/* alternate imagery for selection */
	NULL,	/* first IntuiText structure */
	NULL,	/* gadget mutual-exclude long word */
	(APTR)&patgadsinfo,	/* SpecialInfo structure */
	42L,	/* user-definable data */
	NULL	/* pointer to user-definable data */
};

#define GadgetList1 patgad

struct NewWindow patwindow = {
	214,2,	/* window XY origin relative to TopLeft of screen */
	187,22,	/* window width and height */
	0,1,	/* detail and block pens */
	CLOSEWINDOW|GADGETUP,	/* IDCMP flags */
	WINDOWDRAG+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH,	/* other window flags */
	&patgad,	/* first gadget in gadget list */
	NULL,	/* custom CHECKMARK imagery */
	(UBYTE *)"Edit Patterns",	/* window title */
	NULL,	/* custom screen pointer */
	NULL,	/* custom bitmap */
	5,5,	/* minimum width and height */
	-1,-1,	/* maximum width and height */
	WBENCHSCREEN	/* destination screen type */
};

struct IntuiText body = {
	1,0,
	JAM1|COMPLEMENT,
	30,16,
	NULL,
	NULL,
	NULL
	};

struct IntuiText fbody = {
	1,0,
	JAM1|COMPLEMENT,
	30,5,
	NULL,
	(UBYTE *) "System tries to fool around...",
	&body
	};

struct IntuiText ok = {
	1,0,
	JAM1|COMPLEMENT,
	6,3,
	NULL,
	(UBYTE *)	"Yes, Delete!",
	NULL
	};

struct IntuiText no = {
	1,0,
	JAM1|COMPLEMENT,
	6,3,
	NULL,
	(UBYTE *)  "Oops, No Way!",
	NULL
	};


struct IntuiMessage *msg, *GetMsg();
struct MsgPort *FindPort(), *CreatePort(), *nd_msgport;
struct IntuitionBase *IntuitionBase;
struct Window			*pw, *mw, *aw, *OpenWindow();
struct Library			*DosBase;
struct ArpBase			*ArpBase;
UBYTE						*filename;
void 						*OpenLibrary();
struct Task				*FindTask();

#ifdef DEBUG
void print_info()
{
long i;
for(i=0; i<howmany; i++)
	Printf("Pattern %ld: %s\n", i, patterns[i]);
return;
}
#endif
/* Now here comes the heart of NoDelete. Please excuse the crummy
	structure of the code, but this is another example of a program
	thas has "grown" naturally. I only understand half of this myself!
*/

void NoDelete()
{

	char parsed[131]; /* place to keep the preparsed string */

#asm
	public	_LVOSetProtection
	public   _LVOSetFunction

	movem.l	d0-d7/a0-a6,-(sp)
#endasm
	geta4(); /* THIS is very important due to Aztec's a4-relative addressing */
#asm
	move.l	d1,_filename
#endasm
	;

	;
	ACTIVE=1;
	if(PAT_SET)
		{

		for(answer=0L; answer < howmany; answer++)
			{
			PreParse(patterns[answer], parsed);   /* This is ARP */
			if( !PatternMatch(parsed, filename) ) /* this is new */
				continue;
			else
				goto request;
			}
		}
	else
		goto request;

	goto delete_anyway;

request:
	strcpy(bodystring, "Delete File `");
	strcat(bodystring, (char *)BaseName(filename) );
	strcat(bodystring, "'?");

	body.IText = (UBYTE *) bodystring;
	aw = (struct Window *) IntuitionBase->ActiveWindow;
	answer = (long)AutoRequest(aw, &fbody, &ok, &no, NULL, NULL, 360L, 61L);
	if(!answer)
	{
		;
	ACTIVE=0;
#asm
	movem.l	(sp)+,d0-d7/a0-a6
	move.l	#1,d0 ;This is where we fool the calling program into believing
                  ;that everything is removed.
#endasm
	;
	return;
	}

	if(answer)
	{

delete_anyway:
		;

#asm
		tst.l   _IS2_0
		bne.s  _is20
		move.l	_DosBase,a6
		move.l	#$70f7,d0			;restore old vector
		move.w	d0,-72(a6)
		move.l	#$60000092,d0
		move.l	d0,-70(a6)
		bra.s    _not20

_is20:
		move.l 4,a6
		move.l _DosBase,a1
		move.l #-72,a0
		move.l _deletefile,d0
		jsr    _LVOSetFunction(a6)
      move.l _DosBase,a6

_not20:
		tst.l		_OVERRIDE   /* see if global OVERRIDE equals zero */
		beq.s		_dont_unprotect

		move.l	_filename,d1


		move.l	#0,d2
		jsr		_LVOSetProtection(a6)

_dont_unprotect:

		move.l	_filename,d1
		jsr		-72(a6)				;DeleteFile() call
		move.l   d0,_rvalue        ;save the return value
#endasm

		;

		SetFunction(DosBase, -72L, &NoDelete);
      ACTIVE=0;
/* install our function */


#asm
		movem.l	(sp)+,d0-d7/a0-a6
		move.l	_rvalue,d0
#endasm
		;
		return;
		}
	}


void quit(why)
UBYTE *why;
{
long i;

	if(!SILENT)
		Printf(why);
	SetTaskPri((struct Task *)FindTask(0L), 0L);
	if(DosBase)
	{
		;
		if(!IS2_0)
			{
			;

#asm
		move.l	_DosBase,a6
		move.l	#$70f7,d0			;restore old vector
		move.w	d0,-72(a6)
		move.l	#$60000092,d0
		move.l	d0,-70(a6)
#endasm
			;
			}

		else  /* setfunction should perform as advertised with 2.0 */
			SetFunction(DosBase, -72L, deletefile);

	}

	if (nd_msgport)
		DeletePort(nd_msgport);

	if	(mw)
		CloseWindowSafely(mw);

	if(ArpBase)
		CloseLibrary(ArpBase);

	for(i=0; i<howmany; i++)
		FreeMem(patterns[i], strlen(patterns[i])+1L);
	exit(0L);
}

void edit_patterns()
{
	static struct IntuiMessage *pwmsg=0L;
	long pwclass, pwcode, i;
	char *tmp;

	patgadsibuff = (char *) AllocMem(512L, MEMF_CLEAR);
		if(!patgadsibuff)
			quit("Could not allocate buffer for stringadget (512 bytes)!");
		else
			patgadsinfo.Buffer = (UBYTE *)patgadsibuff;

   undobuff = (char *) AllocMem(512L, MEMF_CLEAR);

		if(!undobuff)
			patgadsinfo.UndoBuffer = NULL;
      else
			patgadsinfo.UndoBuffer = (UBYTE *) undobuff;


	if(howmany)
		{
		*patgadsibuff=0;
		for(i=0; i<howmany; i++)
			{
			strcat(patgadsibuff, patterns[i]);
			strcat(patgadsibuff, " ");
			}
		patgadsibuff[strlen(patgadsibuff)-1] = 0; /* take care of extra blank*/

		}
	pw = (struct Window *) OpenWindow(&patwindow);
	ActivateGadget(&patgad, pw, NULL);
	for(;;)
		{
		Wait(1L << pw -> UserPort -> mp_SigBit);
      while( (pwmsg = GetMsg(pw -> UserPort) ) )
			{
         pwclass = pwmsg -> Class;
         pwcode = pwmsg -> Code;
			ReplyMsg(pwmsg);

			switch(pwclass)
				{
				case CLOSEWINDOW	: 	goto bye;
				break;

				case GADGETUP:
#ifdef DEBUG
				Printf("String entered is %s!\n", patgadsibuff);
#endif
            tmp=patgadsibuff;
				split_string(tmp);

				goto bye;
				break;

				case default:
				break;
				}
			}
		}


bye:
	if(patgadsibuff)
		FreeMem(patgadsibuff, 512L);
	if(undobuff)
		FreeMem(undobuff, 512L);
	if(pw)
		CloseWindowSafely(pw);
return;
}



void main(argc,argv)
long argc;
char *argv[];
	{

	static UBYTE *startmsg = (UBYTE *) \
"NoDelete V2.01 © HooverSoft 1992.\
 This Program is \033[1mFREEWARE\033[0m.\n\
Commercial distribution is strictly \033[4mprohibited.\033[0m\n";
   long class, code;
	long i;

	if(! (ArpBase = (struct ArpBase *) OpenLibrary("arp.library",0L) ) )
		exit(FALSE);

	DosBase = (struct Library *) ArpBase->DosBase;
	if(  (nd_msgport = (struct MsgPort *) FindPort("nd_port")) )
		{
		Printf("NoDelete already installed.\n");
		CloseLibrary(ArpBase);
		exit(0L);
		}
	else
		nd_msgport = CreatePort("nd_port",0L);


	IntuitionBase = (struct IntuitionBase *) ArpBase->IntuiBase;

	if(DosBase->lib_Version >= 36)
		{
#ifdef DEBUG
		Printf("Using Kick 2.0, eh?\n");
#endif
		IS2_0=1;
		}

	strcpy(title, (UBYTE *) what);

	SetTaskPri((struct Task *)FindTask(0L), -5L); /* set def. priority */
	for(i=1; i<argc; i++)
		{
#ifdef DEBUG
			Printf("Scanning argv[%ld]: %s\n", i, (UBYTE *) argv[i] );
#endif
			if( (char) argv[i][0] == '-')
				{
				switch( (char) argv[i][1] )
					{
					case 'y':	if( atoi(argv[i+1]) <= 245L)
										mywindow.TopEdge = atoi(argv[i+1]);
									i++;
									goto go_away;
 									break;

					case 'p':	if(atoi(argv[i+1]) < 10L && atoi(argv[i+1]) > -20L)
										SetTaskPri((struct Task *)FindTask(0L),\
														(long)atoi(argv[i+1]));
									i++;
									goto go_away;
									break;


					case  'O':	OVERRIDE = 1L;
									goto go_away;
									break;

					case  'S':	SILENT = 1L;
									goto go_away;
									break;

					case default:
									Printf("Unknown Option %s\n", argv[i]);
									quit("");
									break;
					}
				/* end switch */
				}/*end if */
			else
				{
				PAT_SET = 1L;
				if( howmany<50 )
					{
					patterns[howmany] = (char *) AllocMem(strlen(argv[i])+1L,\
MEMF_CLEAR);
					if(!patterns[howmany])
						quit("Could not allocate pattern memory!\n");
					strcpy(patterns[howmany], argv[i]);
					}

#ifdef	DEBUG
				Printf("Copied %s, Result: %s\n", argv[i], patterns[i-1L]);
#endif
				howmany++;
				}
go_away:
			;
		/*end for */
			}
#ifdef	DEBUG
		Printf("I found %ld patterns.\n", howmany);
#endif

	if(howmany)
		strcat(title, (UBYTE *) " PAT SET");
	else
		{
		PAT_SET = 0L;
		strcat(title, (UBYTE *) " NO PAT");
		}

/* calculate dimension of	 TitleBar */

	mywindow.Width =  strlen(title) * 8L + 87L;
	mywindow.LeftEdge = (640L-mywindow.Width) / 2L;

	mw = OpenWindow(&mywindow);
	if(!mw)
		quit("Could not open Window.\n\n");
	if(!SILENT)
		Printf(startmsg);

	deletefile=SetFunction(DosBase, -72L, &NoDelete);

	for(;;)
		{
		Wait(1L << mw->UserPort->mp_SigBit);
getmsg:
		while( (msg = GetMsg(mw->UserPort)))
			{
			class=msg->Class;
         code=msg->Code;
			ReplyMsg(msg);
			if ((class == CLOSEWINDOW))
            if(!ACTIVE)
					quit("");
			if(class == VANILLAKEY)
				{
				switch(tolower(code) )
					{
					case ' ':
						if(PAT_SET)
							{
							strcpy(titlebak, (UBYTE *) "Pat: ");
							for(i=0L; i < howmany ; i++)
								{
								strcat(titlebak, patterns[i]);
								strcat(titlebak, " ");
								}
							titlebak[strlen(titlebak)-1L] = '\0';
							SetWindowTitles(mw, titlebak);
							Wait(1L << mw->UserPort->mp_SigBit);
							SetWindowTitles(mw, title);
							ReplyMsg( GetMsg(mw->UserPort) );
							}
						break;

					case 'e': /* change patterns */
						edit_patterns();
#ifdef DEBUG
						print_info();
#endif
							PAT_SET = (howmany) ? 1 : 0;

						if(PAT_SET)
							{
      					strcpy(title, what);
      					strcat(title, " PAT SET");
							}
						else
							{
							strcpy(title, what);
      					strcat(title, " NO PAT");
      					}
						SetWindowTitles(mw, title);
						break;

					case 'c': /* clear patterns */
						for(i=0; i<howmany; i++)
							{
							FreeMem(patterns[i], strlen(patterns[i])+1L);
							patterns[i]=(char *) NULL;
							}
#ifdef DEBUG
						print_info();
#endif
						strcpy(title, what);
     					strcat(title, " NO PAT");
						SetWindowTitles(mw, title);
						howmany=PAT_SET=0L;
						break;

					case 'q': /* shorthand for quit */
							if(!ACTIVE)
								quit("");
						break;

					case default:
						break;
					}
				}

			else
				continue;
			}
		}
	}
#endif

