// CSugDict.cp
// CSugDict.h
// ----------------------------------------------------------------------------------
// The suggested change dictionary class.
//
// This dictionary automatically provides a suggestion(s) for a word.
//
// Note: This file is proprietary and confidential to Art Pollard
//	and Lextek Internation.
// Copyright 1994 Art Pollard / LexTek International
//
//
// ----------------------------------------------------------------------------------
// History:
//		Clark Goble			09/02/94
//			Original.
// ----------------------------------------------------------------------------------

#include "CSugDct.h"
#include <stdio.h>
#include "TSpell.h"
#include "UError.h"

//#define TEST

#ifndef FALSE
#define FALSE 0
#endif

CSugDict::CSugDict(long NumBuffers, FioParam * theFile)
	: CDict(NumBuffers, theFile), UExtended()
{
	theList = NULL;
	LastFound = NULL;
	
	if (theFile)
	{
		
		// Open the file and create the filter
		DictFile = new Uio(theFile);
		DictFile->Open();
		DictFile->SetPos(0, SEEK_SET);
		
		if ( ErrorFunc(0, GET) < eNo_Err )
		{	// try to create the file
			ErrorFunc(0, SET);
			DictFile->Close();
			DictFile->Create();
			
			if ( ErrorFunc(0, GET) < eNo_Err )
				return;		// hopeless
			
			DictFile->SetPos(0, SEEK_SET);
				// Put our magic word	
			DictFile->PutWord("SugDict");
			DictFile->Close();
			
			// Open it for regular reading/writing
			DictFile->Open();
			DictFile->SetPos(0, SEEK_SET);
			
			char *Word = DictFile->GetWord();
			if ( ErrorFunc(0, GET) < eNo_Err )
				return;		
	
			if (EStrCmp(Word, "SugDict"))
			{	// error
				ErrorFunc(eNot_Dictionary, SET);
				return;
			}
	
		
		}
	} else
	{
		DictFile = NULL;
	}
		
		
	WordList = new UBloom(NumBuffers, 20, By_Key);
	if (ErrorFunc(0, GET) < eNo_Err)
		return;		// Bloom error
		
	if (DictFile)
	{
		// Read the words into the filter
		
		char *Word;
		DictFile->SetPos(0, SEEK_SET);
		if ( ErrorFunc(0, GET) < eNo_Err )
			return;		
		Word = DictFile->GetWord();
		if ( ErrorFunc(0, GET) < eNo_Err )
			return;		
	
		if (EStrCmp(Word, "SugDict"))
		{	
			ErrorFunc(0, SET);
	
			DictFile->Close();
			
			DictFile->Create();
			
			if ( ErrorFunc(0, GET) < eNo_Err )
				return;		// hopeless
			
			DictFile->SetPos(0, SEEK_SET);
				// Put our magic word	
			DictFile->PutWord("SugDict");
			DictFile->Close();
			
			// Open it for regular reading/writing
			DictFile->Open();
			DictFile->SetPos(0, SEEK_SET);
			
			char *Word = DictFile->GetWord();
			if ( ErrorFunc(0, GET) < eNo_Err )
				return;		
	
			if (EStrCmp(Word, "SugDict"))
			{	// error
				ErrorFunc(eNot_Dictionary, SET);
				return;
			}
	
			
		}	
	
		// create the list
		
		SugList	*tempList = (SugList*) ::malloc(sizeof(SugList));
		
		theList = tempList;	// copy head
		
		short	theSize;
		
		// get the first word
		Word = DictFile->GetWord();
		if ( ErrorFunc(0, GET) < eNo_Err )
		{
			return;		
		}
		
		// Check to see if it is a blank file
		if  (*Word == '\0')
		{	free(tempList);
			theList = NULL;
		}
		
		while (!DictFile->eof() && (Word != NULL) && (*Word != '\0'))
		{
			
			// get word to replace
			// already got first word
			
			WordList->Insert(Word,strlen(Word));
			theSize = strlen(Word)+1;
			tempList->toChange = (char *) malloc(theSize);
			if (tempList->toChange != NULL)
				strcpy(tempList->toChange,Word);

			Word = DictFile->GetWord(); // suggestion
			
			if ( ErrorFunc(0, GET) < eNo_Err )
				return;		
	
			theSize = strlen(Word)+1;
			tempList->Correction = (char *) malloc(theSize);
			if (tempList->Correction != NULL)
				strcpy(tempList->Correction,Word);
		
			Word = DictFile->GetWord(); // suggestion
	
			if ( ErrorFunc(0, GET) < eNo_Err )
			{	tempList->next = NULL;
				return;	
			}	
	
			theSize = strlen(Word)+1;
			tempList->Comment = (char *) malloc(theSize);
			if (tempList->Comment != NULL)
				strcpy(tempList->Comment,Word);
	
			// Get the first word of the next list
			Word = DictFile->GetWord();
			
			if ( ErrorFunc(0, GET) < eNo_Err )
				return;		
	
	
			
			if (DictFile->eof() || (*Word == '\0') || (Word == NULL))
				tempList->next = NULL;
			else
			{	tempList->next = (SugList*) ::malloc(sizeof(SugList));
				if (tempList->next == NULL)
				{	ErrorFunc(eNo_Mem, SET);
					return;
				}
				tempList = tempList->next;
	
			}	
	
		} // while
	}
	
}

void free_list(SugList	*temp)
{	if (temp->next != NULL)
		free_list(temp->next);

	free(temp->toChange);
	free(temp->Correction);
	free(temp->Comment);
	free(temp);
}



CSugDict::~CSugDict()
{
	if (WordList != NULL)
		delete WordList;

	if (theList != NULL)
		free_list(theList);
	
	if (DictFile)
		DictFile->Close();

}


