#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "resource.h"
#include "lzw.h"

#define BITS		12					// Setting the number of bits to 12, 13
#define MAX_VALUE	(1 << BITS) - 1		// Note that MS-DOS machines need to
#define MAX_CODE	MAX_VALUE - 1		// compile their code in large model if 14 bits are selected.
#define TABLE_SIZE	5021

unsigned int	*prefix_code;		// This array holds the prefix codes
unsigned char	*append_character;	// This array holds the appended chars
unsigned char	decode_stack[4000];	// This array holds the decoded string

int				input_bit_count = 0;
unsigned long	input_bit_buffer = 0;


MEMFILE *unpack(int rID, int unpacksize)
{
	HRSRC		rec;
	HGLOBAL		handle;
	MEMFILE		*memfile, *temp;

	rec		= FindResource (NULL, MAKEINTRESOURCE(rID), "RAWDATA" );
	handle	= LoadResource (NULL, rec);

	memfile = new MEMFILE;
	temp = new MEMFILE;
	temp->length = SizeofResource (NULL, rec);
	temp->data = new unsigned char [temp->length];
	temp->pos = 0;

	memfile->length	= unpacksize;
	memfile->data	= new unsigned char [memfile->length];
	memfile->pos	= 0;

	temp->data = (unsigned char*)LockResource (handle);

	expand(temp, memfile);
	
	UnlockResource (handle);
	delete temp;
	
	return memfile;
}


int Mgetc(MEMFILE *file)
{
	return (file->data[file->pos++]);
}

void Mputc(int c, MEMFILE *file)
{
	file->data[file->pos++] = c;
}

int input_code(MEMFILE *input)
{
	unsigned int return_value;

	while (input_bit_count <= 24)
	{
	    input_bit_buffer	|= (unsigned long) Mgetc(input) << (24-input_bit_count);
		input_bit_count		+= 8;
	}

	return_value = input_bit_buffer >> (32-BITS);
	input_bit_buffer <<= BITS;
	input_bit_count -= BITS;
	return (return_value);
}

/*
** This routine simply decodes a string from the string table, storing
** it in a buffer.  The buffer can then be output in reverse order by
** the expansion program.
*/

char *decode_string(unsigned char *buffer,unsigned int code)
{
	while (code > 255)
	{
		*buffer++ = append_character[code];
		code = prefix_code[code];
	}
	*buffer=code;
	return(char*)(buffer);
}


/*
**  This is the expansion routine.  It takes an LZW format file, and expands
**  it to an output file.  The code here should be a fairly close match to
**  the algorithm in the accompanying article.
*/

void InitLZW ()
{
	prefix_code = new unsigned int[TABLE_SIZE*sizeof(unsigned int)];
	append_character = new unsigned char[TABLE_SIZE*sizeof(unsigned char)];
}

void DeInitLZW ()
{
	delete prefix_code;
	delete append_character;
}

void expand(MEMFILE *input,MEMFILE *output)
{
	unsigned int	next_code;
	unsigned int	new_code;
	unsigned int	old_code;
	unsigned char	*string;
	int				character;

	memset (prefix_code, 0, TABLE_SIZE*sizeof(unsigned int));
	memset (append_character, 0, TABLE_SIZE*sizeof(unsigned char));
	input_bit_count		= 0;
	input_bit_buffer	= 0;

	next_code = 256;				// This is the next available code to define
	old_code = input_code(input);	// Read in the first code, initialize the
	character = old_code;			// character variable, and send the first
	Mputc(old_code, output);		// code to the output file

	/*
	**  This is the main expansion loop.  It reads in characters from the LZW file
	**  until it sees the special code used to inidicate the end of the data.
	*/

	while ((new_code=input_code(input)) != (MAX_VALUE))
	{
		if (new_code >= next_code)
		{
			*decode_stack = character;
			string = (unsigned char*)decode_string(decode_stack+1, old_code);
		}
		// Otherwise we do a straight decode of the new code.
		else
			string = (unsigned char*)decode_string(decode_stack, new_code);

		// Now we output the decoded string in reverse order.
		character = *string;
		while (string >= decode_stack)
			Mputc(*string--, output);

		// Finally, if possible, add a new code to the string table.
		if (next_code <= MAX_CODE)
		{
			prefix_code[next_code] = old_code;
			append_character[next_code] = character;
			next_code++;
		}

		old_code = new_code;
	}
}



