// TDR_file.cp
// File handling of TDR data processing system
#include <complex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Strings.h>

#include "debugs.h"
#include "CustomFileDialog.h"
#include "fileio.h"
#include "inputdialog.h"
#include "datautils.h"
#include "stde.h"
#include "TDR.h"
#include "TDR_meas.h"
#include "TDR_Prefs.h"

// Error code for file
#define TDR_FERR_NOERR			0
#define TDR_FERR_FSTRC			-1
#define TDR_FERR_OVFLW			-2
#define TDR_FERR_TDOM			-3
#define TDR_FERR_NOFILE			-4

// read flag
#define TDR_READ_STD		0
#define TDR_READ_CAL		1
#define TDR_READ_SAMPLE		2

//86100B preamble start position
#define AG_86100B_PRSTAET	15

// local functions
static short read3data(TDR_PARAMETER *pr);
static short read2sample(TDR_PARAMETER *pr);	
static short read2cal(TDR_PARAMETER *pr); 	
static short read1std(TDR_PARAMETER *pr); 	
static short read1sample(TDR_PARAMETER *pr); 	
static short read1cal(TDR_PARAMETER *pr);
static short readHP54750A(TDR_PARAMETER *pr, int flag);
static short read86100BV(TDR_PARAMETER *pr, int flag);
static short read86100BV_preamble(FileIO *fs, TDR_PREAMBLE *pre);
static short read2sampleT(TDR_PARAMETER *pr); 	
static short read2calT(TDR_PARAMETER *pr); 
static void TDR_freaderr(unsigned char *str0, unsigned char *str1, unsigned char *str2, unsigned char *str3);
static void TDR_freaderr_show(short errcode);



// Return 0 when reading completed.
short TDR_readDatafile(TDR_PARAMETER *pr)
{
	short err;
	FileIO *pre_fs_dfile;

	pre_fs_dfile = NULL;
		
	switch(pr->flag_dfile1){ 
		case TDR_FRFLAG_SCS:	// standard, caliblation, unknown
			err = read3data(pr);
			if(err != 0) return err;
			current_fss = &(pr->fs_dfile1.fss);
			TDR_LoadOPInfo(&(pr->fs_dfile1), &oinfo);
			pre_fs_dfile = &(pr->fs_dfile1);
			break;
		case TDR_FRFLAG_SS:		// standard-unknown pair
			err = read2sample(pr);
			if(err != 0) return err;
			current_fss = &(pr->fs_dfile1.fss);
			pre_fs_dfile = &(pr->fs_dfile1);
			TDR_LoadOPInfo(&(pr->fs_dfile1), &oinfo);
			break;
		case TDR_FRFLAG_1D: 	// 1-reflected wave
			err = read1std(pr);	// suppose 1st data file contains standard
			if(err != 0) return err;
			break;
		case TDR_FRFLAG_TOKAI:	// Tokai Univ. format (always contains one pair of reflected wave)
			err = read2sampleT(pr);		// standard-unknown pair
			if(err != 0) return err;
			current_fss = &(pr->fs_dfile1.fss);
			pre_fs_dfile = &(pr->fs_dfile1);
			break;
		case TDR_FRFLAG_HP54750A_D:	// HP54750A data file (always 1 refrected wave, without preamble)
			err = readHP54750A(pr, TDR_READ_STD);	// standard
			if(err != 0) return err;
			break;
		case TDR_FRFLAG_86100B:	// AG81600B data file (always 1 refrected wave, without preamble)
			err = read86100BV(pr, TDR_READ_STD);	// standard
			if(err != 0) return err;
			break;
			
	}
	
	switch(pr->flag_dfile2){ 
		case TDR_FRFLAG_SCS:
			TDR_freaderr("\pPlase click Datafile1 button ", "\pto read std-cal-sample data",
		             "\p","\p");
			break;
		case TDR_FRFLAG_SS:		// standard-DCcal pair
			read2cal(pr);					
			if(err != 0) return err;
			break;
		case TDR_FRFLAG_1D: 	// 1-reflected wave
			read1cal(pr);		// DCcal data
			if(err != 0) return err;
			break;
		case TDR_FRFLAG_TOKAI:	// Tokai Univ. format (always contains one pair of reflected wave)
			read2calT(pr);		// standard-DCcal pair		
			if(err != 0) return err;
			break;
		case TDR_FRFLAG_HP54750A_D:	// HP54750A data file (always 1 refrected wave, without preamble)
			err = readHP54750A(pr, TDR_READ_CAL);		// DCcal data
			if(err != 0) return err;
			break;
		case TDR_FRFLAG_86100B:	// AG81600B data file (always 1 refrected wave, without preamble)
			err = read86100BV(pr, TDR_READ_CAL);	// DCcal data
			if(err != 0) return err;
			break;

	}
	
	switch(pr->flag_dfile3){  // chack the type of 1st file 
		case TDR_FRFLAG_SCS:	// standard, caliblation, unknown
			TDR_freaderr("\pPlase click Datafile1 button ", "\pto read std-cal-sample data",
		             "\p","\p");
			break;
		case TDR_FRFLAG_SS:		// standard-unknown pair
			TDR_freaderr("\pPlase click [Datafile1/Datafile2] button ", "\pto read [std-sample/std-cal] data",
		             "\p","\p");
			break;
		case TDR_FRFLAG_1D: 	// 1-reflected wave
			err = read1sample(pr);	// sample
			if(err != 0) return err;
			current_fss = &(pr->fs_dfile3.fss);
			TDR_LoadOPInfo(&(pr->fs_dfile3), &oinfo);
			pre_fs_dfile = &(pr->fs_dfile3);
			break;
		case TDR_FRFLAG_TOKAI:	// Tokai Univ. format (always contains one pair of reflected wave)
			TDR_freaderr("\pPlase click [Datafile1/Datafile2] button ", "\pto read [std-sample/std-cal] data",
		             "\p","\p");
			break;
		case TDR_FRFLAG_HP54750A_D:	// HP54750A data file (always 1 refrected wave, without preamble)
			err = readHP54750A(pr, TDR_READ_SAMPLE);
			current_fss = &(pr->fs_dfile3.fss);
			if(err != 0) return err;
			pr->timebase_points = pr->n_rawdata;
			TDR_SetTimebase(pr);
			break;
		case TDR_FRFLAG_86100B:	// AG81600B data file (always 1 refrected wave, without preamble)
			err = read86100BV(pr, TDR_READ_SAMPLE);	// DCcal data
			if(err != 0) return err;
			break;

	}

	// reset file type for the next reading
	pr->flag_dfile1 = TDR_FRFLAG_NOFILE;
	pr->flag_dfile2 = TDR_FRFLAG_NOFILE;
	pr->flag_dfile3 = TDR_FRFLAG_NOFILE;
	
	// load preamble and set sampling interval
	// if you use apj's acquisition program, you get the data file with preamble.
	if(pr->launch_flag == LAUNCH_BY_CL && pre_fs_dfile != NULL){
		TDR_ClearPreamble(&pre);
		if(TDR_LoadPreamble(pre_fs_dfile, &pre) == 0){ // in case of preamble exists.
			pr->dt = pre.xincrement;
		}
	}
	return err;
}


