/* >c.fileio */
/****************************************************************/
/*                                                              */
/*                   FILE : FILEIO.C                            */
/*                                                              */
/*             Last Updated : 10 - 12 - 87                      */
/*                       By : R. de Vries                       */
/*                                                              */
/*      CONTENTS :                                              */
/*      set_impar(), getFile(), putFile(), fromdisc(),          */
/*      todisc()                                                */
/*                                                              */
/****************************************************************/

/*       Original filename : TRANSFILE.C
*
*        DESCRIPTION
*        Contains functions to store and recall data in/from file.
*
*        HISTORY
*        25-sep-85  Frank van Breukelen (breuk) at TPD Delft created
*            according to calls to the functions getFile and putFile
*            in TRANSFER.C
*
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "allegro.h"
#include "asm.h"
#include "image.h"
#include "imagwind.h"
#include "errors.h"
#include "fileio.h"

#define max(a,b) ((a) > (b) ? (a) : (b))
/* #define O_RDONLY        0 */
#define O_RAW           0
/* #define O_WRONLY        1 */
/* #define O_CREAT         0 */
/* #define O_TRUNC         0 */
#define Arc_Word        32
#define Arc_Byte        8

extern VENSTER *vp[MAXSIG];
extern int SAMPLE_RATE;

/**************************************************************************
 * getFile: Leest een array van char uit een file.                        *
 * Input  : filename.                                                     *
 *        : buffer: hierin komt de gelezen array te staan.                *
 *        : nbytes: aantal te lezen chars.                                *
 *        : offset: Eerst offset chars overslaan.                         *
 * Returns: Aantal gelezen chars.                                         *
 *        : -1 als file niet bestaat.                                     *
 **************************************************************************/

int getFile (char *filename, char *buffer, int nbytes, int offset)

{
	int n;          /* number of bytes actual read */
	FILE *fp;       /* filedescriptor              */


	/* Open the file               */

	if((fp=fopen(filename,"rb"))==NULL)
	{
		fclose(fp);
		return(-1);
	}

	if (offset > 0) fseek(fp,offset,SEEK_CUR);
	n=fread(buffer,sizeof(char),(int)nbytes,fp);
	fclose(fp);

	return (n);
}


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

int putFile (char *filename, char *buffer, int nbytes, int verbose, BOOL data)

{

	FILE *fp;
	char txtbuf[256];


	/* Set protection mode, create and open the file,
*  reset the protection mode
*/


	if (!data)
	{
		fp=fopen(filename,"wb");

		/* Write the buffer and check                                        */
		if (fwrite(buffer,sizeof(char),nbytes, fp) < (int)nbytes)
		{
			sprintf(txtbuf,"Error writing in file %s\n", filename);
			if (verbose) printw("%s",txtbuf);
			fclose(fp);
			return (ERR_WRITEFILE);
		}

		/*  Close the file and return  */
		if (fclose(fp))
		{
			sprintf(txtbuf,"Error closing %s\n", filename);
			if (verbose) printw("%s",txtbuf);
			return (ERR_CLOSEFILE);
		}
		return (NO_ERROR);
	}


	/* Schrijf de data weg */

	if (data)
	{
		fp=fopen(filename,"ab");
		if (fp==NULL)
		{
			fclose(fp);
			return(ERR_OPENFILE);
		}

		/* Write the buffer and check */
		if (fwrite(buffer,sizeof(char),nbytes, fp) < (int)nbytes)
		{
			sprintf(txtbuf,"Error writing in file %s\n", filename);
			if (verbose) printw("%s",txtbuf);
			fclose(fp);
			return (ERR_WRITEFILE);
		}

		/* Close the file and return */
		if (fclose(fp))
		{
			sprintf(txtbuf,"Error closing %s\n", filename);
			if (verbose) printw("%s",txtbuf);
			return (ERR_CLOSEFILE);
		}
		return (NO_ERROR);
	}
	return (NO_ERROR);
}

