#include <stdio.h>
#include <string.h>
#include "IC_Errors.h"
#include "AppleWorks.h"

#define		CR_RECORD		208		// Carriage Return Record
#define		CL_RECORD		209		// Command Line Record
#define		TXT_RECORD		0		// Text Record
#define		NEWLINE			0x0D

char		i_dataAC[256];
short		i_byteCount = -1;
Boolean		i_SFMinVersB = FALSE;
short		i_newLineState = 2;
short		i_txtLineState = 2;
short		i_txtLineCount = 0;
short		i_byte000 = 0;
short		i_recordType = 0;
Boolean		i_crAtEndB = FALSE;
Boolean		i_endOfDataB = FALSE;

static char	*cat(char *bufP, Byte b1)
{
	char	byteC[2];
	
	byteC[0] = b1;
	byteC[1] = 0;
	
	strcat(bufP, byteC);
	
	return bufP;
}

static char	*cat(char *bufP, char *buf2, Byte b1)
{
	strcat(bufP, buf2);
	cat(bufP, b1);
	return bufP;
}

static char	*cat(char *bufP, char *buf2, short num, Byte b1)
{
	sprintf(bufP, "%s%d%c", buf2, (int)num, (char)b1);
	return bufP;
}

static char	*DecodeAWP(char token, char *bufP)
{
	bufP[0] = 0;
	
	if (i_endOfDataB) return bufP;
	i_byteCount++;
	
	if (i_byteCount < 5) return bufP;
	if (i_byteCount < 85) return cat(bufP, token);
	
	if (i_byteCount == 85) return cat(bufP, NEWLINE); // To close out the ruler from 5-84
	if (i_byteCount == 183) {
		if (token != 0) i_SFMinVersB = TRUE;
		return bufP;
	}
	
	if (i_byteCount < 300) return bufP;
	if (i_byteCount < 302 && i_SFMinVersB) return bufP;

	// Get record parameter
	if (i_newLineState > 1) {	
		i_newLineState = 1;
		i_byte000 = token;
		return bufP;
	}
	
	if (i_newLineState > 0) {
		i_newLineState = 2;
		i_recordType = token;
		
		if (i_recordType == CR_RECORD) {
		//	return cat(bufP, "--------Carriage Return = " + i_byte000 + NEWLINE);
			return cat(bufP, NEWLINE);
		}
		
		if (i_recordType >= CL_RECORD) {
		
			switch (i_recordType) {
				case 0xd4 : return cat(bufP, "--------Internal Ruler", i_byte000, NEWLINE);
				case 0xd5 : return cat(bufP, "--------Page Header End", NEWLINE);
				case 0xd6 : return cat(bufP, "--------Page Footer End", NEWLINE);
				case 0xd7 : return cat(bufP, "--------Right Justified", NEWLINE);
				case 0xd8 : return cat(bufP, "--------Platen Width = ", i_byte000, NEWLINE);
				case 0xd9 : return cat(bufP, "--------Left Margin = ", i_byte000, NEWLINE);
				case 0xda : return cat(bufP, "--------Right Margin = ", i_byte000, NEWLINE);
				case 0xdb : return cat(bufP, "--------Characters Per Inch = ", i_byte000, NEWLINE);
				case 0xdc : return cat(bufP, "--------Proportional-1", NEWLINE);
				case 0xdd : return cat(bufP, "--------Proportional-2", NEWLINE);
				case 0xde : return cat(bufP, "--------Indent = ", i_byte000, NEWLINE);
				case 0xdf : return cat(bufP, "--------Justify", NEWLINE);
				case 0xe0 : return cat(bufP, "--------Unjustify", NEWLINE);
				case 0xe1 : return cat(bufP, "--------Center", NEWLINE);
				case 0xe2 : return cat(bufP, "--------Paper Length = ", i_byte000, NEWLINE);
				case 0xe3 : return cat(bufP, "--------Top Margin = ", i_byte000, NEWLINE);
				case 0xe4 : return cat(bufP, "--------Bottom Margin = ", i_byte000, NEWLINE);
				case 0xe5 : return cat(bufP, "--------Lines Per Inch = ", i_byte000, NEWLINE);
				case 0xe6 : return cat(bufP, "--------Single Space", NEWLINE);
				case 0xe7 : return cat(bufP, "--------Double Space", NEWLINE);
				case 0xe8 : return cat(bufP, "--------Triple Space", NEWLINE);
				case 0xe9 : return cat(bufP, "--------New Page", NEWLINE);
				case 0xea : return cat(bufP, "--------Group Begin", NEWLINE);
				case 0xeb : return cat(bufP, "--------Group End", NEWLINE);
				case 0xec : return cat(bufP, "--------Page Header", NEWLINE);
				case 0xed : return cat(bufP, "--------Page Footer", NEWLINE);
				case 0xee : return cat(bufP, "--------Skip Lines = ", i_byte000, NEWLINE);
				case 0xef : return cat(bufP, "--------Page Number = ", i_byte000, NEWLINE);
				case 0xf0 : return cat(bufP, "--------Pause Each Page", NEWLINE);
				case 0xf1 : return cat(bufP, "--------Pause Here", NEWLINE);
				case 0xf2 : return cat(bufP, "--------Set Marker = ", i_byte000, NEWLINE);
				case 0xf3 : return cat(bufP, "--------Page Number = ", i_byte000, NEWLINE);
				case 0xf4 : return cat(bufP, "--------Page Break = ", i_byte000, NEWLINE);
				case 0xf5 : return cat(bufP, "--------Page Break = ", (i_byte000 + 256), NEWLINE);
				case 0xf6 : return cat(bufP, "--------Page Break Par = ", i_byte000, NEWLINE);
				case 0xf7 : return cat(bufP, "--------Page Break Par = ", (i_byte000 + 256), NEWLINE);
				case 0xf8 : return cat(bufP, "--------Unknown F8 = ", i_byte000 + NEWLINE);
				case 0xf9 : return cat(bufP, "--------Unknown F9 = ", i_byte000, NEWLINE);
				case 0xfa : return cat(bufP, "--------Unknown FA = ", i_byte000, NEWLINE);
				case 0xfb : return cat(bufP, "--------Unknown FB = ", i_byte000, NEWLINE);
				case 0xfc : return cat(bufP, "--------Unknown FC = ", i_byte000, NEWLINE);
				case 0xfd : return cat(bufP, "--------Unknown FD = ", i_byte000, NEWLINE);
				case 0xfe : return cat(bufP, "--------Unknown FE = ", i_byte000, NEWLINE);
				case 0xff : {
					i_endOfDataB = TRUE;
					return cat(bufP, "--------End Of File", NEWLINE);
				}
			}
		}
	
		if (i_recordType != TXT_RECORD) {
			return cat(bufP, /*"--------Unknown Record Type = ", i_byte000,*/ NEWLINE);
		}
		
		// So it must be a text record
		i_newLineState = 0;
		i_txtLineState = 2;
		return bufP;
	}

	if (i_txtLineState > 1) {
		i_txtLineState = 1;
		return bufP;
	}
	
	if (i_txtLineState > 0) {
		i_txtLineState = 0;
		
		if (token < 0) {
			i_crAtEndB = TRUE;
		} else {
			i_crAtEndB = FALSE;
		}
		
		i_txtLineCount = token & 0x7f;
		return bufP;
	}

	if (token < 0) {
		token += 128;
	}
	
	i_dataAC[0] = 0;
	
	switch (token) {
		case 0x00 : i_dataAC[0] = 0; break;
		case 0x01 : strcpy(i_dataAC, "<B>"); break;
		case 0x02 : strcpy(i_dataAC, "</B>"); break;
		case 0x03 : strcpy(i_dataAC, "<SUP>"); break;
		case 0x04 : strcpy(i_dataAC, "</SUP>"); break;
		case 0x05 : strcpy(i_dataAC, "<SUB>"); break;
		case 0x06 : strcpy(i_dataAC, "</SUB>"); break;
		case 0x07 : strcpy(i_dataAC, "<I>"); break;
		case 0x08 : strcpy(i_dataAC, "</I>"); break;
		case 0x09 : strcpy(i_dataAC, "<!Page Number>"); break;
		case 0x0a : strcpy(i_dataAC, "<!Enter Keyboard>"); break;
		case 0x0b : strcpy(i_dataAC, "<!Sticky Space>"); break;
		case 0x0c : strcpy(i_dataAC, "<!Mail Merge>"); break;
		case 0x0d : strcpy(i_dataAC, "<!Reserved>"); break;
		case 0x0e : strcpy(i_dataAC, "<!Date>"); break;
		case 0x0f : strcpy(i_dataAC, "<!Time>"); break;
		case 0x10 : strcpy(i_dataAC, "<!Special 1>"); break;
		case 0x11 : strcpy(i_dataAC, "<!Special 2>"); break;
		case 0x12 : strcpy(i_dataAC, "<!Special 3>"); break;
		case 0x13 : strcpy(i_dataAC, "<!Special 4>"); break;
		case 0x14 : strcpy(i_dataAC, "<!Special 5>"); break;
		case 0x15 : strcpy(i_dataAC, "<!Special 6>"); break;
		case 0x16 : strcpy(i_dataAC, "   "); break; // Ignore actual tab stops
		case 0x17 : i_dataAC[0] = 0; break;
		case 0x18 : strcpy(i_dataAC, "<!Reserved>");
	}
	
	if (token > 24 && token < 32) {
		cat(i_dataAC, "^", token + 64);
	}
	
	if (token > 31) {
		cat(i_dataAC, token);
	}

	i_txtLineCount--;

	if (i_txtLineCount < 1) {
		i_txtLineState = 0;
		i_newLineState = 2;
		
		if (i_crAtEndB) {
			return cat(bufP, i_dataAC, NEWLINE);
		}
	}
	
	return i_dataAC;
}