short	
CSugDict::Check(char *Word)
{	// is the word in our dictionary?
	return (WordList->Test(Word,strlen(Word)));
}

// ----------------------------------------------------------------------------------
// Find	-- finds word
// ----------------------------------------------------------------------------------
// To obtain the word use current and next.

short
CSugDict::Find(char *Word)
{
	SugList	*temp = theList;
	
	// search the list
	while ( (temp != NULL) && (EStrCmp(Word,temp->toChange)) )
		temp = temp->next;
		
	if ( temp == NULL)
		return NOTFOUND;
	
	LastFound = temp;
	return FOUND;
}

short 
CSugDict::Current(char *Word, char *change, char *comment)
{
	#pragma unused(Word)
	
	if (LastFound == NULL)
		return (NOTFOUND);
	
	strcpy(change, LastFound->Correction);
	strcpy(comment, LastFound->Comment);
	
	return (FOUND);
}

short 
CSugDict::Next(char *Word, char *change, char *comment)
{
	SugList	*temp = LastFound->next;
	
	// search the list
	while ( (temp != NULL) && ( EStrCmp(Word,temp->toChange)) )
		temp = temp->next;
		
	if ( temp == NULL)
		return NOTFOUND;
	
	LastFound = temp;
	
	strcpy(change, LastFound->Correction);
	strcpy(comment, LastFound->Comment);
	return (FOUND);

}


short 	
CSugDict::Add(char *Word, char *change, char *comment)
{
	if (*Word == '\0')
		return FALSE;
				
	SugList	*temp = theList;
	
	// Goto the end of the list (at end temp = last element, newly allocated)
	
	if (temp != NULL ) // is there a list?
	{
		while (temp->next != NULL)
			temp  = temp->next;
		
		temp->next = (SugList*) ::malloc(sizeof(SugList));

		if (temp->next == NULL)
		{	ErrorFunc(eNo_Mem, SET);
			return FALSE;
		}

		temp = temp->next;
		temp->next = NULL;

	} else // list doesn't exit
	{
		theList = (SugList*) ::malloc(sizeof(SugList));

		if (theList == NULL)
		{	ErrorFunc(eNo_Mem, SET);
			return FALSE;
		}

		theList->next = NULL;
		temp = theList;
	}



	// note: assumes we are opened in append mode

	WordList->Insert(Word,strlen(Word));
	temp->toChange = (char *) malloc(strlen(Word)+1);
	if (temp->toChange != NULL)
	{	strcpy(temp->toChange,Word);

		if (DictFile)
			DictFile->PutWord(Word);

		if ( ErrorFunc(0, GET) < eNo_Err )
			return FALSE;
	}
	else
	{	ErrorFunc(eNo_Mem, SET);
		return FALSE;
	}


	temp->Correction = (char *) malloc(strlen(change)+1);
	if (temp->Correction != NULL)
	{	strcpy(temp->Correction,change);

		if (DictFile)
			DictFile->PutWord(change);

		if ( ErrorFunc(0, GET) < eNo_Err )
			return FALSE;

	} else
	{	ErrorFunc(eNo_Mem, SET);
		return FALSE;
	}

	temp->Comment = (char *) malloc(strlen(comment)+1);
	if (temp->Comment != NULL)
	{	strcpy(temp->Comment,comment);

		if (DictFile)
			DictFile->PutWord(comment);

		if ( ErrorFunc(0, GET) < eNo_Err )
			return FALSE;

	} else
	{	ErrorFunc(eNo_Mem, SET);
		return FALSE;
	}

	temp->next = NULL;

	if (ErrorFunc(0, GET) < eNo_Err)
	{	return FALSE;
	}

	return TRUE;
}



#ifdef TEST

main()
{
	char	response[256];
	char	response1[10];
	char	change[256];
	char	comment[256];
	short		Choice;
	CSugDict	*SugDict;
	
	for(;;)
	{
		printf("\nCSugDict\n\n");
		printf("1. Open Dictionary\n");
		printf("2. Add Word\n");
		printf("3. Check Word\n");
		printf("4. Get Suggestion\n");
		printf("5. Next Suggestion\n");
		printf("6. Close Dictionary\n");
		
		printf("> ");
		gets(response1);
		Choice = atoi(response1);
		printf("\n");
		
		switch(Choice)
		{	case 1:
				printf("Dictionary to Open\n> ");
				gets(response);
				SugDict = new CSugDict(0, response);
				break;
			case 2:
				printf("Word to Add\n> ");
				gets(response);				
				printf("Word to Change it to\n> ");
				gets(change);
				printf("Comment\n> ");
				gets(comment);
				if (!SugDict->Add(response, change, comment))
				{	printf("\nProblems!\nRight here in River City!\n");
					break;
				}
				break;
			case 3:
				printf("Word to Check\n> ");
				gets(response);				
				if ( SugDict->Check(response) )
				{	printf("FOUND\n");
				} else
				{ 	printf("NOTFOUND\n");
				}
				break;
			case 4:
				if (SugDict->Find(response) )
				{	SugDict->Current(response, change, comment);
					printf("Word: %s\n",response);
					printf("Change: %s\n",change);
					printf("Comment: %s\n",comment);
				} else
					printf("Not Found");
				break;
			case 5:
				if (SugDict->Next(response, change, comment) )
				{	printf("Word: %s\n",response);
					printf("Change: %s\n",change);
					printf("Comment: %s\n",comment);
				} else
					printf("Not Found");
				break;
			case 6:
				delete SugDict;
				SugDict = NULL;
				break;
			
		}// switch
	
	} // fore

}


#endif