int check_file(char *filename)
{
	asm_header *hp;
	int error = NO_ERROR;

	hp = (asm_header *)malloc(sizeof(asm_header));

	if (getFile(filename, (char *)hp, (int)sizeof(asm_header),0) == -1)
		return ERR_OPENFILE;

	if(strncmp(hp->asm_id_string,"ASM",3)!=0)
	{
		asm_wprintf("=============== BIG WARNING ====================");
		asm_wprintf("BAD ID-STRING: %s",hp->asm_id_string);
		error  = ERR_FILETYPE;
	}

	if( (hp->domain_id != TIME)  &&
	    (hp->domain_id != AMPL)  &&
	    (hp->domain_id != MAGN)  &&
	    (hp->domain_id != PHAS)  &&
	    (hp->domain_id != FREQ) )
	{
		asm_wprintf("=============== BIG WARNING ====================");
		asm_wprintf("BAD DOMAIN: %d",hp->domain_id);
		error  = ERR_FILETYPE;
	}

	if( (hp->datatype_id != REAL)  &&
	    (hp->datatype_id != IMAG)  &&
	    (hp->datatype_id != COMP) )
	{
		asm_wprintf("=============== BIG WARNING ====================");
		asm_wprintf("BAD DATATYPE: %d",hp->datatype_id);
		error  = ERR_FILETYPE;
	}
	if( (hp->bits_p_samp != BPS_CHAR)   &&
	    (hp->bits_p_samp != BPS_SHORT)  &&
	    (hp->bits_p_samp != BPS_INT)    &&
	    (hp->bits_p_samp != BPS_FLOAT)  &&
	    (hp->bits_p_samp != BPS_DOUBLE) )
	{
		asm_wprintf("=============== BIG WARNING ====================");
		asm_wprintf("BAD bits per sample: %d",hp->bits_p_samp);
		error  = ERR_FILETYPE;
	}


	free(hp);
	return error;

}
/************************************************************************/
/*
*  fromdisc reads an image from floppy disc
*  wp    : image structure to be written to disc
*  filename : name of file to be read from disc
*/