// subroutines
static short read3data(TDR_PARAMETER *pr)
{
	char readbuf[256];
	double time, dat1, dat2, dat3;
	OSErr err;
	short pathRefNum;
	short i;
	
	if(!pr->fs_dfile1.sfr.sfGood){	// file not selected.....
		TDR_freaderr_show(TDR_FERR_NOFILE);
		return TDR_FERR_NOFILE;
	}
	err = FSpOpenDF(&(pr->fs_dfile1.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile1)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	for(i = 0 ; i < N_DATA; i++){
		err = Read1Line(&(pr->fs_dfile1), readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%le %le %le %le", &time, &dat1, &dat2, &dat3) != 4){
			CloseFileIO(&(pr->fs_dfile1));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		*(TA + i) = time;
		*(RS + i) = dat2;
		*(RB + i) = dat1;
		*(RC + i) = dat2;
		*(RX + i) = dat3;
	}
	CloseFileIO(&(pr->fs_dfile1));
	pr->dt = *(TA + 1) - *(TA);
	pr->n_rawdata = i;
	
	return TDR_FERR_NOERR;
}

/*********************** 2 data in file ***********************/
static short read2sample(TDR_PARAMETER *pr) 	
{
	char readbuf[256];
	double time, dat1, dat2;
	OSErr err;
	short i;
	short pathRefNum;
		
	if(!pr->fs_dfile1.sfr.sfGood){	// file not selected.....
		TDR_freaderr_show(TDR_FERR_NOFILE);
		return TDR_FERR_NOFILE;
	}
	err = FSpOpenDF(&(pr->fs_dfile1.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile1)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	for(i = 0 ; i < N_DATA; i++){
		err = Read1Line(&(pr->fs_dfile1), readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%le %le %le", &time, &dat1, &dat2) != 3){
			CloseFileIO(&(pr->fs_dfile1));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		*(TA + i) = time;
		*(RS + i) = dat1;
		*(RX + i) = dat2;
	}
	CloseFileIO(&(pr->fs_dfile1));
	pr->dt = *(TA + 1) - *(TA);
	pr->n_rawdata = i;

	return TDR_FERR_NOERR;
}

static short read2cal(TDR_PARAMETER *pr) 	
{
	char readbuf[256];
	double time, dat1, dat2;
	OSErr err;
	short i;
	short pathRefNum;
	
	if(!pr->fs_dfile2.sfr.sfGood){	// file not selected.....
		return TDR_FERR_NOERR;		// case of no calibraton
	}
	err = FSpOpenDF(&(pr->fs_dfile2.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile2)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	for(i = 0 ; i < N_DATA; i++){
		err = Read1Line(&(pr->fs_dfile2), readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%le %le %le", &time, &dat1, &dat2) != 3){
			CloseFileIO(&(pr->fs_dfile2));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		if(*(TA + i) != time){
			CloseFileIO(&(pr->fs_dfile2));
			TDR_freaderr_show(TDR_FERR_TDOM);
			return TDR_FERR_FSTRC;
		}			

		*(RB + i) = dat1;
		*(RC + i) = dat2;
	}
	CloseFileIO(&(pr->fs_dfile2));
	return TDR_FERR_NOERR;
}


/************************* 1 data in file *********************************/
static short read1std(TDR_PARAMETER *pr) 	
{
	char readbuf[256];
	double time, dat1;
	OSErr err;
	short i;
	short pathRefNum;
		
	if(!pr->fs_dfile1.sfr.sfGood){	// file not selected.....
		TDR_freaderr_show(TDR_FERR_NOFILE);
		return TDR_FERR_NOFILE;
	}
	err = FSpOpenDF(&(pr->fs_dfile1.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile1)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	for(i = 0 ; i < N_DATA; i++){
		err = Read1Line(&(pr->fs_dfile1), readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%le %le", &time, &dat1) != 2){
			CloseFileIO(&(pr->fs_dfile1));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		*(TA + i) = time;
		*(RS + i) = dat1;
		*(RB + i) = dat1;
	}
	
	pr->n_raw_std = i;

	CloseFileIO(&(pr->fs_dfile1));
	return TDR_FERR_NOERR;
}


static short read1sample(TDR_PARAMETER *pr) 	
{
	char readbuf[256];
	double time, dat1;
	OSErr err;
	short i;
	short pathRefNum;
	
	if(!pr->fs_dfile3.sfr.sfGood){	// file not selected.....
		TDR_freaderr_show(TDR_FERR_NOFILE);	
		return TDR_FERR_NOFILE;
	}
	err = FSpOpenDF(&(pr->fs_dfile3.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile3)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	for(i = 0 ; i < N_DATA; i++){
		err = Read1Line(&(pr->fs_dfile3), readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%le %le ", &time, &dat1) != 2){
			CloseFileIO(&(pr->fs_dfile3));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		if(*(TA + i) != time){
			CloseFileIO(&(pr->fs_dfile3));
			TDR_freaderr_show(TDR_FERR_TDOM);
			return TDR_FERR_TDOM;
		}			

		*(RX + i) = dat1;
	}
	CloseFileIO(&(pr->fs_dfile3));
	pr->dt = *(TA + 1) - *(TA);
	pr->n_rawdata = i;
	pr->n_raw_sample = i;

	return TDR_FERR_NOERR;
}	

static short read1cal(TDR_PARAMETER *pr) 	
{
	char readbuf[256];
	double time, dat1;
	OSErr err;
	short i;
	short pathRefNum;
		
	if(!pr->fs_dfile2.sfr.sfGood){	// file not selected.....
		return TDR_FERR_NOERR;
	}
	err = FSpOpenDF(&(pr->fs_dfile2.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile2)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	for(i = 0 ; i < N_DATA; i++){
		err = Read1Line(&(pr->fs_dfile2), readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%le %le ", &time, &dat1) != 2){
			CloseFileIO(&(pr->fs_dfile2));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		if(*(TA + i) != time){
			CloseFileIO(&(pr->fs_dfile2));
			TDR_freaderr_show(TDR_FERR_TDOM);
			return TDR_FERR_TDOM;
		}			

		*(RC + i) = dat1;
	}
	
	pr->n_raw_cal = i;

	CloseFileIO(&(pr->fs_dfile2));
	return TDR_FERR_NOERR;
}	

/******************* HP54750Aのデータファイルを読む ********************************/
// read1?とは違う方針で、読み込みフラグによって処理を振り分ける
// read1ナントカもこれと同じに直すべきだが、これはまたの機会にする
// flag : TDR_READ_STD | TDR_READ_CAL | TDR_READ_SAMPLE
// １つづつ読み込むときは、Dfile1が標準、Dfile2がDC（あれば）、Dfile3が未知資料
// 時間軸無し
static short readHP54750A(TDR_PARAMETER *pr, int flag)
{
	char readbuf[256];
	double dat1;
	OSErr err;
	short i;
	short pathRefNum;
	FileIO *fs_dfile;
	
	switch(flag){
		case TDR_READ_STD:
			fs_dfile = &(pr->fs_dfile1); break;
		case TDR_READ_CAL:
			fs_dfile = &(pr->fs_dfile2); break;
		case TDR_READ_SAMPLE:
			fs_dfile = &(pr->fs_dfile3); break;
		default:
			return -1;
	}

	if(!fs_dfile->sfr.sfGood){	// file not selected.....
		TDR_freaderr_show(TDR_FERR_NOFILE);
		return TDR_FERR_NOFILE;
	}
	err = FSpOpenDF(&(fs_dfile->fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, fs_dfile) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin readHP54750A data",NULL,NULL);
		return -1;
	}

	i = 0;
	while(1){
		err = Read1Line(fs_dfile, readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%le", &dat1) != 1){
			// ファイルはおおむねデータが１行おきに入っているが、たまに１行空いてない
			// ことがある。メールによるMIME encode/decodeのエラーなのか、変換時のエラー
			// なのかは不明。とりあえずデータの無い行はとばして最後まで読み切る。
			continue;
		}
		switch(flag){
			case TDR_READ_STD:
					*(RS + i) = dat1;
					*(RB + i) = dat1;
					break;
			case TDR_READ_CAL:
					*(RC + i) = dat1;
					break;
			case TDR_READ_SAMPLE:
					*(RX + i) = dat1;
					break;
		}
		
		i++;
		if(i == N_DATA) break;  /* overflow check */
		
	}
	pr->n_rawdata = i;
	
	switch(flag){
		case TDR_READ_STD:
			pr->n_raw_std = i; break;
		case TDR_READ_CAL:
			pr->n_raw_cal = i; break;
		case TDR_READ_SAMPLE:
			pr->n_raw_sample = i; break;
	}

	CloseFileIO(fs_dfile);
	return TDR_FERR_NOERR;
}

/******************* Agilent 86100B(verbose)のデータファイルを読む ********************************/
// 阪大対応版2003/04/22
// read1?とは違う方針で、読み込みフラグによって処理を振り分ける
// read1ナントカもこれと同じに直すべきだが、これはまたの機会にする
// flag : TDR_READ_STD | TDR_READ_CAL | TDR_READ_SAMPLE
// １つづつ読み込むときは、Dfile1が標準、Dfile2がDC（あれば）、Dfile3が未知資料
// 時間軸無し
static short read86100BV(TDR_PARAMETER *pr, int flag)
{

	char readbuf[256];
	double dat1;
	OSErr err;
	short i;
	short pathRefNum;
	FileIO *fs_dfile;
	
	switch(flag){
		case TDR_READ_STD:
			fs_dfile = &(pr->fs_dfile1); break;
		case TDR_READ_CAL:
			fs_dfile = &(pr->fs_dfile2); break;
		case TDR_READ_SAMPLE:
			fs_dfile = &(pr->fs_dfile3); break;
		default:
			return -1;
	}

	if(!fs_dfile->sfr.sfGood){	// file not selected.....
		TDR_freaderr_show(TDR_FERR_NOFILE);
		return TDR_FERR_NOFILE;
	}
	err = FSpOpenDF(&(fs_dfile->fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, fs_dfile) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read86100B(verbose) data",NULL,NULL);
		return -1;
	}

	// verbose形式の場合はヘッダにpreamble情報がある。TDR.h中に宣言したglobalのTDR_PREAMBLE pre中に測定条件の情報を読み込む。
	read86100BV_preamble(fs_dfile, &pre);

	i = 0;
	while(1){
		err = Read1Line(fs_dfile, readbuf, 256);
		if(err == eofErr) break;
		if(sscanf(readbuf, "%lE", &dat1) != 1){
			// ファイルはおおむねデータが１行おきに入っているが、たまに１行空いてない
			// ことがある。メールによるMIME encode/decodeのエラーなのか、変換時のエラー
			// なのかは不明。とりあえずデータの無い行はとばして最後まで読み切る。
			continue;
		}
		switch(flag){
			case TDR_READ_STD:
					*(RS + i) = dat1;
					*(RB + i) = dat1;
					break;
			case TDR_READ_CAL:
					*(RC + i) = dat1;
					break;
			case TDR_READ_SAMPLE:
					*(RX + i) = dat1;
					break;
		}
		
		i++;
		if(i == N_DATA) break; 
		
	}
	pr->n_rawdata = i;
	
	switch(flag){
		case TDR_READ_STD:
			pr->n_raw_std = i; break;
		case TDR_READ_CAL:
			pr->n_raw_cal = i; break;
		case TDR_READ_SAMPLE:
			pr->n_raw_sample = i; break;
	}

	CloseFileIO(fs_dfile);
	return TDR_FERR_NOERR;










}

// 86100Bのverbose modeでは，テキストファイルの最初にprembleが書き込まれる。
static short read86100BV_preamble(FileIO *fs, TDR_PREAMBLE *pre)
{

	char readbuf[256];
	char *dataptr;
	short err;

	if(strstr(readbuf, "Type:") != NULL){
		// void
	}
	else if(strstr(readbuf, "Points:") != NULL){
		sscanf(dataptr, "%d", pre->points);
	}
	else if(strstr(readbuf, "Count:") != NULL){
		sscanf(dataptr, "%d", pre->count);
	}
	else if(strstr(readbuf, "XInc:") != NULL){
		sscanf(dataptr, "%lE", pre->xincrement);
	}
	else if(strstr(readbuf, "XOrg:") != NULL){
		//void
	}
	else if(strstr(readbuf, "YData range:") != NULL){
		//void
	}
	else if(strstr(readbuf, "YData center:") != NULL){
		//void
	}
	else if(strstr(readbuf, "Coupling:") != NULL){
		// void
	}
	else if(strstr(readbuf, "XRange:") != NULL){
		// void
	}
	else if(strstr(readbuf, "XOffset:") != NULL){
		sscanf(dataptr, "%lE", pre->xorigin);
	}
	else if(strstr(readbuf, "YRange:") != NULL){
		sscanf(dataptr, "%lE", pre->yrange);
	}
	else if(strstr(readbuf, "YOffset:") != NULL){
		sscanf(dataptr, "%lE", pre->yorigin);
	}
	else if(strstr(readbuf, "Date:") != NULL){
		//void
	}
	else if(strstr(readbuf, "Time:") != NULL){
		//void
	}
	else if(strstr(readbuf, "Frame:") != NULL){
		//void
	}
	else if(strstr(readbuf, "X Units:") != NULL){
		//void
	}
	else if(strstr(readbuf, "Y Units:") != NULL){
		//void
	}

	pre->format = 0;
	pre->type   = 0;
	pre->xreference = (double)0;
	pre->yreference = (double)0;
	
	return 0;

}


/********************** 東海大学のデータフォーマットを読む **************************/
// 未知試料のシグナルと、リファレンス。
// DC補正が必要な場合は、DCのあるリファレンス（食塩水など）と試料の組み合わせになる
static short read2sampleT(TDR_PARAMETER *pr) 	
{
	char readbuf[256];
	double dt, fact1, fact2;	/* for file header */
	double d1, d2, d3, d4, d5, d6, d7, d8;
	OSErr err;
	short i, j;
	short pathRefNum;
	
	if(!pr->fs_dfile1.sfr.sfGood){	// file not selected.....
		TDR_freaderr_show(TDR_FERR_NOFILE);
		return TDR_FERR_NOFILE;
	}
	//err = DataFileOpen(&(pr->fs_dfile1), fsRdPerm, '\?\?\?\?','\?\?\?\?');
	err = FSpOpenDF(&(pr->fs_dfile1.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile1)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	// read sampling interval
	err = Read1Line(&(pr->fs_dfile1), readbuf, 256);

	if(err == eofErr) return err;
	if(sscanf(readbuf, "%le", &dt) != 1){
		CloseFileIO(&(pr->fs_dfile1));
		TDR_freaderr_show(TDR_FERR_FSTRC);
		return TDR_FERR_FSTRC;
	}
	pr->dt = dt;	/* set time interval */

	// read scale factor of data1
	err = Read1Line(&(pr->fs_dfile1), readbuf, 256);
	if(err == eofErr) return err;;
	if(sscanf(readbuf, "%le", &fact1) != 1){
		CloseFileIO(&(pr->fs_dfile1));
		TDR_freaderr_show(TDR_FERR_FSTRC);
		return TDR_FERR_FSTRC;
	}
	// read scale factor of data2
	err = Read1Line(&(pr->fs_dfile1), readbuf, 256);
	if(err == eofErr) return err;
	if(sscanf(readbuf, "%le", &fact2) != 1){
		CloseFileIO(&(pr->fs_dfile1));
		TDR_freaderr_show(TDR_FERR_FSTRC);
		return TDR_FERR_FSTRC;
	}

	// reading data...
	i = 0;	/* index of array */
	for(j = 0 ; j < 128 ; j++){
		err = Read1Line(&(pr->fs_dfile1), readbuf, 256);
		if(err == eofErr) return err;
		if(sscanf(readbuf, "%le %le %le %le %le %le %le %le",
			&d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8) != 8){
			CloseFileIO(&(pr->fs_dfile1));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		*(RS + i) = d1; i++;	*(RS + i) = d2; i++;	*(RS + i) = d3; i++;	*(RS + i) = d4; i++;
		*(RS + i) = d5; i++;	*(RS + i) = d6; i++;	*(RS + i) = d7; i++;	*(RS + i) = d8; i++;
	}

	i = 0;	/* index of array */
	for(j = 0 ; j < 128 ; j++){
		err = Read1Line(&(pr->fs_dfile1), readbuf, 256);
		if(err == eofErr) return err;
		if(sscanf(readbuf, "%le %le %le %le %le %le %le %le",
			&d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8) != 8){
			CloseFileIO(&(pr->fs_dfile1));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		*(RX + i) = d1; i++;	*(RX + i) = d2; i++;	*(RX + i) = d3; i++;	*(RX + i) = d4; i++;
		*(RX + i) = d5; i++;	*(RX + i) = d6; i++;	*(RX + i) = d7; i++;	*(RX + i) = d8; i++;
	}
	CloseFileIO(&(pr->fs_dfile1));
	pr->n_rawdata = i;

	// and make time axis
	for(i = 0 ; i < pr->n_rawdata ; i++){
		*(TA + i) = dt * (double)i;
	}

	return TDR_FERR_NOERR;
}

// これが使われるのはDC補正が必要なときのみ
// データはDCのないリファレンスとDCをのせたリファレンスの組になる
static short read2calT(TDR_PARAMETER *pr) 	
{
	char readbuf[256];
	double dt, fact1, fact2;	/* for file header */
	double d1, d2, d3, d4, d5, d6, d7, d8;
	OSErr err;
	short i, j;
	short pathRefNum;
		
	if(!pr->fs_dfile2.sfr.sfGood){	// file not selected.....
		return TDR_FERR_NOERR;
	}
	err = FSpOpenDF(&(pr->fs_dfile2.fss), fsRdPerm, &pathRefNum);
	if(err != noErr) return err;
	if(SetUpFileIO(pathRefNum, fsRdPerm, &(pr->fs_dfile2)) != 0){
		showmsgs("\pCan't alloc memory for buffer of input file", "\pin read3data",NULL,NULL);
		return -1;
	}
	// read sampling interval
	err = Read1Line(&(pr->fs_dfile2), readbuf, 256);
	if(err == eofErr) return err;
	if(sscanf(readbuf, "%le", &dt) != 1){
		CloseFileIO(&(pr->fs_dfile2));
		TDR_freaderr_show(TDR_FERR_FSTRC);
		return TDR_FERR_FSTRC;
	}
	
	if(dt != pr->dt){
		CloseFileIO(&(pr->fs_dfile2));
		TDR_freaderr_show(TDR_FERR_TDOM);
		return TDR_FERR_TDOM;
	}
	
	// read scale factor of data1
	err = Read1Line(&(pr->fs_dfile2), readbuf, 256);
	if(err == eofErr) return err;
	if(sscanf(readbuf, "%le", &fact1) != 1){
		CloseFileIO(&(pr->fs_dfile2));
		TDR_freaderr_show(TDR_FERR_FSTRC);
		return TDR_FERR_FSTRC;
	}
	// read scale factor of data2
	err = Read1Line(&(pr->fs_dfile2), readbuf, 256);
	if(err == eofErr) return err;
	if(sscanf(readbuf, "%le", &fact2) != 1){
		CloseFileIO(&(pr->fs_dfile2));
		TDR_freaderr_show(TDR_FERR_FSTRC);
		return TDR_FERR_FSTRC;
	}

	// reading data...
	i = 0;	/* index of array */
	for(j = 0 ; j < 128 ; j++){
		err = Read1Line(&(pr->fs_dfile2), readbuf, 256);
		if(err == eofErr) return err; 
		if(sscanf(readbuf, "%le %le %le %le %le %le %le %le",
			&d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8) != 8){
			CloseFileIO(&(pr->fs_dfile2));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		*(RB + i) = d1; i++;	*(RB + i) = d2; i++;	*(RB + i) = d3; i++;	*(RB + i) = d4; i++;
		*(RB + i) = d5; i++;	*(RB + i) = d6; i++;	*(RB + i) = d7; i++;	*(RB + i) = d8; i++;
	}

	i = 0;	/* index of array */
	for(j = 0 ; j < 128 ; j++){
		err = Read1Line(&(pr->fs_dfile2), readbuf, 256);
		if(err == eofErr) return err;
		if(sscanf(readbuf, "%le %le %le %le %le %le %le %le",
			&d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8) != 8){
			CloseFileIO(&(pr->fs_dfile2));
			TDR_freaderr_show(TDR_FERR_FSTRC);
			return TDR_FERR_FSTRC;
		}
		*(RC + i) = d1; i++;	*(RC + i) = d2; i++;	*(RC + i) = d3; i++;	*(RC + i) = d4; i++;
		*(RC + i) = d5; i++;	*(RC + i) = d6; i++;	*(RC + i) = d7; i++;	*(RC + i) = d8; i++;
	}
	CloseFileIO(&(pr->fs_dfile2));
	return TDR_FERR_NOERR;
}

/*********************** エラー表示共通ルーチン **************************/
// show error messages about file read error
static void TDR_freaderr(unsigned char *str0, unsigned char *str1, unsigned char *str2, unsigned char *str3)
{
	InitCursor();
	ParamText((unsigned char *)str0,
	          (unsigned char *)str1,
			  (unsigned char *)str2,
			  (unsigned char *)str3);
	Alert(TDR_ALERT_FREAD_ID, NULL);
}

static void TDR_freaderr_show(short errcode)
{
	switch(errcode){
		case TDR_FERR_FSTRC:
			TDR_freaderr("\pIllegal file structure.","\pPlease check your read option","\p","\p");
			break;
		case TDR_FERR_OVFLW:
			TDR_freaderr("\pToo many data in file.","\pSome data was truncated.","\p","\p");
			break;
		case TDR_FERR_TDOM:
			TDR_freaderr("\pTime scale of file1 and file2 are differnet","\p","\p","\p");
			break;
		case TDR_FERR_NOFILE:
			TDR_freaderr("\pPlease exact the file to read.", "\p","\p","\p");
			break;
	}
}

/***************************** データの保存 ******************************/
/* 計算後の複素誘電率スペクトルの保存 */
short TDR_saveSpectr(TDR_PARAMETER *pr)
{
	OSErr err;
	short format;
	char outname[128];
	
	format = tdrenv.output_ftype;

	//Make output file name. Name is depends on Environments
	if(strlen(tdrenv.spfile_basename) != 0){
		if(tdrenv.spfile_startnum >= 0){
			sprintf(outname, "%s%d", tdrenv.spfile_basename, tdrenv.spfile_startnum);
			tdrenv.spfile_startnum++;
		}
		else{
			sprintf(outname, "%s", tdrenv.spfile_basename);
		}
	}
	else{
		strcpy(outname, "Untitled");
	}
	
	if(!pr->fs_spec.sfr.sfGood){
		CustomSaveAs("\pOutput file name", CtoPstr(outname), &(pr->fs_spec.sfr), &format);

		if(!pr->fs_spec.sfr.sfGood) return 1;	// canceled.
	}
	pr->fs_spec.fss =  pr->fs_spec.sfr.sfFile;

	tdrenv.output_ftype = format;	
	switch(format){
		case TDR_FSFLAG_TEXT:
			err = saveSpectrDelimitedText(pr);
			TDR_SaveParmsToResouce(&(pr->fs_spec.fss), pr);
			break;
		case TDR_FSFLAG_IGOR:
			err = saveSpectrIgorWave(pr);
			break;
	}
	pr->fs_spec.sfr.sfGood = false;
	return err;
}


// save space delimited text
short saveSpectrDelimitedText(TDR_PARAMETER *pr)
{
	short i;
	OSErr err;
	char writebuf[256];
	short pathRefNum;

	FSpDelete(&(pr->fs_spec.fss)); // if file arelady exists, delete it.
	err = FSpCreate(&(pr->fs_spec.fss),'TDRS','TEXT', smSystemScript);
	if(err != noErr && err != dupFNErr){ 
		FMError(err);
	}
	err = FSpOpenDF(&(pr->fs_spec.fss), fsWrPerm, &pathRefNum);
	if(err != noErr){
		FMError(err);
	}
	if(SetUpFileIO(pathRefNum, fsWrPerm, &(pr->fs_spec)) != 0){
		showmsgs("\pCan't alloc memory for buffer of output file", NULL,NULL,NULL);
		ExitToShell();
	}

	for(i = 0 ; i < pr->n_spec ; i++){
		sprintf(writebuf, "% 5.3e  % 8.6e  % 8.6e  % 8.6e  % 3.3d\n", 
				*(lfa + i), real(*(spect + i)), imag(*(spect + i)), *(calimag + i), *(n_it + i));
		err = Write1Line(&(pr->fs_spec), writebuf,256);
		if(err != noErr){
			CloseFileIO(&(pr->fs_spec));
			FMError(err);
			return err;
		}
	}
	CloseFileIO(&(pr->fs_spec));

	TDR_saveIcon(&(pr->fs_spec), 203);	// ファイルにアイコンをつける
	pr->fs_spec.sfr.sfGood = false;
	
	return 0;
}

// save as Igor wave file.
// processing parameters are in the wave note of the real part.
short saveSpectrIgorWave(TDR_PARAMETER *pr)
{
	short i;
	OSErr err;
	char writebuf[256], vtmp[256], nname_r[128], nname_i[128];
	short pathRefNum;

	FSpDelete(&(pr->fs_spec.fss));	// if file arelady exists, delete it.

	err = FSpCreate(&(pr->fs_spec.fss), TDR_CIGOR, TDR_FIGOR, smSystemScript);
	if(err != noErr && err != dupFNErr){ 
		FMError(err);
	}
	err = FSpOpenDF(&(pr->fs_spec.fss), fsWrPerm, &pathRefNum);
	if(err != noErr){
		FMError(err);
	}
	if(SetUpFileIO(pathRefNum, fsWrPerm, &(pr->fs_spec)) != 0){
		showmsgs("\pCan't alloc memory for buffer of output file", NULL,NULL,NULL);
		ExitToShell();
	}
	
	// IGOR HEADER
	sprintf(writebuf, "IGOR\n");
	Write1Line(&(pr->fs_spec), writebuf,256);
	/* make wave names */
	if(strlen(tdrenv.spfile_freqbname) != 0 && strlen(tdrenv.spfile_realbname) != 0
	   && strlen(tdrenv.spfile_imagbname)){	// name specified.
		if(tdrenv.wave_startnum >= 0){	// start number is valid.
			if(tdrenv.freqdup_flag == true){ //  add number frequency wave
	   			sprintf(writebuf, "WAVES/D\t%s%d\t%s%d\t%s%d\n",
	   					tdrenv.spfile_freqbname, tdrenv.wave_startnum,
	   					tdrenv.spfile_realbname, tdrenv.wave_startnum,
	   					tdrenv.spfile_imagbname, tdrenv.wave_startnum);
	   			}
	   		else{  // does not add number to frequency wave
	   			sprintf(writebuf, "WAVES/D\t%s\t%s%d\t%s%d\n",
	   					tdrenv.spfile_freqbname,
	   					tdrenv.spfile_realbname, tdrenv.wave_startnum,
	   					tdrenv.spfile_imagbname, tdrenv.wave_startnum);
	   		}
	   		sprintf(nname_r, "%s%d", tdrenv.spfile_realbname, tdrenv.wave_startnum);
	   		sprintf(nname_i, "%s%d", tdrenv.spfile_imagbname, tdrenv.wave_startnum);
	   		tdrenv.wave_startnum += 1;
	   	}
	   	else{ // use wavename only. does not add number.
	   		sprintf(writebuf, "WAVES/D\t%s\t%s\t%s\n",
	   			tdrenv.spfile_freqbname,
	   			tdrenv.spfile_realbname,
	   			tdrenv.spfile_imagbname);
	   		sprintf(nname_r, "%s", tdrenv.spfile_realbname);
	   		sprintf(nname_i, "%s", tdrenv.spfile_imagbname);
	   	}
	}
	else{ // use defaults
		sprintf(writebuf, "WAVES/D\tWAVE_logf\tWAVE_real\tWAVE_imag\n");
	   	sprintf(nname_r, "%s", "WAVE_real");
	   	sprintf(nname_i, "%s", "WAVE_imag");
	}
	
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "BEGIN\n");
	Write1Line(&(pr->fs_spec), writebuf,256);
	
	for(i = 0 ; i < pr->n_spec ; i++){
		if(pr->calibflag == true){	// If DC caliblated, imaginary part is DC subtracted.
			sprintf(writebuf, "\t% 5.3e\t% 8.6e\t% 8.6e\n", 
				*(lfa + i), real(*(spect + i)), *(calimag + i) );
		}
		else{
			sprintf(writebuf, "\t% 5.3e\t% 8.6e\t% 8.6e\n", 
				*(lfa + i), real(*(spect + i)), imag(*(spect + i)) );
		}
		err = Write1Line(&(pr->fs_spec), writebuf,256);
		if(err != noErr){
			CloseFileIO(&(pr->fs_spec));
			FMError(err);
			return err;
		}
	}
	sprintf(writebuf, "END\n");
	Write1Line(&(pr->fs_spec), writebuf,256);
	
	// write parameters to wave note
	/* for real wave */
	sprintf(writebuf, "x Note/K %s\n", nname_r);	Write1Line(&(pr->fs_spec), writebuf,256); // delete notes
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_r, "OPERATOR_NAME:", oinfo.operator_name);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_r, "ACQUISITION_TIME:", oinfo.acquisition_time);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_r, "PROCESSING_TIME:", oinfo.processing_time);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%d;\"\n",nname_r, "STANDARD_INDEX:", pr->id_standard);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_r,"STANDARD_NAME:", StdP[pr->id_standard].name);
	Write1Line(&(pr->fs_spec), writebuf,256);
	for(i = 0 ; i < TDR_EDTI_NUMBER ; i++){
		EPGetContent(&ep, i, vtmp);
		sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_r, ep.item[i].label, vtmp);
		Write1Line(&(pr->fs_spec), writebuf,256);
	}
	/* for imaginary wave */
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_i, "OPERATOR_NAME:", oinfo.operator_name);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_i, "ACQUISITION_TIME:", oinfo.acquisition_time);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_i, "PROCESSING_TIME:", oinfo.processing_time);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%d;\"\n",nname_i, "STANDARD_INDEX:", pr->id_standard);
	Write1Line(&(pr->fs_spec), writebuf,256);
	sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_i,"STANDARD_NAME:", StdP[pr->id_standard].name);
	Write1Line(&(pr->fs_spec), writebuf,256);
	for(i = 0 ; i < TDR_EDTI_NUMBER ; i++){
		EPGetContent(&ep, i, vtmp);
		sprintf(writebuf, "x Note %s, \"%s%s;\"\n",nname_i, ep.item[i].label, vtmp);
		Write1Line(&(pr->fs_spec), writebuf,256);
	}

	CloseFileIO(&(pr->fs_spec));

	return 0;
}


/* 計算パラメータの保存。テキスト形式 */
void TDR_saveParam(TDR_PARAMETER *pr)
{
	OSErr err;
	char buf[256];
	short pathRefNum;

	if(!pr->fs_param.sfr.sfGood){
		StandardPutFile("\pOutput file name", "\pUntitled", &(pr->fs_param.sfr));
		if(!pr->fs_param.sfr.sfGood) return;	// canceled.
	}
	pr->fs_param.fss =  pr->fs_param.sfr.sfFile;

	err = FSpCreate(&(pr->fs_param.fss),'TDRS','TEXT', smSystemScript);
	if(err != noErr && err != dupFNErr){ 
		FMError(err);
	}
	err = FSpOpenDF(&(pr->fs_param.fss), fsWrPerm, &pathRefNum);
	if(err != noErr){
		FMError(err);
	}
	if(SetUpFileIO(pathRefNum, fsWrPerm, &(pr->fs_param)) != 0){
		showmsgs("\pCan't alloc memory for buffer of output file", NULL,NULL,NULL);
		ExitToShell();
	}
	
	sprintf(buf, "%d\n%d\n%d\n%d\n", pr->baseXs, pr->baseXe, pr->cutXs, pr->cutXe);
	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
		CloseFileIO(&(pr->fs_param));  return;
	}
	
	sprintf(buf, "%d\n%d\n%d\n%d\n", pr->baseCs, pr->baseCe, pr->cutCs, pr->cutCe);
	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
		CloseFileIO(&(pr->fs_param)); return;
	}
	
//	sprintf(buf, "%d\n%le\n", pr->id_tdiv, pr->dt);
//	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
//		CloseFileIO(&(pr->fs_param)); return;
//	}
	
	sprintf(buf, "%e\n%e\n", pr->d, pr->gd);
	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
		CloseFileIO(&(pr->fs_param)); return;
	}
	
	sprintf(buf, "%e\n%e\n", pr->gX, pr->gC);
	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
		CloseFileIO(&(pr->fs_param)); return;
	}

	sprintf(buf, "%d\n%e\n", pr->id_standard, pr->temperature);
	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
		CloseFileIO(&(pr->fs_param));  return;
	}

	sprintf(buf, "%e\n%e\n%e\n%e\n", pr->DCf, pr->lfs, pr->lfe, pr->dlf);
	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
		CloseFileIO(&(pr->fs_param));  return;
	}

	sprintf(buf, "%d\n%e\n", pr->limit_nit, pr->condition_done);
	if(Write1Line(&(pr->fs_param), buf, 256) != noErr){
		CloseFileIO(&(pr->fs_param)); return;
	}
	CloseFileIO(&(pr->fs_param));

	TDR_saveIcon(&(pr->fs_param), 201);		// アイコンをつける

	
	pr->fs_param.sfr.sfGood = FALSE;
}


