/*
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 *  SCR_CFil.h
 *  Scripts, Beaudet Christophe
 *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 */
 
#ifndef __SCR_CFil_h__
#define __SCR_CFil_h__
 
#include	<fcntl.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<io.h>
 
/*===============================================================================================*/
 
/*===============================================================================================*/
 
#if defined(SCR_DM_OptCFiles) /*******************************************************************/
 
/*
 *	Description a C file (stream handle).
 */
typedef int		SCR_FILE;
 
/*
 *	Modes for opening files.
 */
#define	SCR_COM_OpenRead	(O_BINARY | O_RDONLY)
#define	SCR_COM_OpenWrite	(O_BINARY | O_WRONLY | O_CREAT | O_TRUNC)
#define	SCR_COM_OpenAppend	(O_BINARY | O_APPEND)
 
/*
 *	Common macros.
 */
#define SCR_M_fopen(_FileName, _Mode)					open(_FileName, _Mode, S_IREAD | S_IWRITE)
#define SCR_M_fclose(_File)								close((_File)->p_stHandle->xHandle)
#define	SCR_M_ftell(_File)								(tell((_File)->p_stHandle->xHandle) - (_File)->p_stHandle->iCnt)
#define SCR_M_feof(_File)								eof((_File)->p_stHandle->xHandle)
#define SCR_M_fread(_Buffer, _Size, _Size1, _File)		read((_File)->p_stHandle->xHandle, _Buffer, _Size1)
#define SCR_M_fwrite(_Buffer, _Size, _Size1, _File)		write((_File)->p_stHandle->xHandle, _Buffer, _Size1)
 
/*
 *	Macro to seek at a given position.
 */
#define	SCR_M_fseek(_File, _Offset, _Origin, _iRes)\
{\
	_iRes = lseek((_File)->p_stHandle->xHandle, _Offset, _Origin);\
	if(_iRes == -1)\
		_iRes = 1;\
	else\
	{\
		_iRes = 0;\
		(_File)->p_stHandle->p_cCurrent = (_File)->p_stHandle->p_cBase;\
		(_File)->p_stHandle->iCnt = 0;\
	}\
}
 
 
/*
 *	Macro to set internal buffer.
 */
#define SCR_M_setvbuf(_File, _Buffer, _Const, _Size)\
{\
	(_File)->p_stHandle->p_cBase = (_File)->p_stHandle->p_cCurrent = _Buffer;\
	(_File)->p_stHandle->iCnt = 0;\
}
 
/*
 *	Macro to set a character.
 */
#define SCR_M_fputc(_Char, _File, _iRes)\
{\
	char _temp_ = _Char;\
	_iRes = write((_File)->p_stHandle->xHandle, &_temp_, 1);\
}
 
/*
 *	Macro to get a character.
 */
#define	SCR_M_fgetc(_File, _Char)\
{\
	if(--(_File)->p_stHandle->iCnt == -1)\
	{\
		(_File)->p_stHandle->iCnt = SCR_M_fread((_File)->p_stHandle->p_cBase, 1, SCR_CV_ui_Cfg_SizeBufferFile, _File);\
		if(((_File)->p_stHandle->iCnt == 0) || ((_File)->p_stHandle->iCnt == -1))\
		{\
			(_File)->p_stHandle->iCnt = 0;\
			_Char = EOF;\
		}\
		else\
		{\
			(_File)->p_stHandle->p_cCurrent = (_File)->p_stHandle->p_cBase;\
			(_File)->p_stHandle->iCnt--;\
			_Char = 0xff & *(_File)->p_stHandle->p_cCurrent++;\
		}\
	}\
	else\
		_Char = 0xff & *(_File)->p_stHandle->p_cCurrent++;\
}
 
#else /* SCR_DM_OptCFiles */ /********************************************************************/
 
/*
 *!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *	C Files are not optimised, so use of FILE * capabilities
 *!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 */
 
/*
 *	Description a C file.
 */
typedef FILE	*SCR_FILE;
 
/*
 *	Modes for opening files.
 */
#define	SCR_COM_OpenRead	"rb"
#define	SCR_COM_OpenWrite	"wb"
#define	SCR_COM_OpenAppend	"ab"
 
/*
 *	Access functions.
 */