int fromdisc(VENSTER *vp, int file_type)
{

	asm_header *hp;
	char *filename;
	char *real_data_char;
	char *imag_data_char;
	short *real_data_short;
	short *imag_data_short;
	int *real_data_int;
	int *imag_data_int;
	float *real_data_float;
	float *imag_data_float;
	double *real_data_double;
	double *imag_data_double;
	ASM_SAMPLE *real_data;
	ASM_SAMPLE *imag_data;
	unsigned int elements,alloc_size;
	int    nbytes;
	int    teller,offset;
	int    dtype;

	real_data = DataReal(vp); /* Bewaar de pointers */
	imag_data = DataImag(vp);

	filename = Window_File(vp);
	hp = &vp -> header;
	if (getFile(filename, (char *)hp, (int)sizeof(asm_header),0) == -1)
		return ERR_OPENFILE;




	DataReal(vp) = real_data;  /* Zet pointers terug */
	DataImag(vp) = imag_data;



	if (file_type == TCL )
	{
		asm_wprintf("Inputfile is a TCL-file.\n");
		DataDomain(vp) = TIME;
		DataType(vp) = REAL;
		DataRecords(vp)= 1;
		DataSampleRate(vp) = SAMPLE_RATE;
	}

	elements =DataChannels(vp)*DataRecords(vp)*DataLength(vp);
	alloc_size = elements;

	Realloc_Venster(vp,alloc_size);

	real_data = DataReal(vp);
	imag_data = DataImag(vp);





	dtype = DataType(vp);

	switch (DataBits_p_s(vp))
	{
	case 8:                        /* Binnenhalen 8 bits data. (char) */
		nbytes=elements;
		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_char = (char *) malloc((unsigned int)elements*sizeof(char))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if (getFile(filename,(char *)real_data_char,(int)nbytes,(int)sizeof(asm_header)) == -1)
			{
				free(real_data_char);
				return ERR_OPENFILE;
			}

			for (teller=0;teller < elements;teller++)
			{
				real_data[teller]=(ASM_SAMPLE)real_data_char[teller];
				if (dtype == 0) imag_data[teller]=(ASM_SAMPLE)0;
			}
			free(real_data_char);
		}
		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if (dtype == 1) offset=(int)(sizeof(asm_header));
			else offset=(int)(sizeof(asm_header)+nbytes);

			if ((imag_data_char = (char *) malloc((unsigned int)elements*sizeof(char))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if (getFile(filename,(char *)imag_data_char,(int)nbytes,offset) == -1)
			{
				free(imag_data_char);
				return ERR_OPENFILE;
			}

			for (teller=0;teller < elements;teller++)
			{
				if (dtype == 1) real_data[teller]=(ASM_SAMPLE)0;
				imag_data[teller]=(ASM_SAMPLE)imag_data_char[teller];
			}
			free(imag_data_char);
		}
		break;


	case 16:                /* Binnenhalen 16 bits data (short) */
		nbytes=elements*2;
		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_short = (short *) malloc((unsigned int)elements*sizeof(short))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if(getFile(filename,(char *)real_data_short,(int)nbytes,(int)sizeof(asm_header))==-1)
			{
				free(real_data_short);
				return ERR_OPENFILE;
			}

			for (teller=0;teller < elements;teller++)
			{
				real_data[teller]=(ASM_SAMPLE)real_data_short[teller];
				if (dtype == 0) imag_data[teller]=(ASM_SAMPLE)0;
			}
			free(real_data_short);

		}
		if ((dtype == 1) || (dtype == 2))  /* imaginaire deel */
		{
			if (dtype == 1) offset=(int)(sizeof(asm_header));
			else offset=(int)(sizeof(asm_header)+nbytes);

			if ((imag_data_short = (short *) malloc((unsigned int)elements*sizeof(short))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if(getFile(filename,(char *)imag_data_short,(int)nbytes,offset)==-1)
			{
				free(imag_data_short);
				return ERR_OPENFILE;
			}

			for (teller=0;teller < elements;teller++)
			{
				if (dtype == 1) real_data[teller]=(ASM_SAMPLE)0;
				imag_data[teller]=(ASM_SAMPLE)imag_data_short[teller];
			}
			free(imag_data_short);
		}
		break;


	case 32:             /* Binnenhalen 32 bits data (int) */
		nbytes=elements*4;


		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_int = (int *) malloc((unsigned int)elements*sizeof(int))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if (getFile(filename,(char *)real_data_int,(int)nbytes,(int)sizeof(asm_header))==-1)
			{
				free(real_data_int);
				return ERR_OPENFILE;
			};

			for (teller=0;teller < elements;teller++)
			{
				real_data[teller]=(ASM_SAMPLE)real_data_int[teller];
				if (dtype == 0) imag_data[teller]=(ASM_SAMPLE)0;
			}
			free(real_data_int);
		}

		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if (dtype == 1) offset=(int)(sizeof(asm_header));
			else offset=(int)(sizeof(asm_header)+nbytes);

			if ((imag_data_int = (int *) malloc((unsigned int)elements*sizeof(int))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if(getFile(filename,(char *)imag_data_int,(int)nbytes,offset)==-1)
			{
				free(imag_data_int);
				return ERR_OPENFILE;
			};

			for (teller=0;teller < elements;teller++)
			{
				if (dtype == 1) real_data[teller]=(ASM_SAMPLE)0;
				imag_data[teller]=(ASM_SAMPLE)imag_data_int[teller];
			}
			free(imag_data_int);
		}

		break;


	case 3232:           /* 32 bits float */
		nbytes=elements*4;
		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_float = (float *) malloc((unsigned int)elements*sizeof(float))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if(getFile(filename,(char *)real_data_float,(int)nbytes,(int)sizeof(asm_header))==-1)
			{
				free(real_data_float);
				return ERR_OPENFILE;
			}

			for (teller=0;teller < elements;teller++)
			{
				real_data[teller]=(ASM_SAMPLE)real_data_float[teller];
				if (dtype == 0) imag_data[teller]=(ASM_SAMPLE)0;
			}
			free(real_data_float);
		}
		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if (dtype == 1) offset=(int)(sizeof(asm_header));
			else offset=(int)(sizeof(asm_header)+nbytes);

			if ((imag_data_float = (float *) malloc((unsigned int)elements*sizeof(float))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if(getFile(filename,(char *)imag_data_float,(int)nbytes,offset)==-1)
			{
				free(imag_data_float);
				return ERR_OPENFILE;
			};

			for (teller=0;teller < elements;teller++)
			{
				if (dtype == 1) real_data[teller]=(ASM_SAMPLE)0;
				imag_data[teller]=(ASM_SAMPLE)imag_data_float[teller];
			}
			free(imag_data_float);
		}

		break;


	case 6464:           /* 64 bits double */
		nbytes=elements*8;
		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_double = (double *) malloc((unsigned int)elements*sizeof(double))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if(getFile(filename,(char *)real_data_double,(int)nbytes,(int)sizeof(asm_header))==-1)
			{
				free(real_data_double);
				return ERR_OPENFILE;
			};

			for (teller=0;teller < elements;teller++)
			{
				real_data[teller]=(ASM_SAMPLE)real_data_double[teller];
				if (dtype == 0) imag_data[teller]=(ASM_SAMPLE)0;
			}
			free(real_data_double);
		}

		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if (dtype == 1) offset=(int)(sizeof(asm_header));
			else offset=(int)(sizeof(asm_header)+nbytes);
			if ((imag_data_double = (double *) malloc((unsigned int)elements*sizeof(double))) == NULL)
			{
				asm_wprintf("Error in fromdisc: malloc failed");
				return -1;
			}

			if (getFile(filename,(char *)imag_data_double,(int)nbytes,offset)==-1)
			{
				free(imag_data_double);
				return ERR_OPENFILE;
			}

			for (teller=0;teller < elements;teller++)
			{
				if (dtype == 1) real_data[teller]=(ASM_SAMPLE)0;
				imag_data[teller]=(ASM_SAMPLE)imag_data_double[teller];
			}
			free(imag_data_double);
		}


		break;


	default:
		return (ERR_FILETYPE);
		break;
	}

	return (NO_ERROR);
}


