#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define INCLUDE_HUFFSTUFF 
#include <huffman.h>


SHORT far pascal CompressFileToFile(FILE * pInput, FILE * pOutput)
{
    SHORT rc;
	 struct _HuffStuff * pHS;

    pHS = StartHuff();
	 if (pHS == NULL)
	     return(HUFFMAN_MEMORY_ERROR);
    pHS->sType = HUFFMAN_FILE_TO_FILE;
    pHS->pInput = (PVOID)pInput;
    pHS->pOutput = (PVOID)pOutput;
	 pHS->fGetNextChar = GetNextFileChar;
	 pHS->fPutNextChar = PutNextFileChar;

    fseek((FILE *)pHS->pInput, 0L, 2);
    pHS->textsize = ftell((FILE *)pHS->pInput);
    PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff000000L) >> 24));
    PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff0000L) >> 16));
    PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff00) >> 8));
    PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff)));
    if (ferror((FILE *)pHS->pOutput))
	     return(HUFFMAN_FILE_WRITE_ERROR);
    if (pHS->textsize == 0)
	     return(HUFFMAN_FILE_LENGTH_ERROR);
    rewind((FILE *)pHS->pInput);

	 rc = Compress(pHS);

	 EndHuff(pHS);
	 return(rc);
}


SHORT far pascal CompressFileToBuffer(FILE * pInput, PCHAR pOutput, 
                                      ULONG ulOutSize, PULONG pulOutSize)
{
    SHORT rc;
	 struct _HuffStuff * pHS;

    pHS = StartHuff();
	 if (pHS == NULL)
	     return(HUFFMAN_MEMORY_ERROR);
    pHS->sType = HUFFMAN_FILE_TO_FILE;
    pHS->pInput = (PVOID)pInput;
    pHS->pOutput = (PVOID)pOutput;
	 pHS->fGetNextChar = GetNextFileChar;
	 pHS->fPutNextChar = PutNextBufferChar;
	 pHS->ulMaxOutput = ulOutSize;

    fseek((FILE *)pHS->pInput, 0L, 2);
    pHS->textsize = ftell((FILE *)pHS->pInput);
    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff000000L) >> 24)) == EOF)
	     return(HUFFMAN_FILE_WRITE_ERROR);
    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff0000L) >> 16)) == EOF)
	     return(HUFFMAN_FILE_WRITE_ERROR);
    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff00) >> 8)) == EOF)
	     return(HUFFMAN_FILE_WRITE_ERROR);
    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff))) == EOF)
	     return(HUFFMAN_FILE_WRITE_ERROR);
    if (pHS->textsize == 0)
	     return(HUFFMAN_FILE_LENGTH_ERROR);
    rewind((FILE *)pHS->pInput);

	 rc = Compress(pHS);

	 *pulOutSize  = ulOutSize - pHS->ulMaxOutput;

	 EndHuff(pHS);
	 return(rc);
}


SHORT far pascal ExpandFileToFile(FILE * pInput, FILE * pOutput)
{
    SHORT rc;
	 struct _HuffStuff * pHS;

    pHS = StartHuff();
	 if (pHS == NULL)
	     return(HUFFMAN_MEMORY_ERROR);
    pHS->sType = HUFFMAN_FILE_TO_FILE;
    pHS->pInput = (PVOID)pInput;
    pHS->pOutput = (PVOID)pOutput;
	 pHS->fGetNextChar = GetNextFileChar;
	 pHS->fPutNextChar = PutNextFileChar;

    pHS->textsize  = (UCHAR) GetNextFileChar(pHS);
    pHS->textsize <<= 8;
    pHS->textsize |= (UCHAR) GetNextFileChar(pHS);
    pHS->textsize <<= 8;
    pHS->textsize |= (UCHAR) GetNextFileChar(pHS);
    pHS->textsize <<= 8;
    pHS->textsize |= (UCHAR) GetNextFileChar(pHS);
    if (ferror((FILE *)pHS->pInput))
	     return(HUFFMAN_FILE_READ_ERROR);
    if (pHS->textsize == 0)
	     return(HUFFMAN_FILE_LENGTH_ERROR);

    rc = Expand(pHS);

	 EndHuff(pHS);

	 return(rc);
}


SHORT far pascal ExpandBufferToFile(PCHAR pInput, ULONG ulInSize,
                                    FILE * pOutput)
{
    SHORT rc;
	 struct _HuffStuff * pHS;

    pHS = StartHuff();
	 if (pHS == NULL)
	     return(HUFFMAN_MEMORY_ERROR);
    pHS->sType = HUFFMAN_FILE_TO_FILE;
    pHS->pInput = (PVOID)pInput;
    pHS->pOutput = (PVOID)pOutput;
	 pHS->fGetNextChar = GetNextBufferChar;
	 pHS->ulMaxInput = ulInSize;
	 pHS->fPutNextChar = PutNextFileChar;

    if (pHS->ulMaxInput < 5)
	     return(HUFFMAN_FILE_READ_ERROR);
    pHS->textsize  = (UCHAR) GetNextBufferChar(pHS);
    pHS->textsize <<= 8;
    pHS->textsize |= (UCHAR) GetNextBufferChar(pHS);
    pHS->textsize <<= 8;
    pHS->textsize |= (UCHAR) GetNextBufferChar(pHS);
    pHS->textsize <<= 8;
    pHS->textsize |= (UCHAR) GetNextBufferChar(pHS);
    if (pHS->textsize == 0)
	     return(HUFFMAN_FILE_LENGTH_ERROR);

    rc = Expand(pHS);

	 EndHuff(pHS);

	 return(rc);
}


SHORT GetNextFileChar(struct _HuffStuff * pHS)
{
    return(getc((FILE *)pHS->pInput));
}


SHORT PutNextFileChar(struct _HuffStuff * pHS, USHORT c)
{
    return(putc(c, (FILE *)pHS->pOutput));
}

