/* File.c - Dateifunktionen */

#include "Constants.h"

#include <exec/memory.h>
#include <dos/dos.h>
#include <libraries/asl.h>
#include "Structures/AppAsl.h"
#include "Structures/Nodes.h"

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/asl_protos.h>
#include <string.h>
#include "AsmLib/QuickFuncs.h"

extern struct Library *AslBase;

unsigned long ExamineFileLength(char * name)
{
	/* Ermittelt die Länge der Datei 'name' in Bytes */

	long			filelock;
	struct FileInfoBlock   *fib;
	unsigned long 		length = 0;

	if (filelock = Lock(name, ACCESS_READ)) {
		if (fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)) {
			if (Examine(filelock, fib) == DOSTRUE)
				length = fib->fib_Size;

			FreeDosObject(DOS_FIB, (APTR)fib);
		}
		UnLock(filelock);
	}
	return (length);
}

unsigned long ExamineDiskSpace(char * name)
{
	/* Ermittelt den Platz des Gerätes, auf dem sich 'name' befindet, in Bytes */

	long			filelock;
	struct InfoData	       *infodata;
	long			space = 0;

	if (filelock = Lock(name, ACCESS_READ)) {
		if (infodata = GetVecA(sizeof(struct InfoData), MEMF_PUBLIC | MEMF_CLEAR)) {
			if (Info(filelock, infodata) == DOSTRUE)
				space = (long)((double)infodata->id_NumBlocks - infodata->id_NumBlocksUsed) * (double)infodata->id_BytesPerBlock;

			FreeVec(infodata);
		}
		UnLock(filelock);
	}
	return(space);
}

char *OpenFile(char * name)
{
	/* Öffnet eine Datei und kopiert den Inhalt in einen (char-)Buffer */

	long			filehandle;
	struct FileInfoBlock   *fib;
	void		       *buffer = NULL;

	if (filehandle = Open(name, MODE_OLDFILE)) {
		if (fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)) {
			if (ExamineFH(filehandle, fib) == DOSTRUE) {
				if (fib->fib_Size) {
					if (buffer = (char *)GetVecA(fib->fib_Size, MEMF_PUBLIC | MEMF_CLEAR)) {
						if (Read(filehandle, buffer, fib->fib_Size) != fib->fib_Size) {
							FreeVec(buffer);
							buffer = NULL;
						}
					}
				}
			}
			FreeDosObject(DOS_FIB, (APTR)fib);
		}
		Close(filehandle);
	}
	return ((char *)buffer);
}

short SaveFile(char *name, char *buffer, long len)
{
	/* Speichert die Daten in 'buffer' in die Datei 'name' */

	long			filehandle;
	short			success = FALSE;

	if (filehandle = Open(name, MODE_NEWFILE)) {
		if (Write(filehandle, (void *)buffer, len) == len)
			success = TRUE;
		Close(filehandle);
	}
	return (success);
}

struct List *GetDirContents(char *name)
{
	/* Ermittelt den Inhalt eines Verzeichnisses und legt ihn in einer
	   DirNode-Liste ab. */

	long			filelock;
	struct FileInfoBlock   *fib;
	struct List	       *dirlist = NULL;

	if (filelock = Lock(name, SHARED_LOCK)) {
		if (fib = (struct FileInfoBlock *)AllocDosObject(DOS_FIB, NULL)) {
			if (Examine(filelock, fib) != DOSFALSE) {
				if (fib->fib_DirEntryType >= 0 && fib->fib_DirEntryType != ST_SOFTLINK)	{
					if (dirlist = GetVecA(sizeof(struct List), MEMF_PUBLIC | MEMF_CLEAR)) {
						struct DirNode		       *tempnode;
						NewList(dirlist);

						while (ExNext(filelock, fib) != DOSFALSE) {
							if (tempnode = GetVecA(sizeof(struct DirNode), MEMF_PUBLIC | MEMF_CLEAR)) {
								strncpy(tempnode->dn_Name, fib->fib_FileName, FILENAMELENGTH);
								AddTail(dirlist, (struct Node *)tempnode);
							}
						}
					}
				}
			}
			FreeDosObject(DOS_FIB, (void *)fib);
		}
		UnLock(filelock);
	}
	return (dirlist);
}

short GetFileName(struct AppAsl *asl, struct Screen *screen)
{
	/* Die Funktion schreibt den Pfad in eine spezielle ASL-Verwaltungsstruktur und merkt
	   sich dort auch alle anderen Requesterdaten (z.B. Position, Größe, etc.  */

	short success = FALSE;

	if (AslBase)	/* damit die ASL-Lib nicht zwingend erforderlich ist */
	{
		struct FileRequester	       *filereq;
		struct TagItem			filetags[] = {
							ASLFR_TitleText,	(unsigned long)asl->titletext,
							ASLFR_InitialLeftEdge,	asl->leftedge,
							ASLFR_InitialTopEdge,	asl->topedge,
							ASLFR_InitialWidth,	asl->width,
							ASLFR_InitialHeight,	asl->height,
							ASLFR_RejectIcons,	asl->noicons,
							ASLFR_InitialFile,	(unsigned long)asl->filename,
							ASLFR_InitialDrawer,	(unsigned long)asl->dirname,
							ASLFR_Screen, 		(unsigned long)screen,
							TAG_DONE
						};

		if (filereq = (struct FileRequester *)AllocAslRequest(ASL_FileRequest, filetags)) {
			if (AslRequest(filereq, NULL)) {
				/* Kopieren der Werte */
				asl->leftedge	= filereq->fr_LeftEdge;
				asl->topedge	= filereq->fr_TopEdge;
				asl->width	= filereq->fr_Width;
				asl->height	= filereq->fr_Height;
				strncpy(asl->filename, filereq->fr_File, FILENAMELENGTH);
				strncpy(asl->dirname, filereq->fr_Drawer, DISKPATHLENGTH - FILENAMELENGTH);

				/* Erstellen des gesamten Pfades */
				strncpy(asl->pathname, filereq->fr_Drawer, DISKPATHLENGTH - FILENAMELENGTH);
				if (AddPart(asl->pathname, filereq->fr_File, DISKPATHLENGTH))
					success = TRUE;
			}
			FreeAslRequest(filereq);
		}
	}
	return (success);
}