/***************************************************************************************/
/*
*  todisc writes an image to disc
*
*  wp       : image structure to be written
*
*  filename : name of file
*
*  returns  TRUE if succesfull
*  returns  FALSE if an error in opening or closing occurred
*  returns  the number of bytes written in this does not equal
*  the image size
*
*********************************************************************************/



int  todisc(VENSTER *vp, int file_type, short bps)
{
	char *filename;
	char *real_data_char;
	char *imag_data_char;
	short *real_data_short;
	short *imag_data_short;
	int *real_data_int;
	int *imag_data_int;
	unsigned int elements;
	float *real_data_float;
	float *imag_data_float;
	double *real_data_double;
	double *imag_data_double;
	ASM_SAMPLE *real_data;
	ASM_SAMPLE *imag_data;


	asm_header *hp;
	int    outfile;
	int    nbytes;
	int    teller;
	int    dtype;

	filename = Window_File(vp);
	real_data=DataReal(vp);
	imag_data=DataImag(vp);

	dtype = DataType(vp);

	if ((hp = (asm_header *) malloc(sizeof(asm_header))) == NULL) return (ERR_ALLOC);

	*hp = (*vp).header;

	hp->bits_p_samp=bps;

	/*  Wegschrijven van de header  */

	outfile = putFile(filename,(char *) hp, (int)sizeof(asm_header),TRUE,FALSE);

	free((char *)hp);

	/* Totaal aantal elementen */
	elements = DataChannels(vp)*DataRecords(vp)*DataLength(vp);

	/* Wegschrijven van de data (todisc)   */

	switch (bps)
	{
	case 8:          /* Data saven als chars (8 bit)    */

		nbytes = elements;
		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_char = (char *) malloc((unsigned int)elements*sizeof(char))) == NULL)
			{
				printf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				real_data_char[teller]=(char)real_data[teller];
			outfile = putFile(filename,(char *) real_data_char ,nbytes ,TRUE ,TRUE );
			free(real_data_char);
		}
		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if ((imag_data_char = (char *) malloc((unsigned int)elements*sizeof(char))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				imag_data_char[teller]=(char)imag_data[teller];
			outfile = putFile(filename,(char *) imag_data_char ,nbytes ,TRUE ,TRUE );
			free(imag_data_char);
		}
		break;

	case 16:                        /* Data saven als shorts (16 bit) */
		nbytes = elements*2;

		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_short = (short *) malloc((unsigned int)elements*sizeof(short))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				real_data_short[teller]=(short)real_data[teller];
			outfile = putFile(filename,(char *) real_data_short ,nbytes ,TRUE ,TRUE );
			free(real_data_short);
		}
		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if ((imag_data_short = (short *) malloc((unsigned int)elements*sizeof(short))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				imag_data_short[teller]=(short)imag_data[teller];
			outfile = putFile(filename,(char *) imag_data_short ,nbytes ,TRUE ,TRUE );
			free(imag_data_short);
		}

		break;

	case 32:    
		nbytes = elements*4;       /* Data saven als integers (32 bit) */


		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_int = (int *) malloc((unsigned int)elements*sizeof(int))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				real_data_int[teller]=(int)real_data[teller];
			outfile = putFile(filename,(char *) real_data_int ,nbytes ,TRUE ,TRUE );
			free(real_data_int);
		}
		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if ((imag_data_int = (int *) malloc((unsigned int)elements*sizeof(int))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				imag_data_int[teller]=(int)imag_data[teller];
			outfile = putFile(filename,(char *) imag_data_int ,nbytes ,TRUE ,TRUE );
			free(imag_data_int);
		}

		break;



	case 3232:     /* Data saven als float (32 bit) */
		nbytes = elements*4;
		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_float = (float *) malloc((unsigned int)elements*sizeof(float))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1 ;
			}
			for (teller=0;teller < elements;teller++)
				real_data_float[teller]=(float)real_data[teller];
			outfile = putFile(filename,(char *) real_data_float ,nbytes ,TRUE ,TRUE );
			free(real_data_float);
		}
		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if ((imag_data_float = (float *) malloc((unsigned int)elements*sizeof(float))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				imag_data_float[teller]=(float)imag_data[teller];
			outfile = putFile(filename,(char *) imag_data_float ,nbytes ,TRUE ,TRUE );
			free(imag_data_float);
		}

		break;

	case 6464:
		nbytes = elements*8;
		if ((dtype == 0) || (dtype == 2))   /* Reele deel */
		{
			if ((real_data_double = (double *) malloc((unsigned int)elements*sizeof(double))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				real_data_double[teller]=(double)real_data[teller];
			outfile = putFile(filename,(char *) real_data_double ,nbytes ,TRUE ,TRUE );
			free(real_data_double);
		}
		if ((dtype == 1) || (dtype == 2))   /* Imaginaire deel */
		{
			if ((imag_data_double = (double *)malloc((unsigned int)elements*sizeof(double))) == NULL)
			{
				asm_wprintf("Error in todisc: malloc failed");
				return -1;
			}
			for (teller=0;teller < elements;teller++)
				imag_data_double[teller]=(double)imag_data[teller];
			outfile = putFile(filename,(char *) imag_data_double ,nbytes ,TRUE ,TRUE );
			free(imag_data_double);
		}

		break;
	default:    
		break;
	}

	if (outfile !=NO_ERROR) return(ERR_WRITEFILE);

	/* set filetype of just written file */
	/*  SetFileType(filename,ASMF); */

	return(NO_ERROR);
}
