// CQCheck.cp
// CQCheck.h
// ----------------------------------------------------------------------------------
//
//
// Note: This file is proprietary and confidential to Art Pollard
//	and Lextek Internation.
// Copyright 1994 Art Pollard / LexTek International
//
//
// ----------------------------------------------------------------------------------
// History:
// 		Art Pollard			June 94
//			Original
//		Clark Goble			08/24/94
//			Checked it over and made a few modifications as part of the
//			C++ conversion.
// ----------------------------------------------------------------------------------



#include <string.h>
#include "CQCMn.h"
#include "UError.h"

#define EOS (0)

/***** TEST #defs *****/
//#define TEST
/**********************/

#ifdef TEST
#include <stdio.h>
#include <stdlib.h>
#endif

short	defaultCallBack()
{
	return FALSE;
}

short CQCheck::Same(char *Word1,char *Word2)
{
	register short Index=0;

	while((Word1[Index] == Word2[Index]) && (Word1[Index] != EOS) && (Word2[Index] !=EOS))
		Index++;
	return Index;
}


short CQCheck::CheckMissingDouble(char *Word, char *Suggestion)
{
	register short Counter;

	if (!(inFlag & inMsDb))
	{	Length = strlen(Word);
		memmove(Word+2, Word + 1, Length + 2);
		Word[Length + 1] = 0;
		CMD_Loop = 1;
		inFlag = inMsDb;
	} else
	{	if (CMD_Loop < Length)
		{	memmove(Word + CMD_Loop + 1, Word + CMD_Loop, Length - CMD_Loop + 2);
			Word[Length + 1] = 0;
		}
		else
			memmove(Word + Length, Word + Length -1, 2);
	}

	for (Counter = CMD_Loop; Counter <= Length; Counter++)
	{
		if (Check(Word) == OK)
		{
			strcpy(Suggestion, Word);
			CMD_Loop = Counter + 1;
			memmove(Word+Counter, Word+Counter+1, Length + 2);
			Word[Length+1] = '\0';
			return TRUE;					// found one
		}

		Word[Counter] = Word[Counter + 1];
	}
	return FALSE;


}

short CQCheck::CheckDoubleLetter(char *Word, char *Suggestion)
{
	register short 	Counter;
	char			Temp;

	if (!(inFlag & inDbChar))
	{	Length = strlen(Word);
		CDL_Loop = 1;
		inFlag = inDbChar;
	}

	for (Counter = CDL_Loop; Counter <= Length; Counter++)
	{	Temp = Word[Counter];
		memmove(&Word[Counter], &Word[Counter + 1], (Length - Counter) + 1);
      //printf("\nTesting :%s",Word);
		if (Check(Word) == OK)
		{
			strcpy(Suggestion, Word);
			CDL_Loop = Counter + 1;
			memmove(&Word[Counter + 1], &Word[Counter], (Length - Counter) + 1);
			Word[Counter] = Temp;
			return TRUE;					// found one
		}
		memmove(&Word[Counter + 1], &Word[Counter], (Length - Counter) + 1);
		Word[Counter] = Temp;
	}
	return FALSE;

	
}

