/****************************************************************************
File    : compress.c
/*
@(#) #SY# Atari800Win PLus
@(#) #IS# Implementation of compression handling API
@(#) #BY# Tomasz Szymankowski
@(#) #LM# 28.08.2002
*/

#include "WinConfig.h"
#include "Resource.h"
#include "Debug.h"
#include "atari800.h"
#include "globals.h"
#include "compress.h"

/* Private objects */

static HANDLE  s_hZlib      = NULL;

/* Zlib starters */

static FARPROC s_pfnGzRead  = NULL;
static FARPROC s_pfnGzOpen  = NULL;
static FARPROC s_pfnGzClose = NULL;
static FARPROC s_pfnGzWrite = NULL;
static FARPROC s_pfnGzError = NULL;


/*========================================================
Function : Compress_LoadLibrary
=========================================================*/
/* #FN#
   Loads dynamically Zlib.dll library */
int
/* #AS#
   0 if suceeded, otherwise a value greater than 0 */
Compress_LoadLibrary(
	PHANDLE pHandle
)
{
	int nResult = 0;

	/* Load ZLIB library */
	if( !s_hZlib )
	{
		s_hZlib = LoadLibrary( "ZLIB.DLL" );
		if( !s_hZlib )
			nResult = ZL_ERROR_LOAD;
		else
		{
			s_pfnGzRead  = GetProcAddress( s_hZlib, "gzread"  );
			s_pfnGzOpen  = GetProcAddress( s_hZlib, "gzopen"  );
			s_pfnGzClose = GetProcAddress( s_hZlib, "gzclose" );
			s_pfnGzWrite = GetProcAddress( s_hZlib, "gzwrite" );
			s_pfnGzError = GetProcAddress( s_hZlib, "gzerror" );

			if( !s_pfnGzRead  ||
				!s_pfnGzOpen  ||
				!s_pfnGzClose ||
				!s_pfnGzWrite ||
				!s_pfnGzError )
			{
				FreeLibrary( s_hZlib );
				s_hZlib = NULL;
				nResult = ZL_ERROR_FUNC;
			}
		}
	}
	if( NULL != pHandle )
		pHandle = s_hZlib;

	return nResult;

} /* #OF# Compress_LoadLibrary */

/*========================================================
Function : Compress_FreeLibrary
=========================================================*/
/* #FN#
   Releases Zlib.dll library */
void
/* #AS#
   Nothing */
Compress_FreeLibrary( void )
{
	if( s_hZlib )
	{
		FreeLibrary( s_hZlib );

		s_pfnGzRead  = NULL;
		s_pfnGzOpen  = NULL;
		s_pfnGzClose = NULL;
		s_pfnGzWrite = NULL;
		s_pfnGzError = NULL;
	}
} /* #OF# Compress_FreeLibrary */

/*========================================================
Function : Compress_IsCapable
=========================================================*/
/* #FN#
   Checks if the ZLIB library is available */
int
/* #AS#
   1 if ZLIB has been loaded, otherwise -1 */
Compress_IsCapable( void )
{
	if( !s_hZlib )
	{
//		Aprint( "Cannot gzip/ungzip without zlib.dll loaded properly." );
		return -1;
	}
	return 1;

} /* #OF# Compress_IsCapable */

/*========================================================
Function : GZREAD
=========================================================*/
/* #FN#
   Reads the given number of uncompressed bytes from the compressed file */
int
/* #AS#
   Number of uncompressed bytes actually read (0 for end of file, -1 for error) */
GZREAD(
	gzFile   fFile,
	voidp    pBuf,
	unsigned nLen
)
{
	return (int)s_pfnGzRead( fFile, pBuf, nLen );

} /* #OF# GZREAD */

/*========================================================
Function : GZOPEN
=========================================================*/
/* #FN#
   Opens a gzip (.gz) file for reading or writing */
gzFile
/* #AS#
   NULL if the file could not be opened */
GZOPEN(
	const char *pszPath,
	const char *pszMode
)
{
	return (gzFile)s_pfnGzOpen( pszPath, pszMode );

} /* #OF# GZOPEN */

/*========================================================
Function : GZCLOSE
=========================================================*/
/* #FN#
   Closes the compressed file */
int
/* #AS#
   Zlib error number */
GZCLOSE(
	gzFile fFile
)
{
	return (int)s_pfnGzClose( fFile );

} /* #OF# GZCLOSE */

/*========================================================
Function : GZWRITE
=========================================================*/
/* #FN#
   Writes the given number of uncompressed bytes into the compressed file */
int
/* #AS#
   Number of uncompressed bytes actually written (0 in case of error) */
GZWRITE(
	gzFile      fFile,
	const voidp pBuf,
	unsigned    nLen
)
{
	return (int)s_pfnGzWrite( fFile, pBuf, nLen );

} /* #OF# GZWRITE */

/*========================================================
Function : GZERROR
=========================================================*/
/* #FN#
   Returns the error message for the last error */
const char *
/* #AS#
   Pointer to the error message */
GZERROR(
	gzFile fFile,
	int   *pErrNum
)
{
	return (const char *)s_pfnGzError( fFile, pErrNum );

} /* #OF# GZERROR */