// save refrection data
void write1sample(FileIO *fs, double *xa, double *data1, short n, TDR_PREAMBLE *pre, TDR_OPINFO *oinfo)
{
	short i;
	char buf[256];
	OSErr err;
	short pathRefNum;
	char outname[128];

	//Make output file name. Name is depends on Environments
	if(strlen(tdrenv.rawfile_basename) != 0){
		if(tdrenv.rawfile_startnum >= 0){
			sprintf(outname, "%s%d", tdrenv.rawfile_basename, tdrenv.rawfile_startnum);
			tdrenv.rawfile_startnum++;
		}
		else{
			sprintf(outname, "%s", tdrenv.rawfile_basename);
		}
	}
	else{
		strcpy(outname, "Untitled");
	}

	if(!fs->sfr.sfGood){
		//StandardPutFile("\pOutput file name", "\pUntitled", &(fs->sfr));
		if(!fs->sfr.sfGood) return;	// canceled.
	}
	fs->fss =  fs->sfr.sfFile;

	err = FSpCreate(&(fs->fss),'TDRS','TEXT', smSystemScript);
	if(err != noErr && err != dupFNErr){ 
		FMError(err);
	}
	err = FSpOpenDF(&(fs->fss), fsWrPerm, &pathRefNum);
	if(err != noErr){
		FMError(err);
	}
	if(SetUpFileIO(pathRefNum, fsWrPerm, fs) != 0){
		showmsgs("\pCan't alloc memory for buffer of output file", NULL,NULL,NULL);
		ExitToShell();
	}

	for(i = 0 ; i < n ; i++){
		sprintf(buf, "%e  %e\n", *(xa+i), *(data1+i));
		Write1Line(fs, buf, 256);
	}
	
	CloseFileIO(fs);
	
	TDR_saveIcon(fs, 202);
	TDR_SavePreamble(fs, pre);
	TDR_SaveOPInfo(fs, oinfo);	

	
	fs->sfr.sfGood = false;
}


