#include <windows.h>
#include "sys\types.h"
#include "sys\stat.h"

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

#define INCLUDE_HUFFSTUFF
#include <ttwcomp.h>


SHORT FAR PASCAL __export CompressFileToFile(HFILE Input, HFILE Output)
{
    SHORT      rc;
         PHUFFSTUFF pHS;
    //HANDLE     hStatBuf;
    //struct stat * pStatBuf;

    pHS = StartHuff();
         if (pHS == NULL)
             return(HUFFMAN_MEMORY_ERROR);
    pHS->sType = HUFFMAN_FILE_TO_FILE;
    pHS->hInput = Input;
    pHS->hOutput = Output;
         pHS->fGetNextChar = GetNextFileChar;
         pHS->fPutNextChar = PutNextFileChar;

    //hStatBuf = LocalAlloc(LMEM_MOVEABLE, sizeof(struct stat));
    //     pStatBuf = (struct stat *)LocalLock(hStatBuf);
    //fstat(pHS->hInput, pStatBuf);
    //pHS->textsize = pStatBuf->st_size;
    pHS->textsize = _llseek(pHS->hInput, 0L, 2);    // Get file size
    _llseek(pHS->hInput, 0L, 0);                    // Reset pointer
    //     LocalUnlock(hStatBuf);
    //     LocalFree(hStatBuf);
    if (PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff000000L) >> 24)) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff0000L) >> 16)) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff00) >> 8)) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (PutNextFileChar(pHS, (USHORT)((pHS->textsize & 0xff))) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (pHS->textsize == 0){
             EndHuff(pHS);
             return(HUFFMAN_FILE_LENGTH_ERROR);
                  }

         rc = Compress(pHS);

         EndHuff(pHS);
         return(rc);
}


SHORT FAR PASCAL __export CompressFileToBuffer(HFILE Input, FPCHAR pOutput,
                                      ULONG ulOutSize, FPULONG pulOutSize)
{
    SHORT rc;
         PHUFFSTUFF pHS;
    //HANDLE     hStatBuf;
    //struct stat * pStatBuf;

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

    //hStatBuf = LocalAlloc(LMEM_MOVEABLE, sizeof(struct stat));
    //     pStatBuf = (struct stat *)LocalLock(hStatBuf);
    //fstat(pHS->hInput, pStatBuf);
    // pHS->textsize = pStatBuf->st_size;
    pHS->textsize = _llseek(pHS->hInput, 0L, 2);    // Get file size
    _llseek(pHS->hInput, 0L, 0);                    // Reset pointer
    //     LocalUnlock(hStatBuf);
    //     LocalFree(hStatBuf);

    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff000000L) >> 24)) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff0000L) >> 16)) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff00) >> 8)) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (PutNextBufferChar(pHS, (USHORT)((pHS->textsize & 0xff))) == EOF){
             EndHuff(pHS);
             return(HUFFMAN_FILE_WRITE_ERROR);
                  }
    if (pHS->textsize == 0){
             EndHuff(pHS);
             return(HUFFMAN_FILE_LENGTH_ERROR);
                  }

         rc = Compress(pHS);

         *pulOutSize  = ulOutSize - pHS->ulMaxOutput;

         EndHuff(pHS);
         return(rc);
}


SHORT FAR PASCAL __export ExpandFileToFile(HFILE Input, HFILE Output)
{
    SHORT rc;
         PHUFFSTUFF pHS;

    pHS = StartHuff();
         if (pHS == NULL)
             return(HUFFMAN_MEMORY_ERROR);
    pHS->sType = HUFFMAN_FILE_TO_FILE;
    pHS->hInput = Input;
    pHS->hOutput = Output;
         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 (pHS->textsize == 0){
             EndHuff(pHS);
             return(HUFFMAN_FILE_LENGTH_ERROR);
                  }

    rc = Expand(pHS);

         EndHuff(pHS);

         return(rc);
}


SHORT FAR PASCAL __export ExpandBufferToFile(FPCHAR pInput, ULONG ulInSize,
                                    HFILE Output)
{
    SHORT rc;
         PHUFFSTUFF pHS;

    pHS = StartHuff();
         if (pHS == NULL)
             return(HUFFMAN_MEMORY_ERROR);
    pHS->sType = HUFFMAN_FILE_TO_FILE;
    pHS->pInput = (FPVOID)pInput;
    pHS->hOutput = Output;
         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){
             EndHuff(pHS);
             return(HUFFMAN_FILE_LENGTH_ERROR);
                  }

    rc = Expand(pHS);

         EndHuff(pHS);

         return(rc);
}


SHORT GetNextFileChar(PHUFFSTUFF pHS)
{
char c;

    if (_lread(pHS->hInput, &c, 1) != 1)
             return(EOF);
    return(c);
}


SHORT PutNextFileChar(PHUFFSTUFF pHS, USHORT c)
{
int result;

    result = _lwrite(pHS->hOutput, (LPSTR)&c, 1);
         if (result != 1)
        return(EOF);
    return(0);
}
