/**************************************************************************

                         Denne filen er en del av
                           EXEC's store C-kurs

                              Programmert av 
                    Ørjan Eriksen og Torstein Pettersen

                          hentlagre.c   leksjon 6 
  
**************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <arp/arpbase.h>
#include <arp/arp_proto.h>
#include <proto/dos.h>
#include <dos.h>

#include "base.h"

/* externe variabler og funksjoner */

extern void sett_inn_post(struct Liste **,struct Liste **,struct Liste *);
extern void show_warn(char *);

extern struct Window *w;
extern struct IconBase *IconBase;

/* funksjoner og variabler kun for denne modulen */
static int finn_fil_navn(char *);

static struct FileRequester *frq;
static char filename[40] = {0,};
static char dirname[200] = {0,};
static char virkeligfilnavn[256] = {0,};
static long fd;
static BPTR dirlock = NULL;

#define MakeID(a,b,c,d) ( (long)(a)<<24 | (long)(b)<<16 | (long)(c)<<8 | (d) )
#define DBHD MakeID('D','B','H','D')

/* funksjoner tilgjengelig for andre moduler */

void lagre_liste(struct Liste *,int);
struct Liste *hent_liste(struct Liste **,struct Liste **);
struct Liste *geticonfile(struct WBStartup *,struct Liste **,struct Liste **);

/* Image data til snorke pointeren */
static USHORT chip WaitSpriteData[] = {
	0x0000,0x0000,0x0000,0x0FE0,0x0740,0x18B0,0x0FE0,0x7018,
	0x3FF0,0xC008,0x7FF0,0x9E0C,0x7FF8,0x8406,0x7FFC,0x8802,
	0xFFFC,0x1E03,0x7FFE,0x80F1,0x7FFE,0x8021,0x3FFF,0x4040,
	0x7FFE,0x80F1,0x3FFE,0xC001,0x1FFC,0x6003,0x0FF8,0x3006,
	0x03F0,0x1C0C,0x00E0,0x0718,0x0780,0x0870,0x0FE0,0x1010,
	0x0740,0x0820,0x0000,0x0FE0,0x01C0,0x0220,0x03E0,0x0410,
	0x00C0,0x0330,0x0000,0x00E0,0x0000,0x0000
};

/**************************************************************************/
/*
  Denne rutinen finner navnet på katalogen vi står i og åpner 
  arp fil requestern med riktig katalog 
*/

static int finn_fil_navn(tittel)
char *tittel;
{
	register int i;

	if(strlen(dirname) == 0 && strlen(filename) == 0) {
		if (dirlock == NULL){
			dirlock = ((struct Process *)FindTask(NULL))->pr_CurrentDir;
				if (getpath(dirlock,dirname) != NULL){
				show_warn("Kunne ikke finne \"current dir\"");
				return;
			}
		}
	}

	if (!(frq = (struct FileRequester *)
			AllocMem(sizeof(struct FileRequester),MEMF_CLEAR))) {
		show_warn("For lite minne for filrequester!");
		return(0);
	}

	frq->fr_Hail = tittel;
	frq->fr_File = filename;
	frq->fr_Dir = dirname;
	
	if (!FileRequest(frq)) {
		FreeMem(frq,sizeof(struct FileRequester));
		show_warn("Fil requester avbrutt!");
		return(0);
	}
	FreeMem(frq,sizeof(struct FileRequester));

	strcpy(virkeligfilnavn,dirname);
	i = strlen(dirname) - 1;

	if (i > 0 && dirname[i] != ':' && dirname[i] != '/')
		strcat(virkeligfilnavn,"/");

	strcat(virkeligfilnavn,filename);
	show_warn(virkeligfilnavn);
	return(1);
}

/**************************************************************************/
/* denne rutinen lagre listen enten direkte eller via fil requesteren */

void lagre_liste(hode,type)
struct Liste *hode;
int type;
{
	register struct Liste *cr;
/*
  det er nå blitt mulig å lagre en fil direkte
  uten å gå via fil requesteren
*/
	if (type == NYTTFILNAVN || strlen(filename) == 0) {
		if(!finn_fil_navn("Lagre Liste"))
			return;
	}

	SetPointer(w,(short *)&WaitSpriteData,25,16,-4,-4);

	if ((fd = Open(virkeligfilnavn,MODE_NEWFILE)) == NULL) {
		goto openerror;
	}

	if (Write(fd,"DBHD",4) != 4)
		goto writeerror;

	cr = hode;

	while (cr) {
		if (Write(fd,(char *)cr,LLENGDE-8) != LLENGDE-8) {
			show_warn("Feil under skriving!");
			goto writeerror;
		}

		cr = cr->neste;
	}

	show_warn("Lagring ferdig!");

writeerror:
	Close(fd);

openerror:
	ClearPointer(w);
	return;
}

/**************************************************************************/
/* denne rutinen sjekker ".info" filen til selve databasen
   her kan vi finne et filnavn på en database fil,
   denne filen åpner vi og leser innholdet direkte inn i listen */