void write2sample(FileIO *fs, double *xa, double *data1, double *data2, short n, TDR_PREAMBLE *pre, TDR_OPINFO *oinfo)
{
	short i;
	char buf[256];
	OSErr err;
	short pathRefNum;
	char outname[128];

	//Make output file name. Name is depends on Environments
	if(strlen(tdrenv.rawfile_basename) != 0){
		if(tdrenv.rawfile_startnum >= 0){
			sprintf(outname, "%s%d", tdrenv.rawfile_basename, tdrenv.rawfile_startnum);
			tdrenv.rawfile_startnum++;
		}
		else{
			sprintf(outname, "%s", tdrenv.rawfile_basename);
		}
	}
	else{
		strcpy(outname, "Untitled");
	}

	if(!fs->sfr.sfGood){
		//StandardPutFile("\pOutput file name", "\pUntitled", &(fs->sfr));
		if(!fs->sfr.sfGood) return;	// canceled.
	}
	fs->fss =  fs->sfr.sfFile;

	err = FSpCreate(&(fs->fss),'TDRS','TEXT', smSystemScript);
	if(err != noErr && err != dupFNErr){ 
		FMError(err);
	}
	err = FSpOpenDF(&(fs->fss), fsWrPerm, &pathRefNum);
	if(err != noErr){
		FMError(err);
	}
	if(SetUpFileIO(pathRefNum, fsWrPerm, fs) != 0){
		showmsgs("\pCan't alloc memory for buffer of output file", NULL,NULL,NULL);
		ExitToShell();
	}

	for(i = 0 ; i < n ; i++){
		sprintf(buf, "%e  %e  %e\n", *(xa+i), *(data1+i), *(data2+i));
		Write1Line(fs, buf, 256);
	}
	
	CloseFileIO(fs);
	
	TDR_saveIcon(fs, 202);
	TDR_SavePreamble(fs, pre);
	TDR_SaveOPInfo(fs, oinfo);	
	
	fs->sfr.sfGood = false;
}

