// USound.cp
// USound.h
// ----------------------------------------------------------------------------------
// Sound translator for the Spelling Checker.
//
// Note: This file is proprietary and confidential to Art Pollard
//	and Lextek Internation.  
// Copyright 1994 Art Pollard / LexTek International
//
// This translates a sound into a spell for a prefix.  It is passed a 'sound' 
// represented by a number.  IT then returns a prefix for the word with that
// sound.
// 
// ----------------------------------------------------------------------------------
// History:
// 		Art Pollard			June 94
//			Original.  Simple read/write functions.
//		Clark Goble			08/13/94
//			Fixed in up in minor ways
// ----------------------------------------------------------------------------------



#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "USound.h"


//#define TEST


// ----------------------------------------------------------------------------------
//	USound		- Sound constructor
// ----------------------------------------------------------------------------------
// This makes up the static list of prefixes 

USound::USound()
{
	 CurrentRuleSet = NULL;
	 Position = 0;

	 static HeadStart RuleTable[111] = {
		{"b",   1}, /* (0) B  */
		{NULL,  0},
		{"c",   1}, /* (2) CH */
		{"k",   1},
		{"tch", 3},
		{NULL,  0},
		{"c",   1}, /* (6) CHORKORSH */
		{"k",   1},
		{"q",   1},
		{"sch", 3},
		{"sh",  2},
		{"tch", 3},
		{NULL,  0},
		{"c",   1}, /* (13) CH OR Z */
		{"ex",  2},
		{"gz",  2},
		{"k",   1},
		{"tch", 3},
		{"ts",  2},
		{"tz",  2},
		{"x",   1},
		{"z",   1},
		{NULL,  0},
		{"cz",  2}, /* (23) TS OR Z */
		{"ex",  2},
		{"gz",  2},
		{"ts",  2},
		{"tz",  2},
		{"x",   1},
		{"z",   1},
		{NULL,  0},
		{"d",   1}, /* (31) D */
		{NULL,  0},
		{"f",   1}, /* (33) F */
		{"ph",  2},
		{NULL,  0},
		{"g",   1}, /* (36) G */
		{NULL,  0},
		{"h",   1}, /* (38) H */
		{"who", 3},
		{NULL,  0},
		{"dj",  2}, /* (41) J */
		{"g",   1},
		{"j",   1},
		{NULL,  0},
		{"c",   1}, /* (45) K */
		{"k",   1},
		{"q",   1},
		{NULL,  0},
		{"l",   1}, /* (49) L */
		{NULL,  0},
		{"m",   1}, /* (51) M */
		{NULL,  0},
		{"gn",  2}, /* (53) N */
		{"kn",  2},
		{"mn",  2},
		{"n",   1},
		{"pn",  2},
		{NULL,  0},
		{"p",   1}, /* (59) P */
		{NULL,  0},
		{"r",   1}, /* (61) R */
		{"wr",  2},
		{NULL,  0},
		{"ce",  2}, /* (64) S */
		{"ci",  2},
		{"cy",  2},
		{"ps",  2},
		{"s",   1},
		{NULL,  0},
		{"ch",  2}, /* (70) SH */
		{"sch", 3},
		{"sh",  2},
		{NULL,  0},
		{"pt",  2}, /* (74) T */
		{"t",   1},
		{"th",  2},
		{"tw",  2},
		{NULL,  0},
		{"ts",  2}, /* (79) TS */
		{"tz",  2},
		{"z",   1},
		{NULL,  0},
		{"v",   1}, /* (83) V */
		{NULL,  0},
		{"w",   1}, /* (85) W */
		{NULL,  0},
		{"cz",  2}, /* (87) Z */
		{"ex",  2},
		{"gz",  2},
		{"ts",  2},
		{"tz",  2},
		{"x",   1},
		{"z",   1},
		{NULL,  0},
		{"a",   1}, /* (95) VOWEL */
		{"e",   1},
		{"i",   1},
		{"o",   1},
		{"u",   1},
		{"y",   1},
		{NULL,  0},
		{"c",   1}, /* (102) CHORK */
		{"ch",  2},
		{"cz",  2},
		{"k",   1},
		{"kh",  2},
		{"q",   1},
		{"tch", 3},
		{NULL,  0},
		{NULL,  0}
	};          

	B    = &RuleTable[0];
	CH   = &RuleTable[2];
	CHORKORSH = &RuleTable[6];
	CHORZ = &RuleTable[13];
		

	TSORZ = &RuleTable[23];
	D    = &RuleTable[31];
	F    = &RuleTable[33];
	G    = &RuleTable[36];
	H    = &RuleTable[38];
	J    = &RuleTable[41];
	K    = &RuleTable[45];
	L    = &RuleTable[49];
	M    = &RuleTable[51];
	N    = &RuleTable[53];
	P    = &RuleTable[59];
	R    = &RuleTable[61];
	S    = &RuleTable[64];
	SH   = &RuleTable[70];
	T    = &RuleTable[74];
	TS   = &RuleTable[79];
	V    = &RuleTable[83];
	W    = &RuleTable[85];
	Z    = &RuleTable[87];
	VOWEL = &RuleTable[95];
	CHORK = &RuleTable[102];
}; // USound

