/*------------------------------------------------------------------------------*
 * File Name: stdio.h															*
 * Creation: CPY 3/1/2001														*
 * Purpose: Origin C header	for basic io functions								*
 * Copyright (c) OriginLab Corp.	2001										*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/

#ifndef _STDIO_H
#define _STDIO_H

#include <common.h> // must always include this
#include <string.h> // most likely you will also need strings

// basic internal functions
#pragma dll(@OK)

/** >Basic I/O
	a simple function to print a string, output will be the current output window, 
	can be the Script Window, the output log or the labtalk console.
	Example:
		string	str = "test";
		out_str(str);	
	Return:
		the number of characters printed
	SeeAlso:
		out_double, out_int
*/
int out_str(LPCSTR lpcstr);

/** >Basic I/O
	a simple function to print an integer, output will be the current output window, 
	can be the Script Window, the output log or the labtalk console.
	Example:
		int	nn = 4;
		out_int("nn = ",nn);	
	Return:
		the number of characters printed
	SeeAlso:
		out_double, out_str
*/
int out_int(LPCSTR lpcstr, int nValue);

/** >Basic I/O
	a simple function to print a double value, output will be the current output window, 
	can be the Script Window, the output log or the labtalk console.
	Example:
		double	vv = sin(3.14);
		out_double("vv = ",vv);	
	Return:
		the number of characters printed
	SeeAlso:
		out_str, out_int
*/
int out_double(LPCSTR lpcstr, double dbValue); 

/** >Basic I/O
	Standard C printf function. Output will be the current output window, can be the Script Window, 
	the output log or the labtalk console.
	Example:
		double vv = cos(3.14);
		int		nn = 45;
		string	str = "Test";
		printf("For str(%s) and nn=%d, vv=%f\n",str, nn, vv);
	SeeAlso:
		string::format
*/
int printf(LPCSTR lpcszFormat, ...);



#ifndef NO_ANSI_FILE


typedef		int  	FILE;
#define		EOF     (-1)

#pragma dll(msvcrt, system)

/** >File I/O
	Return:

		fclose returns 0 if the stream is successfully closed. It return EOF to indicate an error.

	Parameters:

		stream	:Pointer to FILE structure

	Remarks:

		The fclose function closes stream. _fcloseall closes all open streams except stdin, stdout, stderr (and, in MS-DOS®, _stdaux and _stdprn). It also closes and deletes any temporary files created by tmpfile. In both functions, all buffers associated with the stream are flushed prior to closing. System-allocated buffers are released when the stream is closed. Buffers assigned by the user with setbuf and setvbuf are not automatically released.

	Example:
        The following example opens a file named "data" and "data2". It then uses fclose to close "data" and "data2"

		void test_fclose()
		{
			FILE *stream, *stream2;
			
			// Open for read (will fail if file "data" does not exist)
			stream  = fopen( "data", "r" );
			if( stream == NULL )
				printf( "The file 'data' was not opened\n" );
			else
				printf( "The file 'data' was opened\n" );
			
			// Open for write 
			stream2 = fopen( "data2", "w+" );
			if( stream2 == NULL )
				printf( "The file 'data2' was not opened\n" );
			else
				printf( "The file 'data2' was opened\n" );
			
			// Close stream 
			if( fclose( stream ) )
				printf( "The file 'data' was not closed\n" );
			// Close stream2 
			if( fclose( stream2 ) )
				printf( "The file 'data2' was not closed\n" );
		}

	SeeAlso:  
		 fflush, fopen

*/
int 	fclose(FILE * stream);