void write3sample(FileIO *fs, double *xa, double *data1, double *data2, double *data3, short n, TDR_PREAMBLE *pre, TDR_OPINFO *oinfo)
{
	short i;
	char buf[256];
	OSErr err;
	short pathRefNum;
	char outname[128];

	//Make output file name. Name is depends on Environments
	if(strlen(tdrenv.rawfile_basename) != 0){
		if(tdrenv.rawfile_startnum >= 0){
			sprintf(outname, "%s%d", tdrenv.rawfile_basename, tdrenv.rawfile_startnum);
			tdrenv.rawfile_startnum++;
		}
		else{
			sprintf(outname, "%s", tdrenv.rawfile_basename);
		}
	}
	else{
		strcpy(outname, "Untitled");
	}

	if(!fs->sfr.sfGood){
		//StandardPutFile("\pOutput file name", "\pUntitled", &(fs->sfr));
		if(!fs->sfr.sfGood) return;	// canceled.
	}
	fs->fss =  fs->sfr.sfFile;

	err = FSpCreate(&(fs->fss),'TDRS','TEXT', smSystemScript);
	if(err != noErr && err != dupFNErr){ 
		FMError(err);
	}
	err = FSpOpenDF(&(fs->fss), fsWrPerm, &pathRefNum);
	if(err != noErr){    
		FMError(err);
	}
	if(SetUpFileIO(pathRefNum, fsWrPerm, fs) != 0){
		showmsgs("\pCan't alloc memory for buffer of output file", NULL,NULL,NULL);
		ExitToShell();
	}

	for(i = 0 ; i < n ; i++){
		sprintf(buf, "%e  %e  %e  %e\n", 
				*(xa+i), *(data1+i), *(data2+i), *(data3+i));
		Write1Line(fs, buf, 256);
	}
	
	CloseFileIO(fs);
	
	TDR_saveIcon(fs, 202);
	TDR_SavePreamble(fs, pre);
	TDR_SaveOPInfo(fs, oinfo);	

	fs->sfr.sfGood = FALSE;
}