struct Liste *geticonfile(wbs,hode,slutt)
register struct WBStartup *wbs;
struct Liste **hode,**slutt;
{
	register struct Liste *cr;
	register struct DiskObject *dobj;
	register char *fname;
	register char *dname;
	register int i;
	ULONG buff;

/* åpne icon.library */

	if (IconBase = OpenLibrary("icon.library",0)) {
/*
  Nå skal vi lese inn data fra iconet til selve databaseprogrammet.
  WBS er en peker til en WBStartup struktur
  denne strukturen har en peker til en ny struktur som
  inneholder et navn og en lock på iconet som ble trykket ned.
  Hvis flere icon ble trykket ned samtidig (shift klikking), vil
  denne strukturen være den første i en array av strukturer
  som hver inneholder et av de icon som ble trykket ned.
  Hver struktur er 8 bytes lang dermed vil neste struktur ligge 8 bytes
  etter den første osv.
  Navnet på iconet er uten .info.
  GetDiskObject legger automatisk .info til navnet.
*/
		if ((dobj = GetDiskObject(wbs->sm_ArgList->wa_Name)) != NULL) {
/*
  do_ToolTypes er en peker til en array av tekst strenger
  som ligger i ToolTypes feltet i iconet, her kan vi finne filnavn og katalog.
  FindToolType returnerer en peker til teksten som følger etter '=' tegnet
  etter den typen man vil søke etter (FILENAME eller DIRECTORY)
*/
			if ((fname = FindToolType(dobj->do_ToolTypes,"FILENAME")) != NULL )
				strcpy(filename,fname);

			if ((dname = FindToolType(dobj->do_ToolTypes,"DIRECTORY")) != NULL ) {
				strcpy(dirname,dname);
			}
/* frigjør iconet til programmet */

			FreeDiskObject(dobj);
		}

/* lukk icon.library */

		CloseLibrary(IconBase);
	}

	if (fname == NULL) /* ikke fortsett dersom filnavnet ikke er satt */
		return(NULL);

/* sett sammen katalog navn og filnavn til virkeligfilnavn */

	strcpy(virkeligfilnavn,dirname);
	i = strlen(dirname) - 1;

	if (i > 0 && dirname[i] != '/'  && dirname[i] != ':')
		strcat(virkeligfilnavn,"/");

	strcat(virkeligfilnavn,filename);
	show_warn(virkeligfilnavn);

/* resten er likt med hent_liste() */

	SetPointer(w,(short *)WaitSpriteData,25,16,-4,-4);

	if ((fd = Open(virkeligfilnavn,MODE_OLDFILE)) == NULL) {
		show_warn("Automatisk henting, kunne ikke åpne filen!");
		goto openerror;
	}

	if (Read(fd,(char *)&buff,4) != 4) {
		show_warn("Lese feil i Auto hent filen");
		goto readerror;
	}

	if (buff != DBHD) {
		show_warn("Advarsel! Auto hent filen er ikke en Database fil!");
		goto readerror;
	}

	cr = (struct Liste *)AllocMem(LLENGDE,MEMF_CLEAR);

	if (cr) {
		FOREVER	{
			if ((Read(fd,(char *)cr,LLENGDE-8) == LLENGDE-8)  && (cr != NULL)) {
				sett_inn_post(hode,slutt,cr);
				cr = (struct Liste *)AllocMem(LLENGDE,MEMF_CLEAR);
			}
			else {
				FreeMem(cr,LLENGDE);
				break;
			}
		}
	}

	show_warn("Auto Innlesning Ferdig!");

readerror:
	Close(fd);

openerror:
	ClearPointer(w);
	return(*hode);
}

/**************************************************************************/
/* les inn en fil fra disk */

struct Liste *hent_liste(hode,slutt)
struct Liste **hode,**slutt;
{
	register struct Liste *cr;
	ULONG buff;

	if (!finn_fil_navn("Hent liste"))
		return(*hode);

	SetPointer(w,(short *)WaitSpriteData,25,16,-4,-4);

	if ((fd = Open(virkeligfilnavn,MODE_OLDFILE)) == NULL) {
		show_warn("Filen kunne ikke åpnes!");
		goto openerror;
	}

	if (Read(fd,(char *)&buff,4) != 4) {
		show_warn("Feil under lesing av filen");
		goto readerror;
	}

	if (buff != DBHD) {
		show_warn("Feil filtype, dette er ikke en Database fil!");
		goto readerror;
	}

	cr = (struct Liste *)AllocMem(LLENGDE,MEMF_CLEAR);

	if (cr) {
		FOREVER	{
			if ((Read(fd,(char *)cr,LLENGDE-8) == LLENGDE-8)  && (cr != NULL)) {
				sett_inn_post(hode,slutt,cr);
				cr = (struct Liste *)AllocMem(LLENGDE,MEMF_CLEAR);
			}
			else {
				FreeMem(cr,LLENGDE);
				break;
			}
		}
	}

	show_warn("Innlesning Ferdig!");

readerror:
	Close(fd);

openerror:
	ClearPointer(w);
	return(*hode);
}