/** >File I/O
	Return:

	returns a pointer to the open file. A null pointer value indicates an error. 

	Parameters:

		filename	:Filename
		mode		:Type of access permitted

	Remarks:
		This  function opens the file specified by filename. 

		The character string mode specifies the type of access requested for the file, as follows:

		"r"	:Opens for reading. If the file does not exist or cannot be found, the fopen call fails.

		"w"	:Opens an empty file for writing. If the given file exists, its contents are destroyed.

		"a"	:Opens for writing at the end of the file (appending) without removing the EOF marker before writing new data to the file; creates the file first if it doesn’t exist.

		"r+":Opens for both reading and writing. (The file must exist.)

		"w+":Opens an empty file for both reading and writing. If the given file exists, its contents are destroyed.

		"a+":Opens for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete; creates the file first if it doesn’t exist.



	Example:
		
        This following example open files named "data", and "data2". It uses fclose to close "data" and "data2"

		void test_fopen()
		{
			FILE *stream, *stream2;
			
			// Open for read (will fail if file "data" does not exist) 
			stream  = fopen( "data", "r" );
			
			if(stream == NULL )
				printf( "The file 'data' was not opened\n" );
			else
				printf( "The file 'data' was opened\n" );
			
			// Open for write
			stream2 = fopen( "data2", "w+" );
			if(stream2 == NULL )
				printf( "The file 'data2' was not opened\n" );
			else
				printf( "The file 'data2' was opened\n" );
			
			// Close stream 
			if( fclose( stream ) )
				printf( "The file 'data' was not closed\n" );
			
			// Close stream2 
			if( fclose( stream2 ) )
				printf( "The file 'data2' was not closed\n" );
		}
		
	SeeAlso:
		fclose
*/
FILE*  	fopen(const char *	filename, const char *mode);

/** >File I/O
	Return:

		Returns a nonnegative value if it is successful. On an error, fputs returns EOF.

	Parameters:

		str		:Output string
		stream	:Pointer to FILE

	Remarks:

		This function copies string to the output stream at the current position. 


	Example:
		
        The following example use fputs to write a single line to the file FPUTS.out

		void test_fputs()
		{
			FILE *stream;
			
			// Open for write
			stream = fopen( "FPUTS.out", "w+" );
			if( stream == NULL )
				printf( "The file 'data' was not opened\n" );
			else
			{
				fputs( "Hello world from fputs.\n", stream );
				
				// Close stream 
				fclose( stream );
			}
		}
		
		// If a code executed after opening the file and before closing it and the code excution leads
		// to execution error, the file stays open. to avoid such circumstance, one may use a try catch block
		// to assure the file is closed either way. plese check the following code
		
		void test(FILE *ff2)
		{
			FILE *ff;
			ff = fopen("C:\\MyFile3.txt", "w");
			fprintf(ff, "Hello World");
			try
			{
				fprintf(ff2, "Hello World");// ff2 is supplied by caller and could be junk
			}
			catch (int nErrorCode)
			{
				fclose(ff);
				
			}
			fclose(ff);
		}

	SeeAlso:
		fgets 
*/
int		fputs(const char *str, FILE *stream );

/** >File I/O
	Return:
		Returns the number of bytes written. Returns a negative value instead when an output error occurs. 
	Parameters:
		stream	:Pointer to FILE structure
		format	:Format-control string
	Remarks:
		Formats and prints a series of characters and values to the output stream. Each function argument (if any) is converted and output according to the corresponding format specification in format. For fprintf, the format argument has the same syntax and use that it has in printf.
	Example:
        
		The following example uses fprintf to format various data and print it the the file named FPRINTF.OUT.

	void test_fprintf()
	{
		FILE *stream;
		int    i = 10;
		double fp = 1.5;
		char   s[] = "this is a string";
		char   c = '\n';
		
		stream = fopen( "fprintf.out", "w" );
		if(stream == NULL)
			printf( "The file fprintf.out was not opened\n" );;
		fprintf( stream, "%s%c", s, c );
		fprintf( stream, "%d\n", i );
		fprintf( stream, "%f\n", fp );
		fclose( stream );
	}

	SeeAlso:
		fscanf
*/
int 	fprintf(FILE *stream, const char *format, ...);