short CQCheck::CheckTransposedLetters(char *Word, char *Suggestion)
{
	register short Position;
	char TempChar;

	// if we weren't already in the routine reset the static variables
	if (!(inFlag & inTrans)) {
		// flag that we are in this routine -- for re-enterance
		inFlag = inTrans;
		CTL_Loop1 = 0;
		CTL_Loop2 = 0;
		Length = strlen(Word);
	}



	for (Position = CTL_Loop1; Position < Length - 1; Position++) {
		/* TRANSPOSE NEIGHBORING CHARACTERS */
		TempChar = Word[Position];
		Word[Position] = Word[Position + 1];
		Word[Position + 1] = TempChar;
		/* CHECK WORD */
		if (Check(Word) == OK) {
			/* THE WORD WAS A REAL WORD ADD IT TO THE LIST */
#ifdef TEST
			printf("\n*%s", Word);
#else
			strcpy(Suggestion, Word);
			CTL_Loop1 = Position + 1;			// go through the next element next time in
			// transpose them back
			TempChar = Word[Position];
			Word[Position] = Word[Position + 1];
			Word[Position + 1] = TempChar;
			return TRUE;
#endif

		}
		/* TRANSPOSE THEM BACK */
		TempChar = Word[Position];
		Word[Position] = Word[Position + 1];
		Word[Position + 1] = TempChar;
	}

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

	for (Position = CTL_Loop2; Position < Length - 2; Position++) {
		/* TRANSPOSE (ALMOST) NEIGHBORING CHARACTERS */
		TempChar = Word[Position];
		Word[Position] = Word[Position + 2];
		Word[Position + 2] = TempChar;
		/* CHECK WORD */
		if (Check(Word) == OK) {
			/* THE WORD WAS A REAL WORD ADD IT TO THE LIST */
#ifdef TEST
			printf("\n*%s", Word);
#else
			strcpy(Suggestion, Word);
#endif

			/* TRANSPOSE THEM BACK */
			TempChar = Word[Position];
			Word[Position] = Word[Position + 2];
			Word[Position + 2] = TempChar;
			CTL_Loop2 = Position + 1;			// go through the next element next time in
			return TRUE;

		}
		/* TRANSPOSE THEM BACK */
		TempChar = Word[Position];
		Word[Position] = Word[Position + 2];
		Word[Position + 2] = TempChar;
	}

	return FALSE;
}


short CQCheck::CheckExtraLetter(char *Word, char *Suggestion)
{
	register short Position;
	char Temp;

	// flag that we are in this routine -- for re-enterance

	if (!(inFlag & inExtra)) {
		Length = strlen(Word);
		CEL_Loop = 0;
		inFlag = inExtra;
	}



	for (Position = CEL_Loop; Position <= Length; Position++) {
		Temp = Word[Position];
		memmove(&Word[Position], &Word[Position + 1], (Length - Position) + 1);
#ifdef TEST
		//	 printf("\n%s",Word);
		
#endif

        
		if (Check(Word) == OK) {
			/* THE WORD WAS A REAL WORD ADD IT TO THE LIST */
#ifdef TEST
			printf("\n*%s", Word);
#else
			strcpy(Suggestion, Word);
#endif

			CEL_Loop = Position + 1;
			memmove(&Word[Position + 1], &Word[Position], (Length - Position) + 1);
			Word[Position] = Temp;
			return TRUE;
		}
		memmove(&Word[Position + 1], &Word[Position], (Length - Position) + 1);
		Word[Position] = Temp;
	}
	return FALSE;
}


short CQCheck::CheckOneWrongAt(short Position, char *Word, char *Suggestion)
{
	register char Counter;

	COW_Temp = Word[Position];

	if (!inOne) {
		COW_Loop = FIRSTCHAR;
		inOne = TRUE;
			 // Find the least possible word which will work.

		Word[Position] = 0;
		Find(Word);
	}

	Word[Position] = COW_Loop;


	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif


	/* NEED TO HAVE A LOOKUP FOR WORD UP TO XXXX[POSITION] */


//	Find(Word); // AP 1/1/96
	 // Now, loop through all the possible characters which could fill the slot.

	for (Counter = COW_Loop; Counter != LASTCHAR && Counter != 0 && Counter != 1; Counter = ENextChar(Counter) )
	{
		// if the next word is larger (alphabetically) than the current one
		// jump to the next word.

		if(/*(ECharCmp(Counter, FIRSTCHAR > 0) && */
		  (ECharCmp(location.Word[Position],Word[Position]) > 0))
			 Counter = location.Word[Position];

		if( /*(ECharCmp(Counter, FIRSTCHAR) > 0) && */(Same(location.Word,Word) < Position)) {
			 Word[Position] = COW_Temp;
			 inOne = FALSE;
			 return FALSE;
		}

//		theSame = Same(location.Word, Word);	// size of stream of identical characters


		Word[Position] = Counter;

		if (Check(Word) == OK) {

			strcpy(Suggestion, Word);
			COW_Loop = Counter + 1;
			Word[Position] = COW_Temp;
			if (Counter == LASTCHAR)
				inOne = FALSE;
			return TRUE;					// found one
		}
	}
	Word[Position] = COW_Temp;
	inOne = FALSE;
	return FALSE;								// didn't find one
}