// ファイルにカスタムアイコンをつける
void TDR_saveIcon(FileIO *fs, short id)
{
	Handle ICNH, icsH, icl8H, icl4H, ics8H, ics4H, oldh;
	short refN, applrefN;
	FInfo finfo;

	applrefN = CurResFile();

	ICNH = GetResource('ICN#', id);
	DetachResource(ICNH);
	icsH = GetResource('ics#', id);
	DetachResource(icsH);
	icl8H = GetResource('icl8', id);
	DetachResource(icl8H);
	icl4H = GetResource('icl4', id);
	DetachResource(icl4H);
	ics8H = GetResource('ics8', id);
	DetachResource(ics8H);
	ics4H = GetResource('ics4', id);
	DetachResource(ics4H);

	FSpCreateResFile(&(fs->fss), 'TDRS', 'TEXT', NULL);

	refN = FSpOpenResFile(&(fs->fss), fsWrPerm);
	UseResFile(refN);

#ifndef ICONTEST
	oldh = Get1Resource('ICN#',-16455);
	RMError(ResError());
	if(oldh != nil){	// resource already exists.
		RemoveResource(oldh);
		RMError(ResError());
		ReleaseResource(oldh);
	}
#endif
	AddResource(ICNH, 'ICN#',-16455, "\p");
	WriteResource(ICNH);
	DetachResource(ICNH);

#ifndef ICONTEST
	oldh = Get1Resource('ics#',-16455);
	RMError(ResError());
	if(oldh != nil){	// resource already exists.
		RemoveResource(oldh);
		RMError(ResError());
		ReleaseResource(oldh);
	}
#endif
	AddResource(icsH, 'ics#',-16455, "\p");
	WriteResource(icsH);
	DetachResource(icsH);
	
#ifndef ICONTEST
	oldh = Get1Resource('icl8',-16455);
	RMError(ResError());
	if(oldh != nil){	// resource already exists.
		RemoveResource(oldh);
		RMError(ResError());
		ReleaseResource(oldh);
	}
#endif
	AddResource(icl8H, 'icl8',-16455, "\p");
	WriteResource(icl8H);
	DetachResource(icl8H);

#ifndef ICONTEST
	oldh = Get1Resource('icl4',-16455);
	RMError(ResError());
	if(oldh != nil){	// resource already exists.
		RemoveResource(oldh);
		RMError(ResError());
		ReleaseResource(oldh);
	}
#endif
	AddResource(icl4H, 'icl4',-16455, "\p");
	WriteResource(icl4H);
	DetachResource(icl4H);

#ifndef ICONTEST
	oldh = Get1Resource('ics8',-16455);
	RMError(ResError());
	if(oldh != nil){	// resource already exists.
		RemoveResource(oldh);
		RMError(ResError());
		ReleaseResource(oldh);
	}
#endif
	AddResource(ics8H, 'ics8',-16455, "\p");
	WriteResource(ics8H);
	DetachResource(ics8H);

#ifndef ICONTEST
	oldh = Get1Resource('ics4',-16455);
	RMError(ResError());
	if(oldh != nil){	// resource already exists.
		RemoveResource(oldh);
		RMError(ResError());
		ReleaseResource(oldh);
	}
#endif
	AddResource(ics4H, 'ics4',-16455, "\p");
	WriteResource(ics4H);
	DetachResource(ics4H);

	CloseResFile(refN);

	UseResFile(applrefN);
	
	// set hasCustomIcon flag
	FMError(FSpGetFInfo(&(fs->fss), &finfo));
	finfo.fdFlags |= 0x0400;
	FMError(FSpSetFInfo(&(fs->fss), &finfo));
	
}

// 処理パラメータを、リソースフォークに保存する。
void TDR_SaveParmsToResouce(FSSpec *fss, TDR_PARAMETER *pr)
{
	
	Handle oldh, newh;
	FInfo finfo;
	short refN, applrefN;

	// copy data from TDR_PARAMETER to TDR_PREFS
	newh = NewHandleClear(sizeof(TDR_PREFS));
	(**(TDR_PREFSHandle)newh).baseXs = pr->baseXs; (**(TDR_PREFSHandle)newh).baseXe = pr->baseXe;
	(**(TDR_PREFSHandle)newh).cutXs  = pr->cutXs;  (**(TDR_PREFSHandle)newh).cutXe = pr->cutXe;
	(**(TDR_PREFSHandle)newh).baseCs = pr->baseCs; (**(TDR_PREFSHandle)newh).baseCe = pr->baseCe;
	(**(TDR_PREFSHandle)newh).cutCs  = pr->cutCs;  (**(TDR_PREFSHandle)newh).cutCe = pr->cutCe;
	(**(TDR_PREFSHandle)newh).dt = pr->dt; (**(TDR_PREFSHandle)newh).d = pr->d; (**(TDR_PREFSHandle)newh).gd = pr->gd;
	(**(TDR_PREFSHandle)newh).gX = pr->gX; (**(TDR_PREFSHandle)newh).gC = pr->gC;
	(**(TDR_PREFSHandle)newh).id_standard = pr->id_standard; (**(TDR_PREFSHandle)newh).temperature = pr->temperature;
	(**(TDR_PREFSHandle)newh).DCf = pr->DCf;
	(**(TDR_PREFSHandle)newh).lfs = pr->lfs; (**(TDR_PREFSHandle)newh).lfe = pr->lfe; (**(TDR_PREFSHandle)newh).dlf = pr->dlf;
	strcpy((**(TDR_PREFSHandle)newh).comment, pr->comment);
	(**(TDR_PREFSHandle)newh).limit_nit = pr->limit_nit; (**(TDR_PREFSHandle)newh).condition_done = pr->condition_done;
	(**(TDR_PREFSHandle)newh).calibflag = pr->calibflag; (**(TDR_PREFSHandle)newh).n_rawdata = pr->n_rawdata;
	(**(TDR_PREFSHandle)newh).n_data = pr->n_data; (**(TDR_PREFSHandle)newh).n_cdata = pr->n_cdata; (**(TDR_PREFSHandle)newh).n_spec = pr->n_spec;
	(**(TDR_PREFSHandle)newh).dcx = pr->dcx; (**(TDR_PREFSHandle)newh).dcc = pr->dcc; (**(TDR_PREFSHandle)newh).sbex = pr->sbex; (**(TDR_PREFSHandle)newh).sbec = pr->sbec;
	(**(TDR_PREFSHandle)newh).timebase_points = pr->timebase_points;
	(**(TDR_PREFSHandle)newh).timebase_lasttime = pr->timebase_lasttime;

	applrefN = CurResFile();

	FSpGetFInfo(fss, &finfo);
	FSpCreateResFile(fss, finfo.fdCreator, finfo.fdType, NULL);

	if((refN = FSpOpenResFile(fss, fsRdWrPerm)) != -1){  
		UseResFile(refN);
		oldh = Get1Resource(TDR_PRM_RESTYPE, TDR_PRM_RESID);
		RMError(ResError());
		if(oldh != nil){	// resource already exists.
			RemoveResource(oldh);
			RMError(ResError());
			ReleaseResource(oldh);
		}
		AddResource(newh, TDR_PRM_RESTYPE, TDR_PRM_RESID,"\p");
		RMError(ResError());
		WriteResource((Handle)newh);
		RMError(ResError());
		DetachResource((Handle)newh);
		RMError(ResError());
		ReleaseResource(newh);				
		CloseResFile(refN);
	}
	
	UseResFile(applrefN);
}