/** >File I/O
	Return:

		Returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. If an error occurs, or if the end of the file stream is reached before the first conversion, the return value is EOF.

	Parameters:

		stream	:Pointer to FILE structure
		format	:Format-control string

	Remarks:

		Reads data from the current position of stream into the locations given by argument (if any). Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format. format controls the interpretation of the input fields and has the same form and function as the format argument for printf. If copying takes place between strings that overlap, the behavior is undefined.


	Example:
        The following example writes formatted data to a file. It then uses fscanf to read the various data back from the file.

    void test_fscanf()
	{
		FILE *stream;
		long l;
		float fp;
		char s[81];
		char c;
		
		stream = fopen( "fscanf.out", "w+" );
		if( stream == NULL )
			printf( "The file fscanf.out was not opened\n" );
		else
		{
			fprintf( stream, "%s %ld %f%c", "a-string", 
				   65000, 3.14159, 'x' );
				   
			// Set pointer to beginning of file:
			fseek( stream, 0L, SEEK_SET );
			
			// Read data back from file: 
			fscanf( stream, "%s", s );
			fscanf( stream, "%ld", &l );
			fscanf( stream, "%f", &fp );
			fscanf( stream, "%c", &c );
			
			// Output data read: 
			printf( "%s\n", s );
			printf( "%ld\n", l );
			printf( "%f\n", fp );
			printf( "%c\n", c );
			
			fclose( stream );
		}
	}

	SeeAlso:
		fprintf
*/
int 	fscanf(FILE *stream, const char *format , ...);

/** >File I/O
	Return:
		Returns a nonzero value after the first read operation that attempts to read past the end of the file. It returns 0 if the current position is not end of file. There is no error return.
	Parameters:
		stream	:Pointer to FILE
	Remarks:
		The feof routine determines whether the end of stream has been reached. When end of file is reached, read operations return an end-of-file indicator until the stream is closed.
	Example:
		The following example uses feof to indicate when it reaches the end of your current C file. It also checks for errors with ferror.

	void test_feof()
	{
		int  count, total = 0;
		char buffer[100];
		FILE *stream;
		 
		// open your current using C file for read
		stream = fopen( __FILE__, "r" );
		if(stream == NULL )
			printf( "The current C file was not opened\n" );
		
		// Cycle until end of file reached: 
		while( !feof( stream ) )
		{
			// Attempt to read in 10 bytes: 
			count = fread( buffer, sizeof( char ), 100, stream );
			if( ferror( stream ) )
				printf("Read Error");
			
			// Total up actual bytes read 
			total += count;
		}
		
		printf( "Number of bytes read = %d\n", total );
		fclose( stream );
	}

	SeeAlso:
		ferror
*/
int		feof(FILE *stream );

/** >File I/O
	Return:
		If no error has occurred on stream, ferror returns 0. Otherwise, it returns a nonzero value.
	Parameters:
		stream	:Pointer to FILE
	Remarks:
		The ferror routine tests for a reading or writing error on the file associated with stream. If an error has occurred, the error indicator for the stream remains set until the stream is closed or rewound, or until clearerr is called against it.
	Example:
		The following example uses feof to indicate when it reaches the end of your current C file. It also checks for errors with ferror.

	void test_ferror()
	{
		int  count, total = 0;
		char buffer[100];
		FILE *stream;
		 
		// open your current using C file for read
		stream = fopen( __FILE__, "r" );
		if(stream == NULL )
			printf( "The current C file was not opened\n" );
		
		// Cycle until end of file reached: 
		while( !feof( stream ) )
		{
			// Attempt to read in 10 bytes: 
			count = fread( buffer, sizeof( char ), 100, stream );
			if( ferror( stream ) )
				printf("Read Error");
			
			// Total up actual bytes read 
			total += count;
		}
		
		printf( "Number of bytes read = %d\n", total );
		fclose( stream );
	}

	SeeAlso:
		feof, fopen
*/
int		ferror(FILE *stream);

/** >File I/O
	Return:
		fflush returns 0 if the buffer was successfully flushed. The value 0 is also returned in cases in which the specified stream has no buffer or is open for reading only. A return value of EOF indicates an error.
		Note:  If fflush returns EOF, data may have been lost due to a write failure.
	Parameters:
		stream	:Pointer to FILE
	Remarks:
		The fflush function flushes a stream. If the file associated with stream is open for output, fflush writes to that file the contents of the buffer associated with the stream. If the stream is open for input, fflush clears the contents of the buffer. Also, fflush(NULL) flushes all streams opened for output. The stream remains open after the call. fflush has no effect on an unbuffered stream.
		Buffers are normally maintained by the operating system, which determines the optimal time to write the data automatically to disk: when a buffer is full, when a stream is closed, or when a program terminates normally without closing the stream. The commit-to-disk feature of the run-time library lets you ensure that critical data is written directly to disk rather than to the operating-system buffers. Without rewriting an existing program, you can enable this feature by linking the program’s object files with COMMODE.OBJ. In the resulting executable file, calls to _flushall write the contents of all buffers to disk. Only _flushall and fflush are affected by COMMODE.OBJ.
	Example:
	    void test_fflush()
	    {	
			FILE  *stream = fopen("C:\\text.txt", "w+" );
			if( NULL == stream )
			{
				printf("Failed to open file test.txt\n");
				return;
			}
			
			char input[6] = {'h', 'e', 'l', 'l', 'o'};
			
			fwrite( input, sizeof(char), 6, stream );  // Write a string into the file.
				
			fflush(stream);   
			fclose(stream);   //set a breakpoint at this line, use Windows Explorer to open the test.txt, you should be able to see that the string have been written to the file
	    }

	SeeAlso:
		fclose
*/
int		fflush(FILE *stream);

