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

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

                              Programmert av 
                    Ørjan Eriksen og Torstein Pettersen

                          hentlagre.c   leksjon 3 
  
**************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <string.h>
#include <stdio.h>

#include "base.h"

#ifndef FOREVER			/* denne er definert i intuition.h som ikke brukes her */
#define FOREVER for( ; ; )
#endif

/* externe variabler og funksjoner */

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

/* funksjoner tilgjengelig for andre moduler */

void lagre_liste(struct Liste *);
void hent_liste(struct Liste **,struct Liste **);

/* variabler kun for denne modulen */

static char filename[80] = {0,};
static long fd;

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

/* denne funksjonen lagrer alle poster i listen */

void lagre_liste(hode)
register struct Liste *hode;
{
	register struct Liste *cr;
	
/* først leser vi inn et filnavn */

	printf("\nLagre liste\n");
	printf("\nFilnavn : ");
	gets(filename);	

/* hvis vi ikke skriver et filnavn returnerer vi til hovedmeny */

	if (strlen(filename) == 0)
		return;

/* her prøver vi å åpne filen */

	if ((fd = Open(filename,MODE_NEWFILE)) == NULL) {
		goto openerror;
	}
/*
  her skriver vi en firebokstavs kode først i filen slik at vi senere
  når filen skal leses inn kan sjekke om det er riktig filtype
*/
	if (Write(fd,"DBHD",4) != 4) /* de fire første tegn i filen er DBHD */
		goto writeerror;

	cr = hode; /* set cr til å peke på første post i listen */

	while (cr) { /* hvis vi kommer til slutten av listen stopper vi */

/*
  når vi lagrer en post er det ikke nødvendig å lagre de to siste
  pekerene i struct Liste fordi disse pekerene vil forabdre seg neste gang 
  vi bruker programmet. Hver peker på Amigaen er 4 bytes lang derfor
  trekker vi fra 8 bytes. Hvis vi programmerer mot en annen CPU en 68000
  må vi ikke gå ut fra at en peker er 4 bytes, da kan vi bruke sizeof()
  for å finne lengden sizeof(struct Liste *) = ant. bytes for 1 peker
*/

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

		cr = cr->neste; /* gå til neste post */
	}

	printf("Lagring ferdig!\n");

writeerror:
	Close(fd); /* lukk filen */

openerror:
	return;
}

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

/* skriv filnavn */

	printf("\nHent liste\n");
	printf("\nFilnavn : ");
	gets(filename);	

	if (strlen(filename) == 0)
		return;

/* prøv å åpne filen */

	if ((fd = Open(filename,MODE_OLDFILE)) == NULL) {
		printf("Filen kunne ikke åpnes!\n");
		goto openerror;
	}

/* les inn de første fire bokstaver av filen */

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

/* hvis filen ikke startet med DBHD er det ikke en databasefil */

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

/* sett av minne til første post på disken */
	cr = (struct Liste *)AllocMem(LLENGDE,MEMF_CLEAR);

	if (cr) {
		FOREVER	{
/*
  Fortsett å lese inn hver post fra disk vi kommer til slutten av filen
  Lesing vil bli avbrutt når vi prøver å lese forbi slutten av filen.
  Vi leser data direkte inn i Liste strukturen. Nesten alle poster i
  strukturen blir oppdatert direkte, bare pekerene i slutten må oppdateres av
  sett_inn_post() funksjonen. 
*/
			if ((Read(fd,(char *)cr,LLENGDE-8) == LLENGDE-8)  && (cr != NULL)) {
				sett_inn_post(hode,sist,cr); /* sett inn posten i listen */
				cr = (struct Liste *)AllocMem(LLENGDE,MEMF_CLEAR); /* sett av minne til ny post */
			}
			else { /* vi er kommet til en lesefeil eller til slutten */
				FreeMem(cr,LLENGDE); /* frigjør minne til posten som ble til overs */
				break;
			}
		}
	}

	printf("Innlesning Ferdig!\n");

readerror:
/* lukk filen */
	Close(fd);

openerror:
	return;
}