short CQCheck::CheckWrongLetter(char *Word, char *Suggestion)
{
	register short Counter;

	if (!(inFlag & inWrong)) {
		CWL_Loop = 1;
		inFlag = inWrong;
	}

	Length = strlen(Word);
	for (Counter = CWL_Loop; Counter < Length; Counter++) {
		/* COUNTER SETS POSITION IN WORD IT START TO CHECK.
		  THE ASS/U/MTION IS THAT THE FIRST LETTER IS CORRECTLY
		  SPELLED (Counter = 1). BY MAKING THIS ASSUMTION, WE
		  SPEED UP THE SPELL CHECKER BY REDUCING THE NUMBER OF
		  PAGES THAT HAVE TO BE LOADED FROM DISK. (BY 25) */
		if ( CheckOneWrongAt(Counter, Word, Suggestion))
		{	CWL_Loop = Counter;
			return TRUE;
		}
	}
	return FALSE;
}


short CQCheck::CheckMissingLetter(char *Word, char *Suggestion)
{
	register short Counter;


	if (!(inFlag & inMiss)) {
		Length = strlen(Word);
		memmove(Word + 2, Word + 1, Length + 2);
		Word[Length + 1] = 0;
		CML_Loop = 1;
		inFlag = inMiss;
	} else
	{	if (CML_Loop < Length)
		{	memmove(Word + CML_Loop + 1, Word + CML_Loop, Length - CML_Loop + 2);
			Word[Length + 1] = 0;
		}
		else
			memmove(Word + Length, Word + Length -1, 2);
	}

	/* THIS FUNCTION HAS THE SAME ASSUMPTION AS CHECKWRONGLETTER.
	  THE ASSUMPTION IS THAT THE FIRST LETTER IS CORRECTLY SPELLED.
	  THIS SPEEDS UP THE SPELL CHECKER BY REDUCING THE NUMBER OF PAGES
	  WHICH HAVE TO BE LOADED INTO MEMORY BY 25. */

	for (Counter = CML_Loop; Counter <= Length; Counter++) {
		if (CheckOneWrongAt(Counter, Word, Suggestion))
		{	CML_Loop = Counter;
			memmove(Word+Counter, Word+Counter+1, Length + 2);
			Word[Length+1] = '\0';
			return TRUE;
		}
		Word[Counter] = Word[Counter + 1];
	}
	return FALSE;

}

short CQCheck::CheckDoubleWord(char *Word, char *Suggestion)
{
	char temp;
	register short counter;
	
	if (!(inFlag & inDouble))
	{
		Length = strlen(Word) - 1;
		CDW_Loop = 1;
		inFlag = inDouble;
	}
	
	for (counter = CDW_Loop; counter < Length; counter++)
	{	// check first part
		temp = Word[counter];
		Word[counter] = '\0';

		if (Check(Word) == OK)
		{
			Word[counter] = temp;

			if (Check( (Word + counter) ))
			{	strcpy(Suggestion, Word);	// copy first half
				Suggestion[counter] = ' ';  // add space
				Suggestion[counter+1] = '\0';
				strcat(Suggestion, Word+counter); // copy second half
				CDW_Loop = counter+1;
				return TRUE;
			}
		}

		Word[counter] = temp;
	}

	return FALSE;

}