/** >File I/O
	Return:
		fgetc return the character read as an int or return EOF to indicate an error or end of file. 
		Use feof or ferror to distinguish between an error and an end-of-file condition. 
		If a read error occurs, the error indicator for the stream is set.
	Parameters:
		stream	:Pointer to FILE
	Remarks:
		fgetc reads a single character from the current position of a file associated with stream. The function then increments the associated file pointer (if defined) to point to the next character. If the stream is at end of file, the end-of-file indicator for the stream is set. 
	Example:
		The following example uses getc to read the first 80 input characters(or until the end of input) and place them into a string named buffer.

		void test_fgetc()
		{
			FILE *stream;
			char buffer[81];
			int  i, ch;
			
			// Open the current C file to read line from: 
			stream = fopen( __FILE__, "r" );
			if(stream == NULL )
				printf("The current C file cannot be opened");
			
			// Read in first 80 characters and place them in "buffer": 
			ch = fgetc( stream );
			for( i=0; (i < 80 ) && ( feof( stream ) == 0 ); i++ )
			{
				buffer[i] = (char)ch;
				ch = fgetc( stream );
			}
			
			// Add null to end string 
			buffer[i] = '\0';
			printf( "%s\n", buffer );
			fclose( stream );
		}

	SeeAlso:
		fputc
*/
int		fgetc(FILE *stream);

/** >File I/O
	Return:
		Each of these functions returns string. NULL is returned to indicate an error or an end-of-file condition. Use feof or ferror to determine whether an error occurred.
	Parameters:
		str		:Storage location for data
		nLen	:Maximum number of characters to read
		stream	:Pointer to FILE
	Remarks:
		fgets reads a string from the input stream argument and stores it in string. 
		fgets reads characters from the current stream position to and including the 
		first newline character, to the end of the stream, or until the number of 
		characters read is equal to n-1, whichever comes first. The result stored in 
		string is appended with a null character. The newline character, if read, 
		is included in the string. 
	Example:
		The following example uses fgets to display a line from a file and then print out this line

		void test_fgets()
		{
		   FILE *stream;
		   char line[100];
		   stream = fopen( __FILE__, "r" );
		   if(stream != NULL )
		   {
			  if( fgets( line, 100, stream ) == NULL)
				 printf( "fgets error\n" );
			  else
				 printf( "%s", line);
			  fclose( stream );
		   }
		}

	SeeAlso:
		fputs
*/
char*	fgets(char *str, int nLen, FILE *stream);

/** >File I/O
	Return:
		Each of these functions returns the character written. For fputc and _fputchar, a return value of EOF indicates an error. For fputwc and _fputwchar, a return value of WEOF indicates an error.
	Parameters:
		c		:Character to be written
		stream	:Pointer to FILE
	Remarks:
		Each of these functions writes the single character c to a file at the position indicated by the associated file position indicator (if defined) and advances the indicator as appropriate. In the case of fputc and fputwc, the file is associated with stream. If the file cannot support positioning requests or was opened in append mode, the character is appended to the end of the stream. Routine-specific remarks follow.
	Example:
		The following example uses fputc and send a character array to FPUTC.out

		void test_fgetc()
		{
			char strptr1[] = "This is a test of fputc!!\n";
			char *p;
			FILE *stream = fopen( "FPUTC.out", "w+t" );
			if(stream != NULL )
			{
				p = strptr1;
				while( (*p != '\0') && fputc( *(p++), stream ) != EOF ) ;
				fclose(stream)
			}
		}


	SeeAlso:
		fgetc
*/
int		fputc(int c, FILE *stream);