void		ResetAWP(void)
{
	i_dataAC[0]		= 0;
	i_byteCount		= -1;
	i_SFMinVersB	= FALSE;
	i_newLineState	= 2;
	i_txtLineState	= 2;
	i_txtLineCount	= 0;
	i_byte000		= 0;
	i_recordType	= 0;
	i_crAtEndB		= FALSE;
	i_endOfDataB	= FALSE;
}

void	DeTokenizeAwp(
	char	*inBufZ,		ushort	inBufSizeS,
	char	*outBufZ,		ushort 	*outBufSizeSP)
{
	ushort		curBufS;
	char		bufAC[256], *curCharZ;
	ushort		strLenS;
	ulong		inMaxL	= GetPtrSize((Ptr)inBufZ), 
				outMaxL	= GetPtrSize((Ptr)outBufZ);
	
	ASSERT((ulong)inBufSizeS <= inMaxL);
	
	*outBufSizeSP	= 0;
	outBufZ[0]		= 0;
	
	for (curBufS = 0; !i_endOfDataB && curBufS < inBufSizeS; curBufS++) {
		curCharZ	= DecodeAWP(inBufZ[curBufS], bufAC);
		strLenS 	= strlen(curCharZ);
		
		if (strLenS) {
			*outBufSizeSP += strLenS;
			
			ASSERT((ulong)*outBufSizeSP <= outMaxL);
			
			strcat(outBufZ, curCharZ);
		}
	}
	
	//	don't forget the zero on the end
	//outBufZ[++(*outBufSizeSP)] = 0;
}
