/***************************************************************
 *                                                             *
    File: C.COMMND1

    Inhoud: int QuitCi (char *s), int WriteCi(char *p),int ReadCi(char *p),
            int RenameCi(char *p)

    Schrijvers: Edwin Zoer & Erwin Waterlander
                HTS Enschede

   Datum:      juni 1993

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

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <time.h>
#include <stdlib.h>
#include <dirent.h>
#include "allegro.h"
#include "asm.h"
#include "parse.h"
#include "commnd.h"
#include "image.h"
#include "errors.h"
#include "imagwind.h"
#include "plotutil.h"
#include "fileio.h"

#define DEF_N 9              /* 2^9 = 512 = default aantal samples */
#define DEF_FREQ 100         /* Default frequentie */
#define DEF_AMPL 100         /* Default amplitude */

#define ASMSIGNAL 19

extern int x_res, y_res;           /* screen resolution */
extern VENSTER* vp[MAXSIG];
extern unsigned short MAX_LENGTH;
extern unsigned short SAMPLE_RATE;
extern int current_signal;  /* The actual signal drawn to screen */
extern BOOL don;
extern BITMAP *asm_draw_bitmap;
extern char signal_dir[1024];
extern int prompt_flag ;
extern FILE *logfile;

/***** s t r m f e *****
   Abstract:   Change file extension.
   Parameters: New filename, old filename and new extension
   Returns:    Nothing
***********************/

void strmfe( char *nieuw, char *old, char *ext )
{
	while ( ( *old != 0 ) && ( *old != '.' ) )
		*nieuw++ = *old++;
	*nieuw++ = '.';
	while ( *ext )
		*nieuw++ = *ext++;
	*nieuw = 0;
} /* strmfe() */
/********************************************************************/

/*************************************************************************
 * int QuitCi(char *s)                                                   *
 * Einde ASM                                                             *
 *************************************************************************/

int QuitCi (char *s)
{
	asm_wprintf("Press <Esc> to quit.");

	return 0;
}

int ListComCi (char *s)
{
	prstab();

	return 0;
}

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