// 処理パラメータを、与えられたファイルのリソースフォークから読み出して、
// TDR_PARMSに入れる。
// あらかじめTDR_QueryParamResExistsで存在を確認しておくこと。
void TDR_ReadParmsFromResouce(FSSpec *fss, TDR_PARAMETER *pr)
{
	Handle h;
	short refN, applrefN;

	applrefN = CurResFile();
	if((refN = FSpOpenResFile(fss, fsRdPerm)) != -1){  // resource already exists.
		UseResFile(refN);
		h = Get1Resource(TDR_PRM_RESTYPE, TDR_PRM_RESID);
		if(h == nil){
			TDR_freaderr("\pCannot read parrameters", "\pfrom your data file.",
		             "\p","\p");
			CloseResFile(refN);
			UseResFile(applrefN);
			return;
		}
		pr->baseXs = (**(TDR_PREFSHandle)h).baseXs; pr->baseXe = (**(TDR_PREFSHandle)h).baseXe;
		pr->cutXs  = (**(TDR_PREFSHandle)h).cutXs;  pr->cutXe = (**(TDR_PREFSHandle)h).cutXe;
		pr->baseCs = (**(TDR_PREFSHandle)h).baseCs; pr->baseCe = (**(TDR_PREFSHandle)h).baseCe;
		pr->cutCs  = (**(TDR_PREFSHandle)h).cutCs;  pr->cutCe = (**(TDR_PREFSHandle)h).cutCe;
		pr->dt = (**(TDR_PREFSHandle)h).dt; pr->d = (**(TDR_PREFSHandle)h).d; pr->gd = (**(TDR_PREFSHandle)h).gd;
		pr->gX = (**(TDR_PREFSHandle)h).gX; pr->gC = (**(TDR_PREFSHandle)h).gC;
		pr->id_standard = (**(TDR_PREFSHandle)h).id_standard; pr->temperature = (**(TDR_PREFSHandle)h).temperature;
		pr->DCf = (**(TDR_PREFSHandle)h).DCf;
		pr->lfs = (**(TDR_PREFSHandle)h).lfs; pr->lfe = (**(TDR_PREFSHandle)h).lfe; pr->dlf = (**(TDR_PREFSHandle)h).dlf;
		strcpy(pr->comment, (**(TDR_PREFSHandle)h).comment);
		pr->limit_nit = (**(TDR_PREFSHandle)h).limit_nit; pr->condition_done = (**(TDR_PREFSHandle)h).condition_done;
		pr->calibflag = (**(TDR_PREFSHandle)h).calibflag; pr->n_rawdata = (**(TDR_PREFSHandle)h).n_rawdata;
		pr->n_data = (**(TDR_PREFSHandle)h).n_data; pr->n_cdata = (**(TDR_PREFSHandle)h).n_cdata; pr->n_spec = (**(TDR_PREFSHandle)h).n_spec;
		pr->dcx = (**(TDR_PREFSHandle)h).dcx; pr->dcc = (**(TDR_PREFSHandle)h).dcc; pr->sbex = (**(TDR_PREFSHandle)h).sbex; pr->sbec = (**(TDR_PREFSHandle)h).sbec;
		pr->timebase_points = (**(TDR_PREFSHandle)h).timebase_points;
		pr->timebase_lasttime = (**(TDR_PREFSHandle)h).timebase_lasttime;

		ReleaseResource(h);
		CloseResFile(refN);
		UseResFile(applrefN);
	}

}

// 与えられたファイルのリソースフォークにリソースがあるかどうか
// 確認する。保存されていればtrue,なければfalseを返す
Boolean TDR_QueryResourceExists(FSSpec *fss, ResType theType, short theID)
{
	FInfo finfo;
	short refN, applrefN;
	Handle handle;

	applrefN = CurResFile();

	FSpGetFInfo(fss, &finfo);
	FSpCreateResFile(fss, finfo.fdCreator, finfo.fdType, NULL);
	if((refN = FSpOpenResFile(fss, fsRdPerm)) != -1){ 
		UseResFile(refN);
		handle = Get1Resource(theType, theID);
		RMError(ResError());
		if(handle != nil){
			CloseResFile(refN);
			ReleaseResource(handle);
			UseResFile(applrefN);
			return true;
		}
		CloseResFile(refN);
		UseResFile(applrefN);
	}
	return false;
}



// 測定時の装置側の情報(preamble)をリソースフォークに保存する
void TDR_SavePreamble(FileIO *fs, TDR_PREAMBLE *preamble)
{
	TDR_PREAMBLEHandle phandle;
	short refN, applrefN;

	applrefN = CurResFile();


	refN = FSpOpenResFile(&(fs->fss), fsWrPerm);

	RMError(ResError());
	
	UseResFile(refN);
	RMError(ResError());

	PtrToHand((void *)preamble, (Handle *)&phandle, sizeof(TDR_PREAMBLE));

	AddResource((Handle)phandle, preambleType, preambleID, "\p");
	RMError(ResError());
	
	WriteResource((Handle)phandle);
	RMError(ResError());

	DetachResource((Handle)phandle);
	RMError(ResError());
	
	CloseResFile(refN);
	RMError(ResError());

	DisposeHandle((Handle)phandle);
	
	UseResFile(applrefN);
}

// preambleを読み込む
short TDR_LoadPreamble(FileIO *fs, TDR_PREAMBLE *pre)
{
	TDR_PREAMBLEHandle phandle;
	short refN, applrefN;
	short err;

	applrefN = CurResFile();
	if((refN = FSpOpenResFile(&(fs->fss), fsRdPerm)) == -1){
		TDR_freaderr("\pCannot find any resource", "\pin your data file.",
		             "\p","\p");

		return -1;
	}
	UseResFile(refN);

	phandle = (TDR_PREAMBLEHandle)Get1Resource(preambleType, preambleID);
	err = ResError();
	if(phandle == NULL){
		TDR_freaderr("\pCannot find resource of Preamble in", "\pyour data file.",
		             "\p","\p");

		CloseResFile(refN);
		UseResFile(applrefN);
		return -1;
	}
	
	DetachResource((Handle)phandle);

	CloseResFile(refN);
	UseResFile(applrefN);
	
	pre->format = (**phandle).format;
	pre->type   = (**phandle).type;
	pre->points = (**phandle).points;
	pre->count  = (**phandle).count;
	pre->xincrement = (**phandle).xincrement;
	pre->xorigin    = (**phandle).xorigin;
	pre->xreference = (**phandle).xreference;
	pre->yincrement = (**phandle).yincrement;
	pre->yorigin    = (**phandle).yorigin;
	pre->yreference = (**phandle).yreference;
	pre->yrange     = (**phandle).yrange;
	
	DisposeHandle((Handle)phandle);
	
	return 0;
}

// 測定時の情報をリソースフォークに保存する
void TDR_SaveOPInfo(FileIO *fs, TDR_OPINFO *oinfo)
{
	Handle oldh, newh;
	FInfo finfo;
	short refN, applrefN;

	// copy data from TDR_OPINFO to handle
	newh = NewHandleClear(sizeof(TDR_OPINFO));
	strcpy((**(TDR_OPINFOHandle)newh).operator_name, oinfo->operator_name);
	strcpy((**(TDR_OPINFOHandle)newh).operation_comment, oinfo->operation_comment);
	strcpy((**(TDR_OPINFOHandle)newh).acquisition_time, oinfo->acquisition_time);
	strcpy((**(TDR_OPINFOHandle)newh).processing_time, oinfo->processing_time);

	applrefN = CurResFile();

	FSpGetFInfo(&(fs->fss), &finfo);
	FSpCreateResFile(&(fs->fss), finfo.fdCreator, finfo.fdType, NULL);
	
	if((refN = FSpOpenResFile(&(fs->fss), fsWrPerm)) != -1){
		UseResFile(refN);
		RMError(ResError());
		oldh = Get1Resource(TDR_OPINFO_RESTYPE, TDR_OPINFO_RESID);
		RMError(ResError());
		if(oldh != nil){	// resource already exists.
			RemoveResource(oldh);
			RMError(ResError());
			ReleaseResource(oldh);
		}
		AddResource(newh, TDR_OPINFO_RESTYPE, TDR_OPINFO_RESID, "\p");
		RMError(ResError());
	
		WriteResource((Handle)newh);
		RMError(ResError());

		DetachResource((Handle)newh);
		RMError(ResError());
		ReleaseResource(newh);
		CloseResFile(refN);
	}
	
	UseResFile(applrefN);
}

// 測定情報を読み込む
// エラーメッセージは出さない
short TDR_LoadOPInfo(FileIO *fs, TDR_OPINFO *oinfo)
{
	Handle h;
	short refN, applrefN;
	short err;

	applrefN = CurResFile();
	if((refN = FSpOpenResFile(&(fs->fss), fsRdPerm)) == -1){
		return -1;
	}
	UseResFile(refN);

	h = Get1Resource(TDR_OPINFO_RESTYPE, TDR_OPINFO_RESID);
	err = ResError();
	if(h == nil){
		CloseResFile(refN);
		UseResFile(applrefN);
		return -1;
	}
	
	strcpy(oinfo->operator_name, (**(TDR_OPINFOHandle)h).operator_name);
	strcpy(oinfo->operation_comment, (**(TDR_OPINFOHandle)h).operation_comment);
	strcpy(oinfo->acquisition_time, (**(TDR_OPINFOHandle)h).acquisition_time);
	strcpy(oinfo->processing_time, (**(TDR_OPINFOHandle)h).processing_time);
	
	ReleaseResource(h);	
	CloseResFile(refN);
	UseResFile(applrefN);

	return 0;
}

// preference file IO
short TDR_GetPrefsDate(DateTimeRec *dtr)
{
	FSSpec fss;
	char prefsName[256];
	short vol_ref;
	long dir_id;
	DateTimeRec crdtr;
	
	strcpy(prefsName, TDR_PREFSFILENAME);
	FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vol_ref, &dir_id);
	FSMakeFSSpec(vol_ref, dir_id, CtoPstr(prefsName), &fss);

	return GetFileDateTime(fss, dtr, &crdtr);
	
}

