/*
 *	File.c - Copyright © 1991 by S.R. & P.C.
 *
 *	Created:	13 Apr 1991  15:35:28
 *	Modified:	20 Jul 1991  12:25:54
 *
 *	Make>> make
 */

#include "Global.h"
#include "DosVar.h"
#include "proto/File.h"
#include "proto/String.h"
#include "proto/Request.h"


/*
 *	Examine() the file, assume it is in the current dir. If Request is TRUE
 *  user will be requested for an answer. If not and file can't be locked
 *	or examined, return A_SKIP to tell "couldn't get fib"!
 */

short GetFib(char *Name, struct FileInfoBlock *fib, BOOL Request)
{
	BPTR L;
	short Ok = A_RETRY;

	while (Ok == A_RETRY && !(L = Lock(Name, ACCESS_READ))) {
		if (Request)
			Ok = ThreeGadRequest("Retry", "Skip", "Couldn't access \"%s\"\n%s.", Name, StrIoErr());
		else
			Ok = A_SKIP;
	}
	if (Ok == A_RETRY) {
		while (Ok == A_RETRY && !Examine(L, fib)) {
			if (Request)
				Ok = ThreeGadRequest("Retry", "Skip", "Couldn't get info for \"%s\"\n%s.", Name, StrIoErr());
			else
				Ok = A_SKIP;
		}
		UnLock(L);
	}
	return Ok;
}


/* Convert DateStamp into a number of seconds since 1-Jan-78 */

long Date2Secs(struct DateStamp *ds)
{
	return ds->ds_Days*86400 + ds->ds_Minute*60 + ds->ds_Tick/50;
}


/* Free memory used by FileInfo, not the FileInfo itself */

void CleanFileInfo(struct FileInfo *FileInfo)
{
	FreeStr(FileInfo->fi_Comment);
	FileInfo->fi_Comment = NULL;
}


/* duplicate a FileInfo */

void CopyFileInfo(struct FileInfo *Dest, struct FileInfo *Src)
{
	CleanFileInfo(Dest);
	*Dest = *Src;
	if (Src->fi_Comment)
		Dest->fi_Comment = CopyStr(Src->fi_Comment);
}


/* Convert a FileInfoBlock into a FileInfo */

BOOL Fib2Fi(struct FileInfo *fi, struct FileInfoBlock *fib)
{
	CleanFileInfo(fi);						/* Free comment before alloc of new one */
	fi->fi_Type = (fib->fib_DirEntryType < 0) ? DLX_FILE : DLX_DIR;
	strcpy(fi->fi_Name, fib->fib_FileName);
	fi->fi_Size = fib->fib_Size;
	fi->fi_NumBlocks = fib->fib_NumBlocks;
	fi->fi_DiskKey = fib->fib_DiskKey;
	fi->fi_Date = fib->fib_Date;
	fi->fi_Secs = Date2Secs(&fib->fib_Date);
	fi->fi_Protection = fib->fib_Protection ^ 0x0F;	/* Complement 4 lower bits so all work the same way */
	if (strlen(fib->fib_Comment) > 0) {
		if (!(fi->fi_Comment = CopyStr(fib->fib_Comment)))
			return FALSE;
		fi->fi_Protection |= FIBF_COMMENT;	/* our magic bit! */
	}
	return TRUE;
}


static BOOL Match(struct FileInfo *FileInfo, struct SelectInfo *SelectInfo)
{
	char buf[PATTERN_BUF_SIZE];

	if (FileInfo->fi_Type == DLX_FILE) {
		if (SelectInfo->si_Flags & SI_ALL_FILES)
			return TRUE;
		else if (!(SelectInfo->si_Flags & SI_MATCH_FILES))
			return FALSE;
	}
	else {	/* DLX_DIR */
		if (SelectInfo->si_Flags & SI_ALL_DIRS)
			return TRUE;
		else if (!(SelectInfo->si_Flags & SI_MATCH_DIRS))
			return FALSE;
	}
	if (SelectInfo->si_Flags & SI_NAME) {
		UStrcpy(buf, FileInfo->fi_Name);
		if (!(PatternMatch(SelectInfo->si_PatTok, buf)))
			return FALSE;
	}
	if (FileInfo->fi_Size < SelectInfo->si_MinSize)
		return FALSE;
	if (SelectInfo->si_MaxSize && (FileInfo->fi_Size > SelectInfo->si_MaxSize))
		return FALSE;
	if (SelectInfo->si_Flags & SI_SINCEDATE) {
		if (FileInfo->fi_Secs < SelectInfo->si_SinceSecs)
			return FALSE;
	}
	if (SelectInfo->si_Flags & SI_BEFOREDATE) {
		if (FileInfo->fi_Secs > SelectInfo->si_BeforeSecs)
			return FALSE;
	}
	if (SelectInfo->si_Flags & SI_POSPROTECTION) {
		if (!(FileInfo->fi_Protection & SelectInfo->si_PosProtect))
			return FALSE;
	}
	if (SelectInfo->si_Flags & SI_NEGPROTECTION) {
		if (FileInfo->fi_Protection & SelectInfo->si_NegProtect)
			return FALSE;
	}
	return TRUE;
}


BOOL MatchFilters(struct FileInfo *FileInfo, struct SelectInfo *SelectInfo)
{
	BOOL ret;

	ret = Match(FileInfo, SelectInfo);
	return (SelectInfo->si_Flags & SI_INVERT) ? !ret : ret;
}