int HistCi(char *p)
{

	int in_im,out_im,i,j;  /* Vensternummer */
	unsigned int alloc_size,lengte;
	unsigned int offset_in,offset_out;
	unsigned short channel,element;
	int channel_nr,buckets,bucket;
	double Delta;
	char *in_signalname;
	char *out_signalname;
	char buffer1[128],buffer2[128];
	ASM_SAMPLE *real_data_out;
	ASM_SAMPLE *imag_data_out;
	ASM_SAMPLE *real_data_in;
	ASM_SAMPLE *imag_data_in;
	ASM_SAMPLE *imag_hulp,*real_hulp;
	BOOL bucket_found;

	in_signalname  = strarg(&p,NULL,"Input Signal","a",buffer1);

	in_im = Find_Signal_Venster(in_signalname);
	if (in_im == -1) return ERR_SIGNAL;       /* Signaal bestaat niet */

	out_signalname = strarg(&p,NULL, "Output Signal",in_signalname,buffer2);

	buckets        = intarg(&p,NULL,"Buckets (2^n)",MIN_N,(int)(log(DataLength(vp[in_im]))/log(2)),(int)(log(DataLength(vp[in_im]))/log(2)));
	channel_nr = (unsigned short) intarg(&p,NULL,"Channel",0,DataChannels(vp[in_im])-1,0);

	if(DataDomain(vp[in_im]) != TIME) return ERR_DOMAIN;

	buckets    = pow(2,buckets);
	alloc_size = DataChannels(vp[in_im])*buckets;
	lengte     = DataRecords(vp[in_im])*DataLength(vp[in_im]); /* channel lengte */

	out_im = Find_Signal_Venster(out_signalname);      /* Vind het juiste venster */
	if (out_im == -1)                                  /* Signaal bestond nog niet */
	{
		out_im = Create_Venster(out_signalname,alloc_size);
		if (out_im == -1) return ERR_WINDOWS;             /* Te veel displaywindows */
	}
	else
		if(in_im != out_im)
			Realloc_Venster(vp[out_im],alloc_size);

	real_data_out = DataReal(vp[out_im]);    /* Bewaar de pointers voor de data */
	imag_data_out = DataImag(vp[out_im]);
	real_data_in  = DataReal(vp[in_im]);
	imag_data_in  = DataImag(vp[in_im]);


	real_hulp=imag_hulp=NULL;
	real_hulp = (ASM_SAMPLE*) malloc((unsigned int)DataAllocSize(vp[in_im])*sizeof(ASM_SAMPLE));
	imag_hulp = (ASM_SAMPLE*) malloc((unsigned int)DataAllocSize(vp[in_im])*sizeof(ASM_SAMPLE));

	if ( (imag_hulp == NULL) || (real_hulp == NULL) )
	{
		asm_wprintf("Error in HistCi: malloc failed");
		return 0;
	}

	/* Copieer de inhoud van de ingangsdata */

	for (i=0;i<(DataChannels(vp[in_im])*DataRecords(vp[in_im])*DataLength(vp[in_im]));i++)
	{
		real_hulp[i] = real_data_in[i];
		imag_hulp[i] = imag_data_in[i];
	}

	if (in_im == out_im)
	{
		Realloc_Venster(vp[out_im],alloc_size);
		real_data_in  = real_data_out = DataReal(vp[out_im]);
		imag_data_in  = imag_data_out = DataImag(vp[out_im]);
	}

	(*vp[out_im]).header = (*vp[in_im]).header;   /* Maak de headers aan elkaar gelijk   */

	DataReal(vp[out_im]) = real_data_out;         /* Zet de pointers van de data weer terug*/
	DataImag(vp[out_im]) = imag_data_out;

	DataLength(vp[out_im])=buckets;
	DataRecords(vp[out_im]) = 1;
	DataType(vp[out_im]) = REAL;
	DataDomain(vp[out_im]) = AMPL;
	strncpy(DataSignalName(vp[out_im]),out_signalname,32);
	Window_Mode(vp[out_im])= HIST_M;
	Window_Record(vp[out_im])= 0;
	Window_Channel(vp[out_im])= channel_nr;
	Window_HScale(vp[out_im]) = Window_HScale(vp[in_im]);

	for (channel = 0;channel < DataChannels(vp[in_im]); channel++)
	{
		/* Het histogram wordt per channel van het ingangssignaal bepaalt */
		/* In het histogram gaat het om de magnitude */


		/* Bereken de offset van het channel */
		offset_in = channel*lengte;
		offset_out = (channel)*DataRecords(vp[out_im])*DataLength(vp[out_im]);

		DataRealMin(vp[out_im])=DataRealMax(vp[out_im])=sqrt(pow(real_hulp[offset_in],2)+pow(imag_hulp[offset_in],
		    2));

		/* Bepaal van de elementen de magnitude en het maximum en minimum */
		for (element=0; element < lengte; element++)
		{
			real_hulp[element+offset_in] = sqrt(pow(real_hulp[element+offset_in],2)+pow(imag_hulp[element+offset_in],
			    2));
			if (real_hulp[element+offset_in] > DataRealMax(vp[out_im]))
				DataRealMax(vp[out_im])=real_hulp[element+offset_in];
			if (real_hulp[element+offset_in] < DataRealMin(vp[out_im]))
				DataRealMin(vp[out_im])=real_hulp[element+offset_in];
		}



		Delta=(double)((DataRealMax(vp[out_im])-DataRealMin(vp[out_im]))/(double)(buckets));


		/*  Maak de elementen van out_im 0  */
		for(i=0;i<(DataRecords(vp[out_im])*DataLength(vp[out_im]));i++)
		{
			real_data_out[i+offset_out] = 0.0;
			imag_data_out[i+offset_out] = 0.0;
		}

		for (i=0;i < lengte;i++)
		{
			bucket = buckets/2;
			bucket_found = FALSE;

			for(j= (buckets/2);(j>0) && (bucket_found == FALSE);j=(int)(j/2))
			{

				if ( real_hulp[i+offset_in] >= (DataRealMin(vp[out_im])+((double)bucket+1.0)*Delta))
					bucket = bucket + (int)(j/2);
				else
				{
					if ( real_hulp[i+offset_in] < (DataRealMin(vp[out_im])+(double)bucket*Delta))
						bucket = bucket - (int)(j/2);
					else
						bucket_found = TRUE;
				}
				if (real_hulp[i+offset_in] < (DataRealMin(vp[out_im])+Delta))
				{
					bucket = 0;
					bucket_found = TRUE;
				}
			}
			real_data_out[offset_out+bucket] = real_data_out[offset_out+bucket] +1;
		}

	}


	free(real_hulp);
	free(imag_hulp);
	free(Window_Diag(vp[out_im]).data);
	Window_Diag(vp[out_im]).data = NULL;


	if (don)
	{
		make_plot(vp[out_im]);
		current_signal = out_im;
		Window_InUse(vp[out_im]) = TRUE;
	}
	else
		Window_InUse(vp[out_im]) = FALSE;

	return 0 /*NO_ERROR*/;
}




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