/** >File I/O
	Return:
		fread returns the number of full items actually read, which may be less than count if an error occurs or if the end of the file is encountered before reaching count. Use the feof or ferror function to distinguish a read error from an end-of-file condition. If size or count is 0, fread returns 0 and the buffer contents are unchanged.
	Parameters:
		buffer	:Storage location for data
		size	:Item size in bytes
		count	:Maximum number of items to be read
		stream	:Pointer to FILE
	Remarks:
		The fread function reads up to count items of size bytes from the input stream and stores them in buffer. The file pointer associated with stream (if there is one) is increased by the number of bytes actually read. If the given stream is opened in text mode, carriage return–linefeed pairs are replaced with single linefeed characters. The replacement has no effect on the file pointer or the return value. The file-pointer position is indeterminate if an error occurs. The value of a partially read item cannot be determined.
	Example:
		The following opens a file named FREAD.OUT and writes 25 characters to the file. It then tries to open FREAD.OUT and read in 25 characters.If the attempt succeeds,the program displays the number of actual items read.

		void test_fread()
		{
			FILE *stream;
			char list[30];
			int  i, numread, numwritten;
			
			// Open file in text mode:
			stream = fopen( "fread.out", "w+t" );
			if(stream != NULL )
			{
				for ( i = 0; i < 25; i++ )
					list[i] = (char)('z' - i);
				
				// Write 25 characters to stream 
				numwritten = fwrite( list, sizeof( char ), 25, stream );
				printf( "Wrote %d items\n", numwritten );
				fclose( stream );
			}
			else
				printf( "Problem opening the file\n" );
			
			stream = fopen( "fread.out", "r+t" );
			if(stream != NULL )
			{
				// Attempt to read in 25 characters 
				numread = fread( list, sizeof( char ), 25, stream );
				printf( "Number of items read = %d\n", numread );
				printf( "Contents of buffer = %.25s\n", list );
				fclose( stream );
			}
			else
				printf( "File could not be opened\n" );
		}

	SeeAlso:
		fwrite
*/
size_t  fread(void *buffer, size_t size, size_t count, FILE *stream);

/** >File I/O
	Return:
		If successful, fseek returns 0. Otherwise, it returns a nonzero value. On devices incapable of seeking, 
		the return value is undefined.
	Parameters:
		stream	:Pointer to FILE
		offset	:Number of bytes from origin
		origin	:Initial position
	Remarks:
		The fseek function moves the file pointer (if any) associated with stream to a new location that is offset 
		bytes from origin. The next operation on the stream takes place at the new location. On a stream open for update, 
		the next operation can be either a read or a write. The argument origin must be one of the following constants, 
		defined in COMMON.H:

		SEEK_CUR	:Current position of file pointer
		SEEK_END	:End of file
		SEEK_SET	:Beginning of file

		You can use fseek to reposition the pointer anywhere in a file. The pointer can also be positioned beyond the end 
		of the file. fseek clears the end-of-file indicator and negates the effect of any prior ungetc calls against stream.
		When a file is opened for appending data, the current file position is determined by the last I/O operation, not by 
		where the next write would occur. If no I/O operation has yet occurred on a file opened for appending, the file 
		position is the start of the file. 
		
		For streams opened in text mode, fseek has limited use, because carriage return, linefeed translations can cause fseek 
		to produce unexpected results. The only fseek operations guaranteed to work on streams opened in text mode are: 

			* Seeking with an offset of 0 relative to any of the origin values.
			* Seeking from the beginning of the file with an offset value returned from a call to ftell. 
	Example:
		The following example open the file FSEEK.OUT and moves the pointer to the file's beginning

		void test_fseek()
		{
			FILE *stream;
			char line[81];
			int  result;
			
			stream = fopen( "fseek.out", "w+" );
			if( stream == NULL )
				printf( "The file fseek.out was not opened\n" );
			else
			{
				fprintf( stream, "The fseek begins here: "
							   "This is the file 'fseek.out'.\n" );
				result = fseek( stream, 23L, SEEK_SET);
				if( result )
					printf( "Fseek failed" );
				else
				{
					printf( "File pointer is set to middle of first line.\n" );
					fgets( line, 80, stream );
					printf( "%s", line );
				}
				fclose( stream );
			}
		}


	SeeAlso:
		ftell
*/
int		fseek(FILE *stream, long, int);