#define SCR_M_fopen(_FileName, _Mode)					fopen(_FileName, _Mode)
#define SCR_M_fclose(_File)								fclose((_File)->p_stHandle->xHandle)
#define	SCR_M_ftell(_File)								ftell((_File)->p_stHandle->xHandle)
#define SCR_M_setvbuf(_File, _Buffer, _Const, _Size)	setvbuf((_File)->p_stHandle->xHandle, _Buffer, _Const, _Size)
#define SCR_M_feof(_File)								feof((_File)->p_stHandle->xHandle)
#define SCR_M_fread(_Buffer, _Size, _Size1, _File)		fread(_Buffer, _Size, _Size1, (_File)->p_stHandle->xHandle)
#define SCR_M_fwrite(_Buffer, _Size, _Size1, _File)		fwrite(_Buffer, _Size, _Size1, (_File)->p_stHandle->xHandle)
#define	SCR_M_fseek(_File, _Offset, _Origin, _iRes)		{_iRes = fseek((_File)->p_stHandle->xHandle, _Offset, _Origin);}
#define	SCR_M_fgetc(_File, _Char)						{_Char = fgetc((_File)->p_stHandle->xHandle);}
#define SCR_M_fputc(_Char, _File, _iRes)				{_iRes = fputc(_Char, (_File)->p_stHandle->xHandle); }
 
#endif /* SCR_DM_OptCFiles */ /*******************************************************************/
 
/*
 *	Structure that describes a file.
 */
typedef struct SCR_tdst_File_Handle_
{
	SCR_FILE	xHandle;				/* Handle of file (can be a "FILE *") */
	char		*p_cBase;				/* Base of buffer */
	char		*p_cCurrent;			/* Current pointer */
	int			iCnt;					/* Number of character from p_cBase to end of buffer */
} SCR_tdst_File_Handle;
 
/*
 *  To seek a file to a given position.
 *  _File       :   File to seek.
 *  _Offset     :   Offset to seek.
 *  _Origin     :   SEEK_SET or SEEK_END.
 */
#define SCR_M_File_Seek(_File, _Offset, _Origin)\
{\
    if((_File)->d_stFirstPage != NULL)\
        fn_v_Page_Seek((_File), _Offset, _Origin);\
    else\
    {\
		int	_iRes_;\
		SCR_M_fseek((_File), _Offset, _Origin, _iRes_);\
		if(_iRes_)\
		{\
			SCR_M_Err_UpdateSyntaxError();\
			sprintf\
			(\
				g_st_Err_GlobalError.a_szBufferTmp2,\
				"File is \"%s\".",\
				(_File)->a_szFileName\
			);\
			SCR_M_Err_RaiseError(SCR_EI_Err_ReadFile);\
		}\
    }\
}
 
/*
 *  To close a file.
 *  _File       :   File to close.
 */
#define SCR_M_File_Close(_File)\
{\
    if((_File)->p_stHandle->xHandle != (SCR_FILE) 0)\
    {\
        if(SCR_M_fclose(_File) == EOF)\
        {\
            sprintf(g_st_Err_GlobalError.a_szBufferTmp1, "File is \"%s\".", (_File)->a_szFileName);\
            *g_st_Err_GlobalError.a_szBufferTmp2 = '\0';\
            SCR_M_Err_RaiseError(SCR_EI_Err_CloseFile);\
        }\
        (_File)->p_stHandle->xHandle = (SCR_FILE) 0;\
    }\
}
 
/*
 *  To open a file to read.
 *  To open a file to write.
 *  _Name   :   Name of file.
 */
#define SCR_M_p_x_File_OpenRead(_Name)\
(\
	!access(_Name, 0) ? SCR_M_fopen(_Name, SCR_COM_OpenRead)\
		: (SCR_FILE) 0\
)
#define SCR_M_p_x_File_OpenWrite(_Name)\
(\
	(access(_Name, 0) || !access(_Name, 2) || !chmod(_Name, _S_IWRITE)) ? SCR_M_fopen(_Name, SCR_COM_OpenWrite)\
		: (SCR_FILE) 0\
)
#define SCR_M_p_x_File_OpenAppend(_Name)\
(\
	(!access(_Name, 0) && (!access(_Name, 2) || !chmod(_Name, _S_IWRITE))) ? SCR_M_fopen(_Name, SCR_COM_OpenAppend)\
		: (SCR_FILE) 0\
)
 
#endif /* __SCR_CFil_h__ */