int WriteCi(char *p)
{
	char *signalfile;
	int im;
	char *file_name;
	char *user_text;
	char *description;
	char *signalname;
	char buffer1[128],buffer2[128],buffer3[128],buffer4[128];
	short  bps,bitsps;
	time_t timer;
	char *ctijd;



	signalname = strarg(&p,NULL,"Signal","a",buffer1);
	file_name = strarg(&p,NULL,"Filename",signalname,buffer2);
	user_text = strarg(&p,NULL,"User Text","",buffer3);
	description = strarg(&p,NULL,"Description","",buffer4);

	im = Find_Signal_Venster(signalname);   /* Vind het juiste venster */
	if (im == -1) return ERR_SIGNAL;        /* Signaal bestaat niet */

	signalfile = (char *) calloc(256,sizeof(char));
	if (signalfile == NULL)
	{
		asm_wprintf("Error in WriteCi: calloc failed");
		return 0;
	}

	strncpy(signalfile,signal_dir,99);
	strncat(signalfile,file_name,512); /* file naam max 10 karakters (RISC OS) */


	switch (DataBits_p_s(vp[im]))
	{
	case BPS_CHAR:
		bps=0;
		break;
	case BPS_SHORT:
		bps=1;
		break;
	case BPS_INT:
		bps=2;
		break;
	case BPS_FLOAT:
		bps=3;
		break;
	case BPS_DOUBLE:
		bps=4;
		break;
	default:
		bps=1;
		break;
	}

	bps = (short) intarg(&p,NULL,"BPS 0:char,1:short,2:int,3:float,4:double",0,4,bps);

	switch (bps)
	{
	case 0:
		bitsps=BPS_CHAR;
		break;
	case 1:
		bitsps=BPS_SHORT;
		break;
	case 2:
		bitsps=BPS_INT;
		break;
	case 3:
		bitsps=BPS_FLOAT;
		break;
	case 4:
		bitsps=BPS_DOUBLE;
		break;
	default:
		bitsps=BPS_SHORT;
		break;
	}
	user_text[sizeof(DataUserText(vp[im]))-1] = '\0';
	description[sizeof(DataDescription(vp[im]))-1] = '\0';
	signalfile[sizeof(Window_File(vp[im]))-1] = '\0';
	strncpy(DataUserText(vp[im]),user_text,sizeof(DataUserText(vp[im])));
	strncpy(DataDescription(vp[im]),description,sizeof(DataDescription(vp[im])));
	strncpy(Window_File(vp[im]),signalfile,sizeof(Window_File(vp[im])));

	time(&timer);
	ctijd = asctime(localtime(&timer));
	ctijd[sizeof(DataDate(vp[im]))-1] = '\0';
	strncpy(DataDate(vp[im]),ctijd,sizeof(DataDate(vp[im])));

	free(signalfile);
	return(todisc(vp[im],ASMF,bitsps));

}

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