short CQCheck::QCFind(char *Word, char *Suggestion, CallBackProc CallBack)
{

	inFlag = 0;

	if(strlen(Word) < 2)
		return FALSE;

      //printf("\n************************Checking Missing Double");
	if (CheckMissingDouble(Word, Suggestion)) {
   	//printf("\nWord: %s   Sug: %s",Word,Suggestion);
		return TRUE;
   }

	if ((CallBack != NULL) && (*CallBack)())
		ErrorFunc(eCancel, SET);

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

	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif

   //printf("\n***************************Checking Double Letter");
	if (CheckDoubleLetter(Word, Suggestion)) {
   	//printf("\nWord: %s   Sug: %s",Word,Suggestion);
		return TRUE;
   }
	if ((CallBack != NULL) && (*CallBack)())
		ErrorFunc(eCancel, SET);
	if (ErrorFunc(0, GET) < eNo_Err)
		return FALSE;

	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif


   //printf("\n***************************Checking Missing Letter");
	if (CheckMissingLetter(Word, Suggestion)) {
   	//printf("\nWord: %s   Sug: %s",Word,Suggestion);
		return TRUE;
   }
	if ((CallBack != NULL) && (*CallBack)())
		ErrorFunc(eCancel, SET);

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


	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif

   //printf("\n***************************Checking Transposed Characters");
	if (CheckTransposedLetters(Word, Suggestion)) {
   	//printf("\nWord: %s   Sug: %s",Word,Suggestion);
		return TRUE;
   }
	if ((CallBack != NULL) && (*CallBack)())
		ErrorFunc(eCancel, SET);

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


	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif


	if (CheckExtraLetter(Word, Suggestion))
		return TRUE;
	if ((CallBack != NULL) && (*CallBack)())
		ErrorFunc(eCancel, SET);

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

	
	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif

	if (CheckWrongLetter(Word, Suggestion))
		return TRUE;
	if ((CallBack != NULL) && (*CallBack)())
		ErrorFunc(eCancel, SET);

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

	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif

	if (CheckDoubleWord(Word, Suggestion))
		return TRUE;
	if ((CallBack != NULL) && (*CallBack)())
		ErrorFunc(eCancel, SET);

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


	return FALSE;
}


short CQCheck::QCNext(char *Word, char *Suggestion, CallBackProc CallBack)
{

	if(strlen(Word) < 2)
		return FALSE;

	if (inFlag <= inMsDb)
	{	if (CheckMissingDouble(Word, Suggestion))
			return TRUE;
		if ((CallBack != NULL) && (*CallBack)())
			ErrorFunc(eCancel, SET);

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

		#ifdef _MACINTOSH_
		//SystemTask();		// let the system have some time
		#endif
	}

	if (inFlag <= inDbChar)
	{
		if (CheckDoubleLetter(Word, Suggestion))
			return TRUE;
		if ((CallBack != NULL) && (*CallBack)())
			ErrorFunc(eCancel, SET);
		if (ErrorFunc(0, GET) < eNo_Err)
			return FALSE;

		#ifdef _MACINTOSH_
		//SystemTask();		// let the system have some time
		#endif
	}


	if (inFlag <= inMiss)
	{	if (CheckMissingLetter(Word, Suggestion))
			return TRUE;
		if ((CallBack != NULL) && (*CallBack)())
			ErrorFunc(eCancel, SET);
		if (ErrorFunc(0, GET) < eNo_Err)
			return FALSE;

		#ifdef _MACINTOSH_
		//SystemTask();		// let the system have some time
		#endif
	}



	if (inFlag <= inTrans)
	{	if (CheckTransposedLetters(Word, Suggestion))
			return TRUE;
		if ((CallBack != NULL) && (*CallBack)())
			ErrorFunc(eCancel, SET);
		if (ErrorFunc(0, GET) < eNo_Err)
			return FALSE;

		#ifdef _MACINTOSH_
		//SystemTask();		// let the system have some time
		#endif
	}

	if (inFlag <= inExtra)
	{	if (CheckExtraLetter(Word, Suggestion))
			return TRUE;
		if ((CallBack != NULL) && (*CallBack)())
			ErrorFunc(eCancel, SET);
		if (ErrorFunc(0, GET) < eNo_Err)
			return FALSE;

		#ifdef _MACINTOSH_
		//SystemTask();		// let the system have some time
		#endif
	}
	
	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif

	if (inFlag <= inWrong)
	{	if (CheckWrongLetter(Word, Suggestion))
			return TRUE;
		if ((CallBack != NULL) && (*CallBack)())
			ErrorFunc(eCancel, SET);
		if (ErrorFunc(0, GET) < eNo_Err)
			return FALSE;

		#ifdef _MACINTOSH_
		//SystemTask();		// let the system have some time
		#endif
	}


	if (inFlag <= inDouble)
	{
		if (CheckDoubleWord(Word, Suggestion))
			return TRUE;
		if ((CallBack != NULL) && (*CallBack)())
			ErrorFunc(eCancel, SET);
		if (ErrorFunc(0, GET) < eNo_Err)
			return FALSE;
			
		#ifdef _MACINTOSH_
		//SystemTask();		// let the system have some time
		#endif
	}


	return FALSE;
}


