/*	Copyright Š2006. The Regents of the University of California (Regents). All Rights Reserved. Permission to use, copy, 
*	modify, and distribute this software and its documentation for educational, research, and not-for-profit purposes, 
*	without fee and without a signed licensing agreement, is hereby granted, provided that the above copyright notice, 
*	this paragraph and the following two paragraphs appear in all copies, modifications, and distributions. 
*	Contact The Office of Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, CA 94720-1620, 
*	(510) 643-7201, for commercial licensing opportunities. Created by Evan Sperber, Bustamante Group, 
*	University of California, Berkeley. IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, 
*	INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
*	EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
*	AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED 
*	"AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/

#include "ltFileIO.h"

/////////////////////////////////////////////////////////
int ltFileIO( void* dataRef, int commandParm )
{
	int statusfio = 0;
	pData data = (pData) dataRef;
	
	switch( commandParm )
	{
		case kDataOpen:
		{
			statusfio = openDataFile( data );
			break;
		}
		case kDataWrite:
		{
			statusfio = writeData( data );
			break;
		}
		case kDataClose:
		{
			statusfio = closeDataFile( data );
			break;
		}
		case kPrefWrite:
		{
			statusfio = writePrefFile( data );
			break;
		}
		case kPrefRead:
		{
			statusfio = readPrefFile( data );
			break;
		}
		case kComm:
		{
			statusfio = writeCommentsFile( data );
			break;
		}
		case kCalibRead:
		{
			statusfio = readCalibFile( data );
			break;
		}
		case kSetWriteSpeedSlow:
		{
			statusfio = setWriteSpeedSlow( data );
			break;
		}
		case kSetWriteSpeedFast:
		{
			statusfio = setWriteSpeedFast( data );
			break;
		}
	}
	
	return statusfio;
}

////////////////////////////////////////////////////////////
int openDataFile( void* dataRef )
{	
	char* tempString = (char*)malloc( 128 );
	int statusfio;
	int i;
		
	pData data = (pData)dataRef;
	statusfio = ltFileSelectDialog( data );
	
	data->dFileData.ccOffsetIsSet = 0;
	data->dFileData.ccNumRollover = 0;
	
	if( statusfio == 0 )
	{
		initCommentsFile( data );
		sprintf(tempString,"trapA_Empty_PSD_Sum = %d\n", data->instrument.psdSumEmptyA);
		writeComment (tempString, data);
		sprintf(tempString,"        trapB_Empty_PSD_Sum = %d\n", data->instrument.psdSumEmptyB);
		writeComment (tempString, data);
		sprintf(tempString,"        trapA_Empty_Iris = %d\n", data->instrument.irisEmptyA);
		writeComment (tempString, data);
		sprintf(tempString,"        trapB_Empty_Iris = %d\n", data->instrument.irisEmptyB);
		writeComment (tempString, data);
		sprintf(tempString,"        trapA_Full_PSD_Sum = %d\n", data->instrument.psdSumFullA);
		writeComment (tempString, data);
		sprintf(tempString,"        trapB_Full_PSD_Sum = %d\n", data->instrument.psdSumFullB);
		writeComment (tempString, data);
		sprintf(tempString,"        trapA_Full_Iris = %d\n", data->instrument.irisFullA);
		writeComment (tempString, data);
		sprintf(tempString,"        trapB_Full_Iris = %d\n", data->instrument.irisFullB);
		writeComment (tempString, data);
		
		char* tempPath = (char*)malloc( strlen(data->dFileData.dFilePath) + 5 );
		strcpy( tempPath, data->dFileData.dFilePath );
		strcat( tempPath, "A.txt" );	//for file cycling
		
		fpd = fopen( tempPath, "w" );	//overwrites previously existing file with the same names
		
		memset( tempPath, 0, strlen( tempPath ) );
		
		if( fpd != 0 )
		{
			sprintf( localBuffer, "#Begin Write:\n" );
			
			writeHeader(data);
			fwrite( localBuffer, strlen( localBuffer ), 1, fpd );
			memset( localBuffer, 0, strlen( localBuffer ) );
			
			//initialize variables for file cycle, indexing, and write speed
			localRecentIndex = data->quicktime.recentIndex;
			currrentLocInFileCycle = 0;
			bytesWritten = 0;
			data->dFileData.posFileCycle = 'A';
			ltFileIO( data, kSetWriteSpeedSlow );
			skipLine = 0;
			data->dFileData.currentWriteState = kWritingSlow;
			//==============================================================
		}
		else
		{
			printf( "File cannot be opened.  No data will be written.\n" );
			statusfio = 1;
		}
	}
	
	return statusfio;
}

/////////////////////////////////////////////////////////////////////
void writeHeader( void* dataRef )
{	int i;
	pData data = (pData) dataRef;
	for( i = 0; i < kChannelCount; i++ )
			{
				if( data->dFileData.dFileActiveChannels[i] == 1 )
				{
					if( i == data->dFileData.dFileHighestActiveChannel )	//newline if this is the last active channel
					{
						sprintf( tempBuffer, data->dFileData.dFileChannelString[i] );
						strcat( tempBuffer, "\n" );
						strcat( localBuffer, tempBuffer );
						memset( tempBuffer, 0, strlen( tempBuffer ) );
					}
					else													//tab otherwise
					{
						sprintf( tempBuffer, data->dFileData.dFileChannelString[i] );
						strcat( tempBuffer, "\t" );
						strcat( localBuffer, tempBuffer );
						memset( tempBuffer, 0, strlen( tempBuffer ) );
					}
				}
			}
			

}
////////////////////////////////////////////////////////////////////
int writeData( void* dataRef )
{
	/*The control structure is as follows:
	1.  localRecentIndex is compared with recentIndex to determine the size of the block of data to be written as well
		as whether or not the recent array has rolled over in between the current time and the previous time when this function was called.
	2.  If there has  not been a rollover the cycle counts of the data are analyzed one at a time and compared with the previous cycle count
		(updated locally).  At this point one of two things can happen:
			a.  The two (int)cycle counts/n are equal and so a running sum is taken and localRecentIndex is iterated up.
			b.  The two (int)cycle counts/n are not equal and the previous average is dumped to localBuffer at which point
				the function notifies the user (in the data file) of any data points skipped and a new running sum is begun.
		If, however, there has been a recent array rollover, a and b above are both executed until localRecentIndex == kRecentSize after
		which localRecentIndex is reset to 0 and a and b above are resumed.
		
		If at any time after a write dump numElemRemaining < n (the number of data packets averaged into a data point), 
		localRecentIndex is fixed and control is returned to the calling function.
	3.  localBuffer is dumped to disk and is terminated.  Control is returned to the calling function.
	*/
	pData data = (pData) dataRef;
	
	if( bytesWritten >= data->instrument.userInteger[kMaxDataFileSize].value )
	{
		int statusfio;
		statusfio = cycleFileStream( data );
		
		if( statusfio == 1 )
		{
			printf( "File cycle failed.\n" );
			writeComment("File cycle failed.\n",data);
			data->dFileData.dFileIsOpen = 0;
			data->dFileData.currentWriteState = kNotWriting;
			return 1;
		}
	}
	
	int i;
	int numElemRemaining;
	int n = data->dFileData.n;
	
	int ccToTime = n / 4;	//converts data for display:  n[dp] * 1[s]/4[dp] = [s]
	
	int flag;	//indicates whether or not a recent-array rollover has occurred
	
	int startIndex = localRecentIndex;
	
	if( data->dFileData.ccOffsetIsSet == 0 )	//sets cycle count offset for data file (makes cycle count display (in data file) incriment continuously)
	{
		data->dFileData.ccOffset = (int)data->quicktime.recent[localRecentIndex][0];
		data->dFileData.ccOffsetIsSet = 1;
		data->quicktime.timeMark = 0;  //SBS		
	}
	int prevCC = data->quicktime.recent[localRecentIndex][0];
	
	int numDPAveraged = 1;
	
	float runningSum[kChannelCount];	//stores all averaged and formatted channel data
	//0th element in the cycle count and is formatted to increase continuously by tracking the number of times it has rolled over.  cc is also offset
	//to start counting from 0.
	runningSum[0] = (int)ccToTime * ((int)prevCC / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
	for( i = 1; i < kChannelCount; i++ )
		runningSum[i] = data->quicktime.recent[localRecentIndex][i];

	int numDPSkipped = 0;
	
		
	if( localRecentIndex < data->quicktime.recentIndex )
	{
		numElemRemaining = data->quicktime.recentIndex - localRecentIndex + 1;
		flag = 0;	//no recent-array rollover has occurred
	}
	else if( localRecentIndex > data->quicktime.recentIndex )
	{
		numElemRemaining = (kRecentSize + 1) % ( localRecentIndex - data->quicktime.recentIndex );
		flag = 1;	//a recent-array rollover has occurred
	}
	else
		numElemRemaining = n - 1;
	
	if( numElemRemaining >= n )	//else wait until data-to-be-averaged is a larger block of the recent array
	{
		localRecentIndex++;
		if( flag == 0 )
		{
			for( localRecentIndex; localRecentIndex <= data->quicktime.recentIndex; localRecentIndex++ )	//we dont need to reset localRecentIndex
			{
				if( data->quicktime.recent[localRecentIndex][0] < prevCC )	//check to see if a cycle count rollover has occurred
					data->dFileData.ccNumRollover++;
					
				if( (int)data->quicktime.recent[localRecentIndex][0] / n == (int)prevCC / n )
				{
					runningSum[0] += (int)ccToTime * ((int)data->quicktime.recent[localRecentIndex][0] / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
					for( i = 1; i < kChannelCount; i++ )
						runningSum[i] += data->quicktime.recent[localRecentIndex][i];

					numElemRemaining--;
					numDPAveraged++;
				}
				else
				{	
					if( skipLine != 1 )	//skipLine == 1 only after time resolution is decreased
					{
					for( i = 0; i < kChannelCount; i++ )	//Dumps local data block into write block
					{
						if( data->dFileData.dFileActiveChannels[i] == 1 )
						{
							if( i == data->dFileData.dFileHighestActiveChannel )
							{
								sprintf( tempBuffer, data->dFileData.dFileChannelFormat[i], runningSum[i] / numDPAveraged );
								strcat( tempBuffer, "\n" );
								strcat( localBuffer, tempBuffer );
								memset( tempBuffer, 0, strlen( tempBuffer ) );
							}
							else
							{
								sprintf( tempBuffer, data->dFileData.dFileChannelFormat[i], runningSum[i] / numDPAveraged );
								strcat( tempBuffer, "\t" );
								strcat( localBuffer, tempBuffer );
								memset( tempBuffer, 0, strlen( tempBuffer ) );
							}
						}
					}
					}
					else
						skipLine = 0;
					if( data->quicktime.recent[localRecentIndex][0] < prevCC )	//check to see if lines were skipped but a cycle count rollover has occurred
					{
						numDPSkipped = ((int)(kMaxCycleCount / n) + 1) % (-1 * (int)data->quicktime.recent[localRecentIndex][0] / n - (int)prevCC / n) - 1;
						prevCC = data->quicktime.recent[localRecentIndex][0];
						runningSum[0] = (int)ccToTime * ((int)prevCC / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
						for( i = 1; i < kChannelCount; i++ )
								runningSum[i] = data->quicktime.recent[localRecentIndex][i];
						numElemRemaining--;
						numDPAveraged = 1;
					}
					else	//check to see if lines were skipped but no cycle count rollover has occurred
					{
						numDPSkipped = (int)data->quicktime.recent[localRecentIndex][0] / n - (int)prevCC / n - 1;
						prevCC = data->quicktime.recent[localRecentIndex][0];
						runningSum[0] = (int)ccToTime * ((int)prevCC / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
						for( i = 1; i < kChannelCount; i++ )
								runningSum[i] = data->quicktime.recent[localRecentIndex][i];
						numElemRemaining--;
						numDPAveraged = 1;
					}
					for( i = 0; i < numDPSkipped; i++ )	//print skipped line notifier to user
					{
						sprintf( tempBuffer, "#Skipped\n" );
						strcat( localBuffer, tempBuffer );
						memset( tempBuffer, 0, strlen( tempBuffer ) );
					}
				}
				if( numElemRemaining < n )
					break;
			}
		}
		else
		{
			for( localRecentIndex; localRecentIndex < kRecentSize; localRecentIndex++ )	//localRecentIndex will need to be reset
			{
				if( data->quicktime.recent[localRecentIndex][0] < prevCC )	//check to see if a cycle count rollover has occurred
					data->dFileData.ccNumRollover++;
				
				if( (int)data->quicktime.recent[localRecentIndex][0] / n == (int)prevCC / n )
				{
					runningSum[0] += (int)ccToTime * ((int)data->quicktime.recent[localRecentIndex][0] / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
					for( i = 1; i < kChannelCount; i++ )
						runningSum[i] += data->quicktime.recent[localRecentIndex][i];

					numElemRemaining--;
					numDPAveraged++;
				}
				else
				{	
					if( skipLine != 1 )
					{
					for( i = 0; i < kChannelCount; i++ )	//Dumps local data block into write block
					{
						if( data->dFileData.dFileActiveChannels[i] == 1 )
						{
							if( i == data->dFileData.dFileHighestActiveChannel )
							{
								sprintf( tempBuffer, data->dFileData.dFileChannelFormat[i], runningSum[i] / numDPAveraged );
								strcat( tempBuffer, "\n" );
								strcat( localBuffer, tempBuffer );
								memset( tempBuffer, 0, strlen( tempBuffer ) );
							}
							else
							{
								sprintf( tempBuffer, data->dFileData.dFileChannelFormat[i], runningSum[i] / numDPAveraged );
								strcat( tempBuffer, "\t" );
								strcat( localBuffer, tempBuffer );
								memset( tempBuffer, 0, strlen( tempBuffer ) );
							}
						}
					}
					}
					else
						skipLine = 0;
					if( data->quicktime.recent[localRecentIndex][0] < prevCC )	//check to see if lines were skipped but a cycle count rollover has occurred
					{
						numDPSkipped = ((int)(kMaxCycleCount / n) + 1) % (-1 * (int)data->quicktime.recent[localRecentIndex][0] / n - (int)prevCC / n) - 1;
						prevCC = data->quicktime.recent[localRecentIndex][0];
						runningSum[0] = (int)ccToTime * ((int)prevCC / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
						for( i = 1; i < kChannelCount; i++ )
							runningSum[i] = data->quicktime.recent[localRecentIndex][i];
						numElemRemaining--;
						numDPAveraged = 1;
					}
					else	//check to see if lines were skipped but no cycle count rollover has occurred
					{
						numDPSkipped = (int)data->quicktime.recent[localRecentIndex][0] / n - (int)prevCC / n - 1;
						prevCC = data->quicktime.recent[localRecentIndex][0];
						runningSum[0] = (int)ccToTime * ((int)prevCC / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
						for( i = 1; i < kChannelCount; i++ )
							runningSum[i] = data->quicktime.recent[localRecentIndex][i];
						numElemRemaining--;
						numDPAveraged = 1;
					}
					for( i = 0; i < numDPSkipped; i++ )	//print skipped line notifier to user
					{
						sprintf( tempBuffer, "#Skipped\n" );
						strcat( localBuffer, tempBuffer );
						memset( tempBuffer, 0, strlen( tempBuffer ) );
					}
				}
				if( numElemRemaining < n )	//abort loop if there aren't enough data points remaining in averaging block to be averaged
					break;
			}
			if( numElemRemaining >= n )
			{
				for( localRecentIndex = 0; localRecentIndex <= data->quicktime.recentIndex; localRecentIndex++ )	//recent localRecentIndex
				{
					if( data->quicktime.recent[localRecentIndex][0] < prevCC )	//check to see if a cycle count rollover has occurred
						data->dFileData.ccNumRollover++;
				
					if( (int)data->quicktime.recent[localRecentIndex][0] / n == (int)prevCC / n )
					{
						runningSum[0] += (int)ccToTime * ((int)data->quicktime.recent[localRecentIndex][0] / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
						for( i = 1; i < kChannelCount; i++ )
							runningSum[i] += data->quicktime.recent[localRecentIndex][i];
						numElemRemaining--;
						numDPAveraged++;
					}
					else
					{	
						if( skipLine != 1 )
						{
						for( i = 0; i < kChannelCount; i++ )	//Dumps local data block into write block
						{
							if( data->dFileData.dFileActiveChannels[i] == 1 )
							{
								if( i == data->dFileData.dFileHighestActiveChannel )
								{
									sprintf( tempBuffer, data->dFileData.dFileChannelFormat[i], runningSum[i] / numDPAveraged );
									strcat( tempBuffer, "\n" );
									strcat( localBuffer, tempBuffer );
									memset( tempBuffer, 0, strlen( tempBuffer ) );
								}
								else
								{
									sprintf( tempBuffer, data->dFileData.dFileChannelFormat[i], runningSum[i] / numDPAveraged );
									strcat( tempBuffer, "\t" );
									strcat( localBuffer, tempBuffer );
									memset( tempBuffer, 0, strlen( tempBuffer ) );
								}
							}
						}
						}
						else
							skipLine = 0;
						if( data->quicktime.recent[localRecentIndex][0] < prevCC )	//check to see if lines were skipped but a cycle count rollover has occurred
						{
							numDPSkipped = ((int)(kMaxCycleCount / n) + 1) % (-1 * (int)data->quicktime.recent[localRecentIndex][0] / n - (int)prevCC / n) - 1;
							prevCC = data->quicktime.recent[localRecentIndex][0];
							runningSum[0] = (int)ccToTime * ((int)prevCC / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
							for( i = 1; i < kChannelCount; i++ )
								runningSum[i] = data->quicktime.recent[localRecentIndex][i];
							numElemRemaining--;
							numDPAveraged = 1;
						}
						else	//check to see if lines were skipped but no cycle count rollover has occurred
						{
							numDPSkipped = (int)data->quicktime.recent[localRecentIndex][0] / n - (int)prevCC / n - 1;
							prevCC = data->quicktime.recent[localRecentIndex][0];
							runningSum[0] = (int)ccToTime * ((int)prevCC / n - (int)data->dFileData.ccOffset / n + (int)(kMaxCycleCount * data->dFileData.ccNumRollover) / n);
							for( i = 1; i < kChannelCount; i++ )
								runningSum[i] = data->quicktime.recent[localRecentIndex][i];
							numElemRemaining--;
							numDPAveraged = 1;
						}
						for( i = 0; i < numDPSkipped; i++ )	//print skipped line notifier to user
						{
							sprintf( tempBuffer, "#Skipped\n" );
							strcat( localBuffer, tempBuffer );
							memset( tempBuffer, 0, strlen( tempBuffer ) );
						}
					}
					if( numElemRemaining < n )	//abort loop if there aren't enough data points remaining in averaging block to be averaged
						break;
				}
				
			}
		}
	}
	
	fwrite( localBuffer, strlen( localBuffer ), 1, fpd );
	bytesWritten += strlen( localBuffer );
	memset( localBuffer, 0, strlen( localBuffer ) );
}

////////////////////////////////////////////////
int closeDataFile( void* dataRef )
{
	pData data = (pData) dataRef;
	sprintf( tempBuffer, "#End Write" ); // writes to data file
	fwrite( tempBuffer, strlen( tempBuffer ), 1, fpd );
	memset( tempBuffer, 0, strlen( tempBuffer ) );
	
	writeComment("End Write\n" ,data);	//writes to comments file
	writeCommentsFile(data);

	data->dFileData.currentWriteState = kNotWriting;
	
	fclose( fpd );
	
	data->quicktime.timeMark = 0;
}

////////////////////////////////////////////////////////////SBS
int writePrefFile( void* dataRef )
{
	pData data = (pData) dataRef;
	
	int statusfio;
	int count;
	int i;
	char tempString[1024];
	char bigString[4096] = "";
	
	char* tempPath = (char*)malloc( strlen( data->dFileData.prefFilePath ) );
	strcpy( tempPath, data->dFileData.prefFilePath );
	
	for (count = 0; count < kUserIntSize + kChannelCount + kNWriteStateCount; count++)		// save all userIntegers
		{
			sprintf(tempString, "%s\t%s\t\%i\n",
			"@",		// denotes userInteger
			data->instrument.userInteger[count].label,
			data->instrument.userInteger[count].value);
			strcat( bigString, tempString );
			memset( tempString, 0, strlen( tempString) );
		}

	for( count = 0; count < kUserXYZintSize; count++ )	// append all userXYZintegers
		{	
			sprintf( tempString, "%s\t%s\t%i\t%i\t%i\n", 
					"#",	//denotes userXYZinteger
					data->instrument.userXYZinteger[count].label, 
					data->instrument.userXYZinteger[count].value.x, 
					data->instrument.userXYZinteger[count].value.y,
					data->instrument.userXYZinteger[count].value.z);
			strcat( bigString, tempString );
			memset( tempString, 0, strlen( tempString) );
		}

	for( count = 0; count < kUserFloatSize; count++ )	// append all userFloats
		{	
			sprintf( tempString, "%s\t%s\t%f\n", 
					"$",		// denotes Float
					data->instrument.userFloat[count].label, 
					data->instrument.userFloat[count].value);
			strcat( bigString, tempString );
			memset( tempString, 0, strlen( tempString) );
		}
		for( count = 0; count < kUserXYZfloatSize; count++ )	// append all userXYZfloats
		{	
			sprintf( tempString, "%s\t%s\t%f\t%f\t%f\n", 
					"*",	//denotes userXYZinteger
					data->instrument.userXYZfloat[count].label, 
					data->instrument.userXYZfloat[count].value.x, 
					data->instrument.userXYZfloat[count].value.y,
					data->instrument.userXYZfloat[count].value.z);
			strcat( bigString, tempString );
			memset( tempString, 0, strlen( tempString) );
		}
	
sprintf( tempString, "end\n");		// required as EOF signal
strcat( bigString, tempString );

fpp = fopen( tempPath, "w" );
	if( fpp != 0 )
	{
		statusfio = 0;
		
		fwrite( bigString, strlen( bigString ), 1, fpp );
		fclose( fpp );
		
		memset( bigString, 0, strlen(bigString) );
	}
	else
	{
		statusfio = 1;
		printf( "Cannot open Preferences file.  Preferences not saved.\n" );
	}
		
	return statusfio;
}

///////////////////////////////////////////////////////////////
int readPrefFile( void* dataRef )
{
	pData data = (pData) dataRef;
	
	int statusfio;
	int count;
	int err;
	
	char* tempPath = (char*)malloc( strlen( data->dFileData.prefFilePath ) );
	strcpy( tempPath, data->dFileData.prefFilePath );
	
	char* tString;
	
	fpp = fopen( tempPath, "r" );
	
	if( fpp != 0 )
	{	
		printf("open PREF file\n"); 
		err = 0;
		while (err == 0)	err = readDataLine( data );
		fclose( fpp );
		printf("close PREF file\n");
	}
	else
		printf( "Cannot open PREF file.  Leaving defaults\n" );
	
	return statusfio;
}

///////////////////////////////////////////////////////
int readDataLine( void* dataRef )
// reads in one line, tries to assign values to user variable, and returns 
// assume lines start with code character where @ = integer, # = XYZinteger,   $ = float,   * = XYZfloat
{
	pData data = (pData) dataRef;
	#define TOKEN "\t\n" 
	// these characters considered white-space by strtok procedure
	int i; int j; int k;
	int sign;
	int result;
	float resultf;
	Str255 temp; //a Pascal string
	int cmp; 
	int varIndex;
	char *lineString;
	char *wordString ="";
	lineString = (char*)malloc(256);
	wordString = (char*)malloc(24);

	fgets(lineString, 256, fpp); // gets next section of file up to endLine, not to exceed 256 
	wordString = strtok(lineString, TOKEN); // gets first substring delimited by tokens
	if (wordString == NULL) 
		{ printf("unexpected EOF \n"); return(1); };

	cmp = strcmp( wordString,"@" ); // looking for a userInteger line
	if (cmp == 0 )  // found one
		{
		wordString = strtok(NULL,TOKEN); //get variable name
		varIndex = -1;
		for (i = 0; i < kUserIntSize + kChannelCount + kNWriteStateCount; i++) //find which one
			{cmp = strcmp( wordString, data->instrument.userInteger[i].label);
			if (cmp == 0) varIndex = i;	}
		if (varIndex > -1 ) 
			{
			printf("%s",wordString);
			wordString = strtok(NULL,TOKEN); //get value			
			CopyCStringToPascal(wordString, temp );
			StringToNum( temp, &result );
			data->instrument.userInteger[varIndex].value = result;		
			printf("  %i\n",result);
			}
		else printf("unknown name \n");
		return(0);
		}	// end found "@"

	cmp = strcmp( wordString,"#" ); // looking for a userXYZinteger line
	if (cmp == 0 )  // found one
		{
		wordString = strtok(NULL,TOKEN); //get variable name
		varIndex = -1;
		for (i = 0; i < kUserXYZintSize; i++) //find which one
			{cmp = strcmp( wordString, data->instrument.userXYZinteger[i].label);
			if (cmp == 0) varIndex = i;	}
		if (varIndex > -1 ) 
			{
			printf("%s",wordString);

			wordString = strtok(NULL,TOKEN); //get value.x			
			CopyCStringToPascal(wordString, temp );
			StringToNum( temp, &result );
			data->instrument.userXYZinteger[varIndex].value.x = result;		
			printf("  %i",result);
						
			wordString = strtok(NULL,TOKEN); //get value.y			
			CopyCStringToPascal(wordString, temp );
			StringToNum( temp, &result );
			data->instrument.userXYZinteger[varIndex].value.y = result;			
			printf("  %i",result);
					
			wordString = strtok(NULL,TOKEN); //get value.z			
			CopyCStringToPascal(wordString, temp );
			StringToNum( temp, &result );
			data->instrument.userXYZinteger[varIndex].value.z = result;					
			printf("  %i\n",result);
			} 
		else printf("unknown name \n");
		return(0);
		} // end found "#"

	cmp = strcmp( wordString,"$" ); // looking for userFloat
	if (cmp == 0 )  // found one
		{
		wordString = strtok(NULL,TOKEN); //get variable name
		varIndex = -1;
		for (i = 0; i < kUserFloatSize; i++) //find a match
			{
			cmp = strcmp( wordString, data->instrument.userFloat[i].label);
			if (cmp == 0) varIndex = i;	
			}
		if (varIndex > -1 ) 
			{
			printf("%s",wordString);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;										//SBS
			data->instrument.userFloat[varIndex].value = resultf;	
			printf("   %f\n",resultf);
			} 
		else printf("unknown name \n");
		return(0);
		}// end found "$"

	cmp = strcmp( wordString,"*" ); // looking for a userXYZfloat
	if (cmp == 0 )  // found one
		{
		wordString = strtok(NULL,TOKEN); //get variable name
		varIndex = -1;
		for (i = 0; i < kUserXYZfloatSize; i++) //find which one
			{cmp = strcmp( wordString, data->instrument.userXYZfloat[i].label);
			if (cmp == 0) varIndex = i;	}
		if (varIndex > -1 ) 
			{
			printf("%s",wordString);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;									
			data->instrument.userXYZfloat[varIndex].value.x = resultf;	
			printf("   %f",resultf);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;									
			data->instrument.userXYZfloat[varIndex].value.y = resultf;	
			printf("   %f",resultf);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;									
			data->instrument.userXYZfloat[varIndex].value.z = resultf;	
			printf("   %f\n",resultf);

			} 
		else printf("unknown name \n");
		return(0);
		} // end found "*"

	cmp = strcmp( wordString,"end" ); // looking for end of file
	if (cmp == 0 ) 
		{ printf("end \n"); return(1); };
	
	printf("invalid line identifier \n");
	return(1);  
}

////////////////////////////////////////////////////
int writeCommentsFile( void* dataRef )
{
	pData data = (pData) dataRef;
	char* tempString = malloc( 1024 );
	
	int localRollover = data->dFileData.ccNumRollover;
	
	int ccToTime = data->instrument.nLow / 4;
	
	if( data->cFileData.localCommentsTime < data->quicktime.recent[localRecentIndex][0] )
		localRollover++;
	
	fpc = fopen( data->cFileData.commentsPath, "a" );
	if( fpc != 0 )
	{
		sprintf( tempString, "%i\t", ccToTime * ((int)data->cFileData.localCommentsTime / data->instrument.nLow - (int)data->dFileData.ccOffset / data->instrument.nLow + (int)(kMaxCycleCount * localRollover) / data->instrument.nLow));
		strcat( tempString, data->cFileData.commentsString );
		fwrite( tempString, strlen( tempString ), 1, fpc );
		memset( tempString, 0, strlen( tempString ) );
		memset( data->cFileData.commentsString, 0, strlen( data->cFileData.commentsString ) );
		fclose( fpc );
	}
//	else
//		printf( "Cannot open comments file path.  No user activity will be logged\n" );
		
	data->cFileData.updateCommentsFile = 0;
}

//////////////////////////////////////////////////////
int readCalibFile( void* dataRef )
{
	pData data = (pData) dataRef;
	
	int statusfio;
	int count;
	int err;
	char* tempPath = "/ltCalibration";
	
	char* tString;
	
	fpa = fopen( tempPath, "r" );
	
	if( fpa != 0 )
	{	
		printf("open Calibration file\n"); 
		err = 0;
		while (err == 0)	err = readCalibLine( data );
		fclose( fpa );
		printf("close Calibration file\n");
	}
	else
		printf( "Cannot open Calibration file.  Leaving defaults\n" );
	
	return statusfio;
}

///////////////////////////////////////////////////////
int readCalibLine( void* dataRef )
// reads in one line, tries to assign values to user variable, and returns 
// assume lines start with code character where @ = integer, # = XYZinteger,   $ = float,   * = XYZfloat
{
	pData data = (pData) dataRef;
	#define TOKEN "\t\n" 
	// these characters considered white-space by strtok procedure
	int i; int j; int k;
	int sign;
	int result;
	float resultf;
	Str255 temp; //a Pascal string
	int cmp; 
	int varIndex;
	char *lineString;
	char *wordString ="";
	lineString = (char*)malloc(256);
	wordString = (char*)malloc(15);

	fgets(lineString, 256, fpa); // gets next section of file up to endLine, not to exceed 256 
	wordString = strtok(lineString, TOKEN); // gets first substring delimited by tokens
	if (wordString == NULL) 
		{ printf("unexpected EOF \n"); return(1); };

	cmp = strcmp( wordString,"#" ); // looking for a calibXYZinteger line
	if (cmp == 0 )  // found one
		{
		wordString = strtok(NULL,TOKEN); //get variable name
		varIndex = -1;
		for (i = 0; i < kcalibXYZintSize; i++) //find which one
			{cmp = strcmp( wordString, data->instrument.calibXYZint[i].label);
			if (cmp == 0) varIndex = i;	}
		if (varIndex > -1 ) 
			{
			printf("%s",wordString);

			wordString = strtok(NULL,TOKEN); //get value.x			
			CopyCStringToPascal(wordString, temp );
			StringToNum( temp, &result );
			data->instrument.calibXYZint[varIndex].value.x = result;		
			printf("  %i",result);
						
			wordString = strtok(NULL,TOKEN); //get value.y			
			CopyCStringToPascal(wordString, temp );
			StringToNum( temp, &result );
			data->instrument.calibXYZint[varIndex].value.y = result;			
			printf("  %i",result);
					
			wordString = strtok(NULL,TOKEN); //get value.z			
			CopyCStringToPascal(wordString, temp );
			StringToNum( temp, &result );
			data->instrument.calibXYZint[varIndex].value.z = result;					
			printf("  %i\n",result);
			} 
		else printf("unknown name \n");
		return(0);
		} // end found "#"

	cmp = strcmp( wordString,"$" ); // looking for calibFloat
	if (cmp == 0 )  // found one
		{
		wordString = strtok(NULL,TOKEN); //get variable name
		varIndex = -1;
		for (i = 0; i < kcalibFloatSize; i++) //find a match
			{
			cmp = strcmp( wordString, data->instrument.calibFloat[i].label);
			if (cmp == 0) varIndex = i;	
			}
		if (varIndex > -1 ) 
			{
			printf("%s",wordString);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;										//SBS
			data->instrument.calibFloat[varIndex].value = resultf;	
			printf("   %f\n",resultf);
			} 
		else printf("unknown name \n");
		return(0);
		}// end found "$"


	cmp = strcmp( wordString,"*" ); // looking for a userXYZfloat
	if (cmp == 0 )  // found one
		{
		wordString = strtok(NULL,TOKEN); //get variable name
		varIndex = -1;
		for (i = 0; i < kcalibXYZfloatSize; i++) //find which one
			{cmp = strcmp( wordString, data->instrument.calibXYZfloat[i].label);
			if (cmp == 0) varIndex = i;	}
		if (varIndex > -1 ) 
			{
			printf("%s",wordString);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;									
			data->instrument.calibXYZfloat[varIndex].value.x = resultf;	
			printf("   %f",resultf);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;									
			data->instrument.calibXYZfloat[varIndex].value.y = resultf;	
			printf("   %f",resultf);

			wordString = strtok(NULL,TOKEN);		
			resultf = 0.0; //get float value	
			sign= +1;
			k = strlen(wordString);
			for (i=0; i < strlen(wordString); i++)
				{			//	0=48  1=49  2=50  3=51 ........ 9=57
				j = wordString[i]; // ascii character code of numerals
				if (j > 47) resultf = resultf * 10 + (j - 48);
				if (j == 46) k = i + 1;			// decimalPt=46
				if (j == 45) sign = -1;			// minus sign
				}
			for (i = k; i < strlen(wordString); i++) 
				resultf = resultf / 10;
			resultf = resultf * sign;									
			data->instrument.calibXYZfloat[varIndex].value.z = resultf;	
			printf("   %f\n",resultf);

			} 
		else printf("unknown name \n");
		return(0);
		} // end found "*"
		
	cmp = strcmp( wordString,"?" ); // looking for instrument name
	if (cmp == 0 )  // found one
		{
		data->instrument.deviceName = strtok(NULL,TOKEN); //get variable name
		printf("deviceName = %s\n",data->instrument.deviceName);
		return(0);
		};	

	cmp = strcmp( wordString,"end" ); // looking for end of file
	if (cmp == 0 ) 
		{ printf("end \n"); return(1); };
	
	printf("invalid line identifier \n");
	return(1);  
}

////////////////////////////////////////////////////////////
int setWriteSpeedSlow( void* dataRef )
{
	pData data = (pData) dataRef;
	
	data->dFileData.n = data->instrument.nHigh;
	data->dFileData.currentWriteState = kWritingSlow;
	if( data->quicktime.recent[data->quicktime.recentIndex][0] < data->quicktime.recent[localRecentIndex][0] )
		data->dFileData.ccNumRollover++;
	localRecentIndex = data->quicktime.recentIndex;
	skipLine = 1;	//skip a line write to prevent (apparent) regression of timestamp
	
	return 0;
}

/////////////////////////////////////////////////
int setWriteSpeedFast( void* dataRef )
{
	pData data = (pData) dataRef;
	
	data->dFileData.n = data->instrument.nLow;
	data->dFileData.currentWriteState = kWritingFast;
	//if( data->quicktime.recent[data->quicktime.recentIndex][0] < data->quicktime.recent[localRecentIndex][0] )
	//	data->dFileData.ccNumRollover++;
	//localRecentIndex = data->quicktime.recentIndex;
	
	return 0;
}

/////////////////////////////////////////////////////
int cycleFileStream( void* dataRef )
{
	fclose( fpd );
	pData data = (pData) dataRef;
	
	char* tempFIOPath = (char*)malloc( strlen( data->dFileData.dFilePath ) + 5 );
	//strncpy( tempFIOPath, data->dFileData.dFilePath, strlen( data->dFileData.dFilePath) - 5 ); //strips off A.txt
	strcpy( tempFIOPath, data->dFileData.dFilePath );
	
	int statusfio;
	
	switch( currrentLocInFileCycle )
	{
		case 0:
		{
			currrentLocInFileCycle = 1;
			strcat( tempFIOPath, "B.txt" );
			bytesWritten = 0;
			writeComment("-----------------------switch to file B ---------------------\n", data);
			fpd = fopen( tempFIOPath, "w" );
			printf( "%s\n", tempFIOPath );
			
			if( fpd != 0 )
			{
				statusfio = 0;
				data->dFileData.posFileCycle = 'B';
				writeHeader(data);
			}
			else
				statusfio = 1;
				
			break;
		}
		case 1:
		{
			currrentLocInFileCycle = 2;
			strcat( tempFIOPath, "C.txt" );
			bytesWritten = 0;
			writeComment("-----------------------switch to file C ---------------------\n", data);			
			fpd = fopen( tempFIOPath, "w" );
			printf( "%s\n", tempFIOPath );
			
			if( fpd!= 0 )
			{
				statusfio = 0;
				data->dFileData.posFileCycle = 'C';
				writeHeader(data);
			}
			else
				statusfio = 1;
				
			break;
		}
		case 2:
		{
			currrentLocInFileCycle = 3;
			strcat( tempFIOPath, "D.txt" );
			bytesWritten = 0;
			writeComment("-----------------------switch to file D ---------------------\n", data);			
			fpd = fopen( tempFIOPath, "w" );
			printf( "%s\n", tempFIOPath );
			
			if( fpd != 0 )
			{
				statusfio = 0;
				data->dFileData.posFileCycle = 'D';
				writeHeader(data);
			}
			else
				statusfio = 1;
			
			break;
		}
		case 3:
		{
			currrentLocInFileCycle = 4;
			strcat( tempFIOPath, "E.txt" );
			bytesWritten = 0;
			writeComment("-----------------------switch to file E ---------------------\n", data);			
			fpd = fopen( tempFIOPath, "w" );
			printf( "%s\n", tempFIOPath );
			
			if( fpd != 0 )
			{
				statusfio = 0;
				data->dFileData.posFileCycle = 'E';
				writeHeader(data);
			}
			else
				statusfio = 1;
			
			break;
		}
		case 4:
		{
			currrentLocInFileCycle = 5;
			strcat( tempFIOPath, "F.txt" );
			bytesWritten = 0;
			writeComment("-----------------------switch to file F ---------------------\n", data);			
			fpd = fopen( tempFIOPath, "w" );
			printf( "%s\n", tempFIOPath );
			
			if( fpd != 0 )
			{
				statusfio = 0;
				data->dFileData.posFileCycle = 'F';
				writeHeader(data);
			}
			else
				statusfio = 1;
			
			break;
		}
		case 5:
		{
			currrentLocInFileCycle = 6;
			strcat( tempFIOPath, "G.txt" );
			bytesWritten = 0;
			writeComment("-----------------------switch to file G ---------------------\n", data);			
			fpd = fopen( tempFIOPath, "w" );
			printf( "%s\n", tempFIOPath );
			
			if( fpd != 0 )
			{
				statusfio = 0;
				data->dFileData.posFileCycle = 'G';
				writeHeader(data);
			}
			else
				statusfio = 1;
				
			break;
		}
		case 6:
		{
			currrentLocInFileCycle = 0;
			strcat( tempFIOPath, "A.txt" );
			bytesWritten = 0;
			writeComment("-----------------------switch to file A ---------------------\n", data);			
			fpd = fopen( tempFIOPath, "w" );
			printf( "%s\n", tempFIOPath );
			
			if( fpd != 0 )
			{
				statusfio = 0;
				data->dFileData.posFileCycle = 'A';
				writeHeader(data);
			}
			else
				statusfio = 1;
			
			break;
		}
	}
	
	memset( tempFIOPath, 0, strlen( tempFIOPath ) );
	return statusfio;
}

///////////////////////////////////////////////////
void initCommentsFile( void* dataRef )
{
	pData data = (pData) dataRef;
	data->cFileData.commentsPath = (char*)malloc( strlen( data->dFileData.dFilePath ) + 3 );
	
	memset( data->cFileData.commentsPath, '\0', strlen( data->cFileData.commentsPath ) );
	strcat( data->cFileData.commentsPath, data->dFileData.dFilePath );
	strcat( data->cFileData.commentsPath, "COM.txt" );
	
	char* tempString = (char*)malloc( 128 );
	fpc = fopen( data->cFileData.commentsPath, "w" );
	printf("fpc = %s\n",data->cFileData.commentsPath);
	if( fpc != 0 )
	{
		int i;	
		sprintf( data->cFileData.commentsString, "Instrument name = %s\n",data->instrument.deviceName);

		sprintf( tempString, "*****Calibration values *****\n" );
		strcat( data->cFileData.commentsString, tempString );
		memset( tempString, 0, strlen( tempString ) );

		for( i = 0; i < kcalibFloatSize; i++ )
		{
			sprintf( tempString, "%s\t%f\n", data->instrument.calibFloat[i].label, 
													data->instrument.calibFloat[i].value);
			strcat( data->cFileData.commentsString, tempString );
			memset( tempString, 0, strlen( tempString ) );
		}

		for( i = 0; i < kcalibXYZfloatSize; i++ )
		{
			sprintf( tempString, "%s\t%f\t%f\t%f\n", data->instrument.calibXYZfloat[i].label, 
													data->instrument.calibXYZfloat[i].value.x, 
													data->instrument.calibXYZfloat[i].value.y,
													data->instrument.calibXYZfloat[i].value.z);
			strcat( data->cFileData.commentsString, tempString );
			memset( tempString, 0, strlen( tempString ) );
		}

		for( i = 0; i < kcalibXYZintSize; i++ )	
		{
			sprintf( tempString, "%s\t%i\t%i\t%i\n", data->instrument.calibXYZint[i].label, 
													data->instrument.calibXYZint[i].value.x, 
													data->instrument.calibXYZint[i].value.y,
													data->instrument.calibXYZint[i].value.z);
			strcat( data->cFileData.commentsString, tempString );
			memset( tempString, 0, strlen( tempString ) );
		}

		sprintf( tempString, "*****Initial Preference Settings*****\n" );
		strcat( data->cFileData.commentsString, tempString );
		memset( tempString, 0, strlen( tempString ) );
		for( i = 0; i < kUserIntSize + kChannelCount + kNWriteStateCount; i++ )
		{
			sprintf( tempString, "%s\t%i\n", data->instrument.userInteger[i].label, 
										data->instrument.userInteger[i].value );
			strcat( data->cFileData.commentsString, tempString );
			memset( tempString, 0, strlen( tempString ) );
		}
		for( i = 0; i < kUserXYZintSize; i++ )
		{
			sprintf( tempString, "%s\t%i\t%i\t%i\n", data->instrument.userXYZinteger[i].label, 
													data->instrument.userXYZinteger[i].value.x, 
													data->instrument.userXYZinteger[i].value.y,
													data->instrument.userXYZinteger[i].value.z);
			strcat( data->cFileData.commentsString, tempString );
			memset( tempString, 0, strlen( tempString ) );
		}
		for( i = 0; i < kUserFloatSize; i++ )
		{
			sprintf( tempString, "%s\t%f\n", data->instrument.userFloat[i].label, 
										data->instrument.userFloat[i].value );
			strcat( data->cFileData.commentsString, tempString );
			memset( tempString, 0, strlen( tempString ) );
		}
		for( i = 0; i < kUserXYZfloatSize; i++ )
		{
			sprintf( tempString, "%s\t%f\t%f\t%f\n", data->instrument.userXYZfloat[i].label, 
													data->instrument.userXYZfloat[i].value.x, 
													data->instrument.userXYZfloat[i].value.y,
													data->instrument.userXYZfloat[i].value.z);
			strcat( data->cFileData.commentsString, tempString );
			memset( tempString, 0, strlen( tempString ) );
		}
		sprintf( tempString, "*****End Initial Preference Settings*****\n\n" );
		strcat( data->cFileData.commentsString, tempString );
		memset( tempString, 0, strlen( tempString ) );
		
		sprintf(tempString, "Zero-Force Offsets (pN)  %f\t%f\t%f\n", data->instrument.forceOffset.x,
																data->instrument.forceOffset.y,
																data->instrument.forceOffset.z);
		strcat( data->cFileData.commentsString, tempString );
		memset( tempString, 0, strlen( tempString ) );

		fwrite( data->cFileData.commentsString, strlen( data->cFileData.commentsString ), 1, fpc );
		memset( data->cFileData.commentsString, 0, strlen( data->cFileData.commentsString ) );
		fclose( fpc );
	}
	else
		printf( "Cannot open comments path.  No user activity will be logged\n" );
}	