int ReadCi(char *p)
{
	int i,im, c, k;
	int filetype;
	char *signalfile;
	unsigned int alloc_size;
	char *file_name;
	char *signalname;
	char buffer1[128],buffer2[128];
	FILE *fp;

	file_name  = strarg(&p,NULL,"Filename","a",buffer1);
	signalname = strarg(&p,NULL,"Signal",file_name,buffer2);

	if( check_file(file_name) != NO_ERROR)
	{
		asm_wprintf("File %s is possibly not an ASM file.",file_name);
		asm_wprintf("Continue anyway? y/n");
		k = readkey();
		c = k & 0xFF;
		if( (c != 'y') && (c!='Y'))
			return(ERR_FILETYPE);
	}

	signalfile = (char *) calloc(256,sizeof(char));
	if (signalfile == NULL)
	{
		asm_wprintf("Error in ReadCi: calloc failed");
		return 0;
	}

	strncpy(signalfile,signal_dir,99);
	strncat(signalfile,file_name,512); /* file naam max 10 karakters (RISC OS)*/


	/* Controleer of de file wel bestaat */

	if((fp=fopen(signalfile,"rb"))==NULL)
	{
		fclose(fp);
		return(ERR_OPENFILE);
	}
	fclose(fp);    /* Sluit de file, als hij bestond */

	filetype = ASMF;

	/* Neem een voorlopige alloc_size, er moet nog gerealloceerd worden
    omdat de grootte nu nog niet bekend is.                  */

	alloc_size = 128; /* willekeurig */

	im = Find_Signal_Venster(signalname);   /* Vind het juiste venster */
	if (im == -1)                           /* Signaal bestond nog niet */
	{
		im = Create_Venster(signalname,alloc_size);
		if (im == -1) return ERR_WINDOWS;      /* Te veel displaywindows */
	}
	else Realloc_Venster(vp[im],alloc_size);


	signalfile[sizeof(Window_File(vp[im]))-1] = '\0';
	strncpy(Window_File(vp[im]),signalfile,sizeof(Window_File(vp[im])));
	if ( (i=fromdisc(vp[im],filetype))!=NO_ERROR)
		return i;
	signalname[sizeof(DataSignalName(vp[im]))-1] = '\0';
	strncpy(DataSignalName(vp[im]),signalname,sizeof(DataSignalName(vp[im])));
	Window_Record(vp[im]) = 0;     /* Te displayen record */
	Window_Channel(vp[im]) =0;     /* Te displayen channel */

	switch(DataDomain(vp[im]))
	{
	case TIME:
		Window_Mode(vp[im]) = REAL_M;
		break;
	case FREQ:
		Window_Mode(vp[im]) = BODE_M;
		break;
	case AMPL:
		Window_Mode(vp[im]) = HIST_M;
		break;
	case MAGN:
		Window_Mode(vp[im]) = MAGN_M;
		break;
	case PHAS:
		Window_Mode(vp[im]) = PHAS_M;
		break;
	default:
		Window_Mode(vp[im]) = REAL_M;
		break;
	}

	free(signalfile);

	if (don)
	{
		make_plot(vp[im]);
		current_signal = im;
		Window_InUse(vp[im]) = TRUE;
	}
	else
		Window_InUse(vp[im]) = FALSE;
	return 0;         /* No Error */
}



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

int RenameCi(char *p)
{
	int im;
	char buffer1[128],buffer2[128];
	char *in_signalname;
	char *out_signalname;
	char nm[128];

	in_signalname  = strarg(&p,NULL,"Signal","a",buffer1);
	out_signalname = strarg(&p,NULL,"Name","b",buffer2);

	im = Find_Signal_Venster(in_signalname);
	if (im == -1) return ERR_SIGNAL;       /* Signaal bestaat niet */

	if (Find_Signal_Venster(out_signalname) != (-1) )
		return ERR_EXIST;         /* Signaal bestaat al */



	strncpy(DataSignalName(vp[im]),out_signalname,sizeof(DataSignalName(vp[im])));

	switch (Window_Mode(vp[im]))
	{
	case REAL_M:
		strncpy(nm,"Signal ",10);
		strncat(nm,DataSignalName(vp[im]),40);
		if (DataDomain(vp[im])==TIME)
			strncat(nm,"  Real (Time)",20);
		if (DataDomain(vp[im])==FREQ)
			strncat(nm,"  Real (Freq)",20);
		break;
	case IMAG_M:
		strncpy(nm,"Signal ",10);
		strncat(nm,DataSignalName(vp[im]),40);
		if (DataDomain(vp[im])==TIME)
			strncat(nm,"  Imaginary (Time)",20);
		if (DataDomain(vp[im])==FREQ)
			strncat(nm,"  Imaginary (Freq)",20);
		break;
	case BODE_M:
		strncpy(nm,"Signal ",10);
		strncat(nm,DataSignalName(vp[im]),40);
		strncat(nm,"  BodeDiagram",20);
		break;
	case PHAS_M:
		strncpy(nm,"Signal ",10);
		strncat(nm,DataSignalName(vp[im]),40);
		strncat(nm,"  Phase",20);
		break;
	case MAGN_M:
		strncpy(nm,"Signal ",10);
		strncat(nm,DataSignalName(vp[im]),40);
		strncat(nm,"  Magnitude",20);
		break;
	default    :
		break;
	}

	if (don)
	{
		make_plot(vp[im]);
		current_signal = im;
		Window_InUse(vp[im])= TRUE;
	}
	else
		Window_InUse(vp[im]) = FALSE;


	return 0;
}

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