short TDR_WritePrefs(TDR_PARAMETER *pr)
{
	FSSpec fss;
	FInfo finfo;
	char prefsName[256];
	short vol_ref;
	long dir_id;

	strcpy(prefsName, TDR_PREFSFILENAME);	
	FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vol_ref, &dir_id);
	FSMakeFSSpec(vol_ref, dir_id, CtoPstr(prefsName), &fss);

	FSpGetFInfo(&fss, &finfo);
	finfo.fdType = 'pref';
	finfo.fdCreator = 'TDRS';
	FSpSetFInfo(&fss, &finfo);

	TDR_SetParamToStruct(&ep, pr);
	TDR_SaveParmsToResouce(&fss, pr);

	return 0;
}

short TDR_ReadPrefs(TDR_PARAMETER *pr)
{
	FSSpec fss;
	char prefsName[256];
	short vol_ref;
	long dir_id;
	
	strcpy(prefsName, TDR_PREFSFILENAME);
	FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vol_ref, &dir_id);
	FSMakeFSSpec(vol_ref, dir_id, CtoPstr(prefsName), &fss);

	if(TDR_QueryResourceExists(&fss, TDR_PRM_RESTYPE,TDR_PRM_RESID) == false){ // no preference file
		return -1;
	}

	TDR_ReadParmsFromResouce(&fss, pr);

	TDR_SetParamToEditPanel(&ep, pr);	// refresh parameter window

	return 0;
}

short TDR_WriteEnv(TDR_ENV *env)
{
	FSSpec fss;
	FInfo finfo;

	char prefsName[256];
	short vol_ref;
	long dir_id;

	strcpy(prefsName, TDR_PREFSFILENAME);	
	FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vol_ref, &dir_id);
	FSMakeFSSpec(vol_ref, dir_id, CtoPstr(prefsName), &fss);

	FSpGetFInfo(&fss, &finfo);
	finfo.fdType = 'pref';
	finfo.fdCreator = 'TDRS';
	FSpSetFInfo(&fss, &finfo);

	TDR_SaveEnvToResouce(&fss, env);

	return 0;
}

short TDR_ReadEnv(TDR_ENV *env)
{
	FSSpec fss;
	char prefsName[256];
	short vol_ref;
	long dir_id;
	
	strcpy(prefsName, TDR_PREFSFILENAME);
	FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &vol_ref, &dir_id);
	FSMakeFSSpec(vol_ref, dir_id, CtoPstr(prefsName), &fss);

	if(TDR_QueryResourceExists(&fss, TDR_ENV_RESTYPE,TDR_ENV_RESID) == true){ // no preference file
		TDR_ReadEnvFromResouce(&fss, env);
		GPIBAddress = atoi(env->GPIB_addr);
		return 0;
	}
	else{	// set default values.
		strcpy(env->GPIB_addr, TDR_DEFAULT_GPIBADDR);
		GPIBAddress = atoi(env->GPIB_addr);
		env->input_ftype = TDR_DEFAULT_IFTYPE;
		env->output_ftype = TDR_DEFAULT_OFTYPE;
		return -1;
	}
}


// Write Enviroments
void TDR_SaveEnvToResouce(FSSpec *fss, TDR_ENV *env)
{
	
	Handle oldh, newh;
	FInfo finfo;
	short refN, applrefN;

	// copy data from TDR_PARAMETER to TDR_PREFS
	newh = NewHandleClear(sizeof(TDR_ENV));
	strcpy((**(TDR_ENVHandle)newh).GPIB_addr, env->GPIB_addr); 
	(**(TDR_ENVHandle)newh).input_ftype = env->input_ftype;
	(**(TDR_ENVHandle)newh).output_ftype = env->output_ftype;
	strcpy((**(TDR_ENVHandle)newh).rawfile_basename, env->rawfile_basename); 
	strcpy((**(TDR_ENVHandle)newh).rawfile_pathname, env->rawfile_pathname); 
	(**(TDR_ENVHandle)newh).rawfile_vRefNum = env->rawfile_vRefNum;
	(**(TDR_ENVHandle)newh).rawfile_parID = env->rawfile_parID;
	(**(TDR_ENVHandle)newh).rawfile_startnum = env->rawfile_startnum;
	strcpy((**(TDR_ENVHandle)newh).spfile_basename, env->spfile_basename); 
	strcpy((**(TDR_ENVHandle)newh).spfile_pathname, env->spfile_pathname); 
	(**(TDR_ENVHandle)newh).spfile_vRefNum = env->spfile_vRefNum;
	(**(TDR_ENVHandle)newh).spfile_parID = env->spfile_parID;
	(**(TDR_ENVHandle)newh).spfile_startnum = env->spfile_startnum;
	strcpy((**(TDR_ENVHandle)newh).spfile_freqbname, env->spfile_freqbname); 
	strcpy((**(TDR_ENVHandle)newh).spfile_realbname, env->spfile_realbname); 
	strcpy((**(TDR_ENVHandle)newh).spfile_imagbname, env->spfile_imagbname); 
	if(env->numsave_flag == true){
		(**(TDR_ENVHandle)newh).wave_startnum = env->wave_startnum;
	}
	(**(TDR_ENVHandle)newh).freqdup_flag = env->freqdup_flag;
	(**(TDR_ENVHandle)newh).numsave_flag = env->numsave_flag;
	memcpy((**(TDR_ENVHandle)newh).process_mmap, env->process_mmap, sizeof(short)*4);
	memcpy((**(TDR_ENVHandle)newh).process_mmap, env->process_mmap, sizeof(short)*4);

	applrefN = CurResFile();

	FSpGetFInfo(fss, &finfo);
	FSpCreateResFile(fss, finfo.fdCreator, finfo.fdType, NULL);

	if((refN = FSpOpenResFile(fss, fsRdWrPerm)) != -1){  
		UseResFile(refN);
		oldh = Get1Resource(TDR_ENV_RESTYPE, TDR_ENV_RESID);
		RMError(ResError());
		if(oldh != nil){	// resource already exists
			RemoveResource(oldh);
			RMError(ResError());
			ReleaseResource(oldh);
		}
		AddResource(newh, TDR_ENV_RESTYPE, TDR_ENV_RESID,"\p");
		RMError(ResError());
		WriteResource((Handle)newh);
		RMError(ResError());
		DetachResource((Handle)newh);
		RMError(ResError());
		ReleaseResource(newh);				
		CloseResFile(refN);
	}
	
	UseResFile(applrefN);
}

void TDR_ReadEnvFromResouce(FSSpec *fss, TDR_ENV *env)
{
	Handle h;
	short refN, applrefN;

	applrefN = CurResFile();

	if((refN = FSpOpenResFile(fss, fsRdPerm)) != -1){  // resource already exists.
		UseResFile(refN);
		h = Get1Resource(TDR_ENV_RESTYPE, TDR_ENV_RESID);
		RMError(ResError());
		if(h == nil){
			TDR_freaderr("\pCannot read enviroments", "\pfrom preference file.",
		             "\p","\p");
			CloseResFile(refN);
			UseResFile(applrefN);
			return;
		}

		strcpy(env->GPIB_addr, (**(TDR_ENVHandle)h).GPIB_addr);
		env->input_ftype = (**(TDR_ENVHandle)h).input_ftype;
		env->output_ftype = (**(TDR_ENVHandle)h).output_ftype;
		strcpy(env->rawfile_basename, (**(TDR_ENVHandle)h).rawfile_basename);
		strcpy(env->rawfile_pathname, (**(TDR_ENVHandle)h).rawfile_pathname);
		env->rawfile_vRefNum = (**(TDR_ENVHandle)h).rawfile_vRefNum;
		env->rawfile_parID = (**(TDR_ENVHandle)h).rawfile_parID;
		env->rawfile_startnum = (**(TDR_ENVHandle)h).rawfile_startnum;
		strcpy(env->spfile_basename, (**(TDR_ENVHandle)h).spfile_basename);
		strcpy(env->spfile_pathname, (**(TDR_ENVHandle)h).spfile_pathname);
		env->spfile_vRefNum = (**(TDR_ENVHandle)h).spfile_vRefNum;
		env->spfile_parID = (**(TDR_ENVHandle)h).spfile_parID;
		env->spfile_startnum = (**(TDR_ENVHandle)h).spfile_startnum;
		strcpy(env->spfile_freqbname, (**(TDR_ENVHandle)h).spfile_freqbname);
		strcpy(env->spfile_realbname, (**(TDR_ENVHandle)h).spfile_realbname);
		strcpy(env->spfile_imagbname, (**(TDR_ENVHandle)h).spfile_imagbname);
		env->freqdup_flag = (**(TDR_ENVHandle)h).freqdup_flag;
		env->numsave_flag = (**(TDR_ENVHandle)h).numsave_flag;
		if(env->numsave_flag == true){
			env->wave_startnum = (**(TDR_ENVHandle)h).wave_startnum;
		}
		memcpy(env->process_mmap, (**(TDR_ENVHandle)h).process_mmap, sizeof(short)*4);
		memcpy(env->process_mmap, (**(TDR_ENVHandle)h).process_mmap, sizeof(short)*4);

		ReleaseResource(h);
		CloseResFile(refN);
		UseResFile(applrefN);
	}

}