// ----------------------------------------------------------------------------------
//	~USound		- Sound destructor
// ----------------------------------------------------------------------------------
// Clears the memory
USound::~USound()
{
//	 if (CurrentRuleSet != NULL)
//	 	free(CurrentRuleSet);
	 Position = 0;

}; // ~USound

// ----------------------------------------------------------------------------------
//	Reset	- Clears the memory
// ----------------------------------------------------------------------------------
// Clears the memory, but doesn't free the Rule Table

void USound::Reset()
{
//	 if (CurrentRuleSet != NULL)
//	 	free(CurrentRuleSet);
	 Position = 0;
}; // Reset

// ----------------------------------------------------------------------------------
//	Start	- Starts a prefix match
// ----------------------------------------------------------------------------------
// 

char *USound::Start(short Prefix, short *Length)
{
	switch (Prefix) {
		case Initial_B :
			CurrentRuleSet = B;
			Position = 0;
			*Length = CurrentRuleSet[Position].Length;
			return (CurrentRuleSet[Position].WordPrefix);
		case Initial_CH:
			CurrentRuleSet = CH;
			Position = 0;
			*Length = CurrentRuleSet[Position].Length;
			return (CurrentRuleSet[Position].WordPrefix);
		case Initial_CHORKORSH:
			CurrentRuleSet = CHORKORSH;
			Position = 0;
			*Length = CurrentRuleSet[Position].Length;
			return (CurrentRuleSet[Position].WordPrefix);
		case Initial_CHORZ:
			CurrentRuleSet = CHORZ;
			Position = 0;
			*Length = CurrentRuleSet[Position].Length;
			return (CurrentRuleSet[Position].WordPrefix);
		case Initial_TSORZ:
			  CurrentRuleSet = TSORZ;
			  Position = 0;
			  *Length = (CurrentRuleSet)[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_D:
			  CurrentRuleSet = D;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_F:
			  CurrentRuleSet = F;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_G:
			  CurrentRuleSet = G;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_H:
			  CurrentRuleSet = H;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_J:
			  CurrentRuleSet = J;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_K:
			  CurrentRuleSet = K;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_L:
			  CurrentRuleSet = L;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_M:
			  CurrentRuleSet = M;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_N:
			  CurrentRuleSet = N;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_P:
			  CurrentRuleSet = P;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_R:
			  CurrentRuleSet = R;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_S:
			  CurrentRuleSet = S;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_SH:
			  CurrentRuleSet = SH;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_T:
			  CurrentRuleSet = T;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_TS:
			  CurrentRuleSet = TS;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_V:
			  CurrentRuleSet = V;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_W:
			  CurrentRuleSet = W;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_Z:
			  CurrentRuleSet = Z;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_VOWEL:
			  CurrentRuleSet = VOWEL;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
			  return (CurrentRuleSet[Position].WordPrefix);
		case Initial_CHORK:
			  CurrentRuleSet = CHORK;
			  Position = 0;
			  *Length = CurrentRuleSet[Position].Length;
		  	  return (CurrentRuleSet[Position].WordPrefix);
		}; // case
		
	return (NULL); // shouldn't ever be called except on error;
}; // Start

// ----------------------------------------------------------------------------------
//	NextPhoneme	- gets the next prefix match
// ----------------------------------------------------------------------------------
// 

char *USound :: NextPhoneme(short *Length)
{
	Position++;
	*Length = CurrentRuleSet[Position].Length;
		
	#ifdef _MACINTOSH_
	//SystemTask();		// let the system have some time
	#endif

	return ( CurrentRuleSet[Position].WordPrefix );
};



#ifdef TEST


void main()
{
	short Length;
	char *Prefix;
	short Counter;
	char Choice[20];
	short Result1;
	short Result2;
	USound *First;
	
	First = new USound;
	for(;;) {
		printf("\n\n1) List All Prefixes for Rule");
		printf("\n0) Quit\n");
		gets(Choice);
		Result1 = atoi(Choice);
		switch (Result1) 
		{
		  case 1:
			  printf("\n Rule Number (1-24) :");
			  gets(Choice);
			  Result2 = atoi (Choice);
			  Counter = 0;
			  Prefix = First->Start(Result2,&Length);
			  printf("\n%d Prefix :%s  Length %d",Counter,Prefix,(short)Length);
			  Counter++;
			  while (Length !=0) {
			   Prefix = First->NextPhoneme(&Length);
			   printf("\n%d Prefix :%s  Length %d",Counter,Prefix,(short)Length);
			   Counter++;
			  }
			  break;
		  case 0: exit(1);
		}
	}
}
	

#endif