int BitmapCi(char *p)
{
	char *signalname;
	int im, format;
	char buffer1[512],buffer2[512];
	char file_name[1024], *fn;
	RGB asm_pallete[256];



	signalname = strarg(&p,NULL,"Signal","a",buffer1);
	fn         = strarg(&p,NULL,"Filename",signalname,buffer2);
	format     = intarg(&p,NULL,"Format? 1 = pcx, 2 = tga, 3 = bmp",1 ,3 , 1);

	im = Find_Signal_Venster(signalname);   /* Vind het juiste venster */
	if (im == -1) return ERR_SIGNAL;        /* Signaal bestaat niet */

	current_signal = im;
	make_plot(vp[im]);
	get_pallete(asm_pallete);


	switch (format)
	{
	case 1:
		strmfe(file_name,fn,"pcx");
		save_pcx(file_name,asm_draw_bitmap,asm_pallete);
		break;
	case 2:
		strmfe(file_name,fn,"tga");
		save_tga(file_name,asm_draw_bitmap,asm_pallete);
		break;
	case 3:
		strmfe(file_name,fn,"bmp");
		save_bmp(file_name,asm_draw_bitmap,asm_pallete);
		break;
	default:
		strmfe(file_name,fn,"pcx");
		save_pcx(file_name,asm_draw_bitmap,asm_pallete);
		break;
	}

	asm_wprintf("Signal image saved in %s",file_name);
	return 0;
}

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


int SamplerateCi(char *p)
{

	SAMPLE_RATE = (unsigned short) intarg(&p,NULL,"Samplerate in 10Hz",1,USHRT_MAX,SAMPLE_RATE);

	asm_wprintf("SAMPLE_RATE has been set to %d",SAMPLE_RATE);
	return 0;

}

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

int SignaldirCi(char *p)
{
	char buffer1[1024], *sd;
	DIR *dirp;

	sd = strarg(&p,NULL,"Signal directory",signal_dir,buffer1);

	if((dirp=opendir(sd)) == NULL) /* GJM */
	{
		asm_wprintf("Directory does not exist");
	}
	else
	{
		closedir(dirp);
		strcpy(signal_dir,sd);
		put_backslash(signal_dir); /*function provided by Allegro */
		asm_wprintf("signal_dir has been set to %s",signal_dir);
	}
	return 0;
}

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

int MacroCi(char *p)
{
	char buffer1[1024], *filename;
	FILE *infile;
	char line[1024],c ,error=0;
	int i,j;
	char *cmd, *nxt, *cmmnt;


	filename = strarg(&p,NULL,"Macro file","asm.mac",buffer1);


	if  ((infile = fopen(filename,"r")) == NULL)
	{
		asm_wprintf("Error opening Macro file %s",filename);
		return(0);
	}
	else
	{
		asm_wprintf("Executing macrofile: %s",filename);

		while (!feof(infile) )
		{
			j=0;
			error = 0;
			for(i=0; ((c=getc(infile)) != '\n') && (c!=EOF) ;i++)
				if (i < (sizeof(line)-1))
				{
					line[i]=c;
					j++;
				}
				else error = 1;
			line[j]='\0';  /* end string */

			if(strcmp(line,"")!=0)
			{
				asm_wprintf("%s<",line);

				cmd = line;

				/* skip comment ('*--------') from parsing by making it 0 */

				if ((cmmnt = strchr(line, '*')) != NULL) *cmmnt = '\0';
				nxt = nxtarg(&cmd, NULL);
				switch (j = stablk(nxt, 0))
				{
				case -1:
					error = ERR_UNKNOWN;
					break;
				case -2:
					error = ERR_AMBIGUOUS;
					break;
				default:
					nxt = stpblk(cmd);
					if (*nxt == '?')
						if (*stpblk(nxt + 1) == 0) prompt_flag = TRUE;
					error = cmd_exec(j, cmd);
					prompt_flag = FALSE;
					break;
				}
				print_error(error);
			}
		}

		fclose(infile);
		asm_wprintf("Finished executing macrofile: %s",filename);


	}
	return 0;
}

int DosshellCi (char *s)
{

	if(logfile)
		fclose(logfile);

	remove_mouse();
	remove_keyboard();
	set_gfx_mode(GFX_TEXT,80,25,0,0);

	system(NULL);

	install_keyboard();
	install_mouse();
	gfx_mode(x_res,y_res);
	init_interp();

	logfile = fopen(ASM_LOG_FILE,"a");

	return 0;
}