CQCheck::CQCheck(short NumBuffers, FioParam * theFile)
	: CMainDict(NumBuffers, theFile)
{


	inFlag = FALSE;
	inOne = FALSE;
}


CQCheck::~CQCheck()
{
}



#ifdef TESTPROGRAM


void main()
{
	char Choice[40];
	char Suggestion[40];
	short Result;
	short Num;
	CQCheck * QCheck;

	char DictName[20];
	short NumBuffers;

	QCheck = new(CQCheck);

	for (;;) {
		printf("\n\n1) Transpose Characters ");
		printf("\n2) CheckExtraLetter");
		printf("\n3) Check One Wrong At ");
		printf("\n4) Check Wrong Letter ");
		printf("\n5) Check Missing Letter ");
		printf("\n---------------------------------");
		printf("\n6) Find Suggestion");
		printf("\n7) Next Suggestion");
		printf("\n8) Open Dictionary");
		printf("\n0) Quit\n");
		gets(Choice);
		Result = atoi(Choice);
		switch (Result) {
		case 1:
			printf("\nWord To Transpose :");
			gets(Choice);
			if (QCheck->CheckTransposedLetters(Dict, Choice, Suggestion))
				printf("Suggestion: %s\n", Suggestion);
			else
				printf("No more finds\n");
			break;
		case 2:
			printf("\nWord To Check :");
			gets(Choice);
			if (QCheck->CheckExtraLetter(Dict, Choice, Suggestion))
				printf("Suggestion: %s\n", Suggestion);
			else
				printf("No more finds\n");
			break;
		case 3:
			printf("\nPosition to Try :");
			gets(Choice);
			Num = atoi(Choice);
			printf("\nWord :");
			gets(Choice);
			if (QCheck->CheckOneWrongAt(Dict, Num, Choice, Suggestion))
				printf("Suggestion: %s\n", Suggestion);
			else
				printf("No more finds\n");
			break;
		case 4:
			printf("\nWord to Check Wrong Letter In :");
			gets(Choice);
			if (QCheck->CheckWrongLetter(Dict, Choice, Suggestion))
				printf("Suggestion: %s\n", Suggestion);
			else
				printf("No more finds\n");
			break;
		case 5:
			printf("\nWord to Check for Missing Letter ");
			gets(Choice);
			if (QCheck->CheckMissingLetter(Dict, Choice, Suggestion))
				printf("Suggestion: %s\n", Suggestion);
			else
				printf("No more finds\n");
			break;
		case 6:
			printf("\nWord to Quick Check ");
			gets(Choice);
			if ( QCheck->QCFind(Dict, Choice, Suggestion))
				printf("Suggestion: %s\n", Suggestion);
			else
				printf("No more finds\n");
			break;
		case 7:
			printf("\nWord to Quick Check ");
			gets(Choice);
			if ( QCheck->QCNext(Dict, Choice, Suggestion))
				printf("Suggestion: %s\n", Suggestion);
			else
				printf("No more finds\n");
			break;
		case 8:
			printf("\nDictionary Name :");
			gets(DictName);
			printf("\nNumber of Buffers :");
			gets(Choice);
			NumBuffers = atoi(Choice);
			Dict = new CMainDict(NumBuffers, DictName);
			if (Dict == NULL)
				printf("\n\a\aError Opening Dictionary....");
			break;
		case 0:
			exit(1);
		}
	}
}

#endif