/** >File I/O
	Return:
		ftell returns the current file position. The value returned by ftell may not reflect the physical byte offset for streams opened in text mode, because text mode causes carriage return–linefeed translation. Use ftell with fseek to return to file locations correctly. On error, ftell returns –1L and errno is set to one of two constants, defined in ERRNO.H. The EBADF constant means the stream argument is not a valid file-handle value or does not refer to an open file. EINVAL means an invalid stream argument was passed to the function. On devices incapable of seeking (such as terminals and printers), or when stream does not refer to an open file, the return value is undefined.
	Parameters:
		stream	:Pointer to Target FILE
	Remarks:
		The ftell function gets the current position of the file pointer (if any) associated with stream. 
		The position is expressed as an offset relative to the beginning of the stream. Note that when a 
		file is opened for appending data, the current file position is determined by the last I/O operation, 
		not by where the next write would occur. For example, if a file is opened for an append and the last 
		operation was a read, the file position is the point where the next read operation would start, not 
		where the next write would start. (When a file is opened for appending, the file position is moved 
		to end of file before any write operation.) If no I/O operation has yet occurred on a file opened 
		for appending, the file position is the beginning of the file.
	Example:
		The following example opened a file named the current C file for reading and tries to read 100 characters. It then uses ftell to determine the position of the file pointer and displays this position.

		void test_fseek()
		{
			FILE *stream;
			long position;
			char list[100];
			
			stream = fopen( __FILE__, "rb" );
			if(stream != NULL )
			{
				// Move the pointer by reading data: 
				fread( list, sizeof( char ), 100, stream );
				// Get position after read: 
				position = ftell( stream );
				printf( "Position after trying to read 100 bytes: %ld\n",position );
				fclose( stream );
			}
		}

	SeeAlso:
		fseek
*/
long	ftell(FILE *stream);

/** >File I/O
	Return:
		fwrite returns the number of full items actually written, which may be less than count 
		if an error occurs. Also, if an error occurs, the file-position indicator cannot be determined.
	Parameters:
		buffer	:Pointer to data to be written
		size	:Item size in bytes
		count	:Maximum number of items to be written
		stream	:Pointer to FILE
	Remarks:
		The fwrite function writes up to count items, of size length each, from buffer to the output stream. 
		The file pointer associated with stream (if there is one) is incremented by the number of bytes actually 
		written. If stream is opened in text mode, each carriage return is replaced with a carriage-return - linefeed 
		pair. The replacement has no effect on the return value.
	Example:
		The following opens a file named FREAD.OUT and writes 25 characters to the file. It then tries to open FREAD.OUT and read in 25 characters.If the attempt succeeds,the program displays the number of actual items read.

		void test_fread()
		{
			FILE *stream;
			char list[30];
			int  i, numread, numwritten;
			
			// Open file in text mode:
			stream = fopen( "fread.out", "w+t" );
			if(stream != NULL )
			{
				for ( i = 0; i < 25; i++ )
					list[i] = (char)('z' - i);
				
				// Write 25 characters to stream 
				numwritten = fwrite( list, sizeof( char ), 25, stream );
				printf( "Wrote %d items\n", numwritten );
				fclose( stream );
			}
			else
				printf( "Problem opening the file\n" );
			
			stream = fopen( "fread.out", "r+t" );
			if(stream != NULL )
			{
				// Attempt to read in 25 characters 
				numread = fread( list, sizeof( char ), 25, stream );
				printf( "Number of items read = %d\n", numread );
				printf( "Contents of buffer = %.25s\n", list );
				fclose( stream );
			}
			else
				printf( "File could not be opened\n" );
		}

	SeeAlso:
		fread
*/
size_t  fwrite(const void *buffer, size_t size, size_t count, FILE *stream);

#endif // NO_ANSI_FILE


#endif //_STDIO_H

