#include  <stdio.h>
#include  <string.h>
#include  <stdlib.h>
#include  "GeneType.h"
#include  "PyBasic.h"
#include  "ciku.h"

VOID	ProcGbkHz(VOID);

VOID	CreateUdCikuFile();
JINT	ReadUdcData(CHAR* szUdcName);
JINT	WriteUdcData(CHAR* szUdcName, JINT nTimeStamp);
JINT	AddUdc(JWORD* pwHz2244, JINT nLen);
JINT	DelUdc(JWORD* pwHz2244, JINT nLen);
JINT	PureUdc(VOID);

VOID	ParseSample(VOID);
VOID	ListSysCandiInfo(SysCandi *psc);
JINT	GetXrdCandi(SysCandi* psc, JINT nXrd, JWORD* pwOneCandi);
VOID	ParseRawInputStr(CHAR* szPreedit, JINT* pnOutPreedit);
VOID	DecompPeIntArray(JINT *pnOutPreedit, CHAR* szDspPreedit);

extern JINT    HzcodeToYjcode(JINT nHzcode);
JINT	Hzcode2244ToYjcode(JINT nHzcode);
JINT	GetDyzInfo(JINT nHzcode, JINT* pnDyzYjCode);
JINT	EncodeDyzTo2244(JINT nHzcode, JINT nYjcode);
JINT	FastMatchYinJieStr(CHAR* szPystr);
UCHAR*	RecovDyz2244(UCHAR *szDyz2244);
CHAR	LastChar (JINT nYinjieCode);
CHAR	FirstChar(JINT nYinjieCode);
JINT	ValidButLastChar (JINT nYinjieCode);
JINT	ValidButFirstChar(JINT nYinjieCode);
JINT	ValidAddChar(CHAR ch, JINT nYinjieCode);

VOID	InitCizuItem(JINT nItems);
VOID	InitSingleHanziByYj(JINT nArraySize);
VOID	InitCizuGroupByYj(JINT nArraySize);
VOID	CopyStructCZ(CizuItem* pThisCZ, CizuItem* pNewCZ);
VOID	GetAllCizuItems(JINT nMode);
VOID	GetAllCizuItems_CZPY(JINT nMode);
JINT	GetNextLine(FILE* pfFile, CHAR* szBuf);
VOID	FilterVtoU(UCHAR* pszLine);
VOID	GetHzInfo(UCHAR *pszLine, UCHAR *pszHz, JINT *pnYj, JINT *pnHzNum, JINT *pnYjNum);
VOID	GetYjInfo(UCHAR *pszLine, UCHAR *pszHz, JINT *pnYj, UCHAR *pszHz2244);
JINT	EnumFanganForm(UCHAR *pszHz, JINT *pnYj, JINT nYjNum, JINT *pnbFanganFlag, JINT *pnFanganYj, JINT nMode, JINT nDspMode);
JINT	EnumEnaoForm  (UCHAR* pszHz, JINT *pnYj, JINT nYjNum, JINT *pnbEnaoFlag,   JINT *pnFanganYj, JINT nMode, JINT nDspMode);
JINT	EnumXianForm  (UCHAR* pszHz, JINT *pnYj, JINT nYjNum, JINT *pnbXianFlag,   JINT *pnXianYj,   JINT nMode, JINT nDspMode);
VOID	BuildSingleHzDB(JINT nDspMode);

JINT	CompIntArray(JINT* pnArray1, JINT* pnArray2);
VOID	QuickSort(JINT nFirst, JINT nLast);

VOID	CreateAllData();
VOID	CreateCikuFile();
VOID	SetCkh(CikuHeader *pCkh);
VOID	SetShi(ShIndex *pShi);
VOID	SetDhi(DhIndex *pDhi);
VOID	SetMhi(MhIndex *pMhi);

JINT	WriteCikuData (CHAR* szSysCikuName, JINT nTimeStamp);
JINT	GetCikuData (CHAR* szSysCikuName);
SysCandi* LookupSysCiku(JINT *pnOrgYj, JINT nLenYj, JINT nMatchMode);
VOID	AdjustFreq(JWORD* pwHz2244, JINT nLenThis);

JINT	nItemNum;
JINT	nSortNumber;
CizuItem	  czCZ[MAX_CIZU_ITEMS];
SingleHanziByYj	  shSH[NUM_YINJIE];
CizuGroupByYj	  cgCG[NUM_YINJIE];


VOID InitCizuItem(JINT nItems)
{
	JINT	i, j;

	for (i = 0; i < nItems; i++)
	{
		for (j = 0; j < CIZU_ITEM_LEN; j++)
			czCZ[i].szLine[j]	   = '\0';

		for (j = 0; j < (2 * MAX_CIZU_HZ_NUM); j++)
		{
			czCZ[i].szHz[j]		   = '\0';
			czCZ[i].szHz2244[j]	   = '\0';
		}

		for (j = 0; j < MAX_CIZU_HZ_NUM; j++)
		{
			czCZ[i].nYj[j]		   = 0xFFFF;
			czCZ[i].nXianFormYj[j]	   = 0xFFFF;
			czCZ[i].nFanganFormYj[j]   = 0xFFFF;
		}

		czCZ[i].nHzNum	       = 0;
		czCZ[i].nYjNum	       = 0;
		czCZ[i].nFreq	       = 0;
		czCZ[i].nbIsXianForm   = 0;
		czCZ[i].nbIsFanganForm = 0;
		czCZ[i].nbIsEnaoForm   = 0;
	}
}


VOID CopyStructCZ(CizuItem* pThisCZ, CizuItem* pNewCZ)
{
	JINT	i, nSiz;

	nSiz = sizeof(CizuItem);

	for (i = 0; i < nSiz; i++)
		*((UCHAR*)pNewCZ + i) = *((UCHAR*)pThisCZ + i);
}


VOID InitSingleHanziByYj(JINT nArraySize)
{
	JINT	i, j;

	for (i = 0; i < nArraySize; i++)
	{
		for (j = 0; j < 256; j++)
			shSH[i].szHanzi[j]	      = '\0';
		for (j = 0; j < 64; j++)
			shSH[i].szXianFormList[j]     = '\0';
		shSH[i].nHzNum = shSH[i].nXianFormNum = 0;
	}
}


VOID InitCizuGroupByYj(JINT nArraySize)
{
	JINT	i, j;

	for (i = 0; i < nArraySize; i++)
	{
		cgCG[i].nNumFirstYjIs	  = 0;
		for(j = 0; j < NUM_YINJIE; j++)
			cgCG[i].nNum2ndYjIs[j]	     = 0;
		for(j = 0; j < 1300; j++)
			cgCG[i].nIdxItem[j]	     = 0;
		for(j = 0; j < 60; j++)
			cgCG[i].nIdxFanganItem[j]    = 0;
		cgCG[i].nSizePureCizu	  = 0;
	}
}


VOID GetAllCizuItems(JINT nMode)
{
	FILE   *pfCneFile;
	CHAR	szCneCiku[] = "PyCiku.txt";
	JINT	i, j, m, k, t2, t3, nLen;
	UCHAR	szTmp[256];
	CHAR	szFreq[8];
	JINT	nFreq, nFlag;

	pfCneFile = fopen (szCneCiku, "rb");
	if (pfCneFile == NULL)
	{
		printf ("Failed to Open File %s\n", szCneCiku);
		exit (FALSE);
	}

	k = 0;
	for (t2 = 1; t2 == 1;  )
	{
		memset(szTmp, '\0', 256);
		t2 = GetNextLine(pfCneFile, (CHAR*)szTmp);
		t3 = strlen((CHAR*)szTmp);

		if (t3 > 3)
		{
			for (m = 0; m < t3; m++)
				czCZ[k].szLine[m] = szTmp[m];
			k++;
		}
	}

	fclose (pfCneFile);

	nItemNum = k;
	printf("nItemNum is %d\n", nItemNum);

	for (i = 0; i < nItemNum; i++)
	{
		memset (szFreq, '\0', 8);
		nLen  = strlen ((CHAR*)czCZ[i].szLine);

		nFlag = 0;
		k     = 0;

		for (j = 0; j < nLen; j++)
		{
			if( (czCZ[i].szLine[j] >= '0') && (czCZ[i].szLine[j] <= '9') )
			{
				nFlag = 1;
				szFreq[k++] = czCZ[i].szLine[j];
			}
			else if (nFlag == 1)
				break;
		}

		nFreq = atoi(szFreq);
		if (nFreq > 127)
			nFreq = 127;
		if (nFreq < 1)
			nFreq = 1;

		czCZ[i].nFreq = 1 + ((nFreq - 1) / 9);	     /* Between [1 ~ 15] */
	}
}


/*
**  Get All Cizu Items from CZPY??.TXT. It is an Alt Form of
**  above function GetAllCizuItems(JINT nMode)
*/
VOID GetAllCizuItems_CZPY(JINT nMode)
{
	CHAR   szFileName[20];
	FILE*  pfRawFile;
	JINT   i, k, m, nTmp;
	JINT   t1, t2, t3;
	CHAR   szTmp[100];

	k = nItemNum = 0;
	if (nMode == READ_RAW_CIZU)
		nTmp = 56;
	else
		nTmp = 1;

	for (i = 1; i <= nTmp; i++)
	{
		t1 = t2 = t3 = 0;

		t1 = 15 - ((i+3)/4);			/* Freq number.	 From 15 ~ 1 */
		if (nMode == READ_RAW_CIZU)
			sprintf (szFileName, "./CZPY/CZPY%02d.TXT", i);
		else
			sprintf (szFileName, "./CZPY/allcizu.txt");

		pfRawFile = fopen (szFileName , "rb");
		if (pfRawFile == NULL)
		{
			printf ("Failed to Open File %s\n", szFileName);
			exit (0);
		}

		for (t2 = 1; t2 == 1;  )
		{
			t2 = GetNextLine(pfRawFile, szTmp);
			t3 = strlen(szTmp);

			if (t3 > 3)
			{
				for (m = 0; m < t3; m++)
					czCZ[k].szLine[m] = szTmp[m];
				czCZ[k].nFreq = t1;
				k++;
			}
		}
		fclose (pfRawFile);
	}

	nItemNum = k;
	printf("nItemNum is %d\n", nItemNum);
}


JINT GetNextLine(FILE* pfFile, CHAR* szBuf)
{
	JINT	i = 0;

	do
	{
		fread (&szBuf[i], 1, 1, pfFile);
		i ++;
	} while (!feof(pfFile) && (szBuf[i-1] != 0x0A));

	szBuf[i-1] = '\0';

	if (!feof(pfFile))
		return 1;
	else
		return 0;
}


/*
**  Convert "v" to "u" except that "lv" and "nv" in given line
*/
VOID FilterVtoU(UCHAR *pszLine)
{
	JINT	i;
	UCHAR	ch;

	for (i = 0; pszLine[i] != '\0'; i++)
	{
		ch = pszLine[i];
		if (ch == 'v')
		{
			if ( i > 0 && ((pszLine[i-1] == 'l') || (pszLine[i-1] == 'n')) &&	\
				((pszLine[i+1] < 'a')  || (pszLine[i+1] > 'z')) )
			{
				pszLine[i] = 'v';
			}
			else
				pszLine[i] = 'u';
		}
	}
}


/*
**  Get Hanzi string [pszHz], set default YinjieCode, number [pnHzNum] from pszLine
*/
VOID GetHzInfo(UCHAR *pszLine, UCHAR *pszHz, JINT *pnYj, JINT *pnHzNum, JINT *pnYjNum)
{
	JINT	i, t1;
	UCHAR	ch, chHigh, chLow;
	JINT	nHanziFlag;
	JINT	nThisHz;

	*pnHzNum = 0;
	*pnYjNum = 0;
	i = t1 = 0;
	nHanziFlag = 0;
	chHigh = chLow = '\0';

	for (i = 0; pszLine[i] != '\0'; i++)
	{
		ch = pszLine[i];

		if ((ch >= 0xB0) && (ch <= 0xF7) && (nHanziFlag == 0))
		{
			nHanziFlag	    = 1;
			chHigh		    = ch;
		}
		else if ((ch >= 0xA1) && (ch <= 0xFE) && (nHanziFlag == 1))
		{
			nHanziFlag	    = 0;
			chLow		    = ch;

			pszHz[2 * t1]	    = chHigh;
			pszHz[(2 * t1) + 1] = chLow;
			(*pnHzNum)++;

			nThisHz		    = (JINT)((chHigh << 8) + chLow);
			pnYj[t1]	    = HzcodeToYjcode(nThisHz);
			(*pnYjNum)++;
			t1 ++;
		}
	}

	if (nHanziFlag)
		fprintf (stderr, "Error in GetHzInfo: %s\n", pszLine);
}


/*
**  Check to see if there is any Yinjie String in pszLine and set related info.
**  Steps:   1. Is this string a valid String
**	     2. Is it a DuoYinZi Yinjie of corresponding Hanzi
**	     3. If Yes, find their corresponding code between [0x2001 ~ 0x2244]
*/
VOID GetYjInfo(UCHAR *pszLine, UCHAR *pszHz, JINT *pnYj, UCHAR *pszHz2244)
{
	JINT	i, j, t1, t2, t3, t4;
	JINT	nPyFlag;
	CHAR	ch;
	CHAR	szYjStr[MAX_CIZU_HZ_NUM][7];
	JINT	nThisHz, nDyzYjCode[5], nbCorrectDyz;

	for (i = 0; i < MAX_CIZU_HZ_NUM; i++)
		for (j = 0; j < 7; j++)
			szYjStr[i][j] = '\0';

	t2 = t3 = nPyFlag = 0;
	for (i = 0; pszLine[i] != '\0'; i++)
	{
		ch = pszLine[i];

		if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')))
		{
			nPyFlag		= 1;
			szYjStr[t2][t3] = ch;
			t3 ++;
		}
		else if ((ch == ' ') && (nPyFlag == 1))
		{
			nPyFlag		= 0;
			t2 ++;
			t3 = 0;
		}
	}
	nPyFlag = 0;

	for (i = 0; i < (2 * MAX_CIZU_HZ_NUM); i++)
		pszHz2244[i] = pszHz[i];

	/* Check if it is a DyoYinZi, Is this given Yjcode correct? */
	for (i = 0; (i < MAX_CIZU_HZ_NUM) && (strlen(szYjStr[i]) > 0); i++)
	{
		t1 = FastMatchYinJieStr (szYjStr[i]);
		t2 = pnYj[i];

		/* Is t1 a Valid Yjcode? Is it as same as Yjcode in pnYj? */
		if ((t1 != -1) && (t1 != t2))
		{
			nThisHz = ((JINT)(pszHz[2*i]) << 8) + (JINT)pszHz[2*i + 1];
			t3	= GetDyzInfo(nThisHz, nDyzYjCode);

			nbCorrectDyz = 1;
			for (j = 0; (j < t3) && (nbCorrectDyz == 1); j++)
			{
				if (t1 == nDyzYjCode[j])
				{
					nbCorrectDyz = 0;
					pnYj[i]	     = t1;
					t4 = EncodeDyzTo2244(nThisHz, t1);
					if (t4 != 0xFFFF)
					{
						pszHz2244[2*i]	   = (UCHAR)((t4 & 0xFF00) >> 8);
						pszHz2244[2*i + 1] = (UCHAR)(t4 & 0x00FF);
					}
				}
				else
					nbCorrectDyz = 1;
			}
			if ((t3 > 0) && (nbCorrectDyz == 1))
				printf ("GetYjInfo Error. No this DYZ YjCode.[%s] %s\n", pszLine, &(pszHz[2*i]));
		}
		else if (t1 == -1)
			printf ("GetYjInfo Error. Invalid Yinjie String.[%s]\n", pszLine);
	}
}


/*
**  Is [*pnYj] Fangan Form? If yes, return TRUE, fill pnFanganFlag and pnFanganYj
**			    else,   return FALSE
*/
JINT EnumFanganForm(UCHAR* pszHz, JINT *pnYj, JINT nYjNum, JINT *pnbFanganFlag, JINT *pnFanganYj, JINT nMode, JINT nDspMode)
{
	JINT	i, j, k;
	CHAR	ch1, ch2;
	JINT	res1, res2;
	JINT	nGNRAOEIUVnum = 0;

	CHAR	szTmp1[43], szTmp2[7];
	JINT	nYjNumAlt;

	JINT	nRet = FALSE;

	if ((nMode == ENUM_SIMP) || (nMode == ENUM_SIMP_W))		/* Simple Mode */
		nYjNumAlt = 2;
	else
		nYjNumAlt = nYjNum;

	for (i = 0; (i < (nYjNumAlt - 1)) && (nYjNumAlt >= 2); i++)
	{
		/* Get Last char of first Yinjie string and first char of second Yinjie string */
		ch1 = LastChar (pnYj[i]);
		ch2 = FirstChar(pnYj[i + 1]);

		res1 = res2 = 0xFFFF;
		/*
		**  Not include "an" "en" of first Yinjie
		*/
		if( ((ch1 == 'g') && ((ch2 == 'a') || (ch2 == 'e') ||	\
				      (ch2 == 'o') || (ch2 == 'u') ))	\
		||  ((ch1 == 'r') && ((ch2 == 'a') || (ch2 == 'e') ||	\
				      (ch2 == 'i') || (ch2 == 'o') ||	\
				      (ch2 == 'u') ))			\
		|| (((ch1 == 'n') && ((ch2 == 'a') || (ch2 == 'e') ||	\
				      (ch2 == 'i') || (ch2 == 'o') ||	\
				      (ch2 == 'u') || (ch2 == 'v') ))	\
		    && ( strcmp ( "an", YINJIESTR_CSZ[ pnYj[i] ] ) != 0 )	\
		    && ( strcmp ( "en", YINJIESTR_CSZ[ pnYj[i] ] ) != 0 ) ))
		{
			res1 = ValidButLastChar (pnYj[i]);
			res2 = ValidAddChar (ch1, pnYj[i + 1]);
			if ((res1 != 0xFFFF) && (res2 != 0xFFFF))
			{
				if (nDspMode == F_PRINT)
				{
				/***********************LIST FANGAN FORM ITEMS************************/
				printf ("%-8s  ", pszHz);

				for (k = 0; k < 43; k++)
					szTmp1[k] = '\0';
				for (k = 0; k < 7; k++)
					szTmp2[k] = '\0';

				for (k = 0; k < nYjNum; k++)
				{
					for (j = 0; j < 7; j++)
						szTmp2[j] = '\0';
					strcat(szTmp2, YINJIESTR_CSZ[pnYj[k]]);
					strcat(szTmp2, " ");
					strcat(szTmp1, szTmp2);
				}
				printf ("%-20s | ", szTmp1);

				for (k = 0; k < 43; k++)
					szTmp1[k] = '\0';
				for (k = 0; k < 7; k++)
					szTmp2[k] = '\0';
				for (k = 0; k < nYjNum; k++)
				{
					for (j = 0; j < 7; j++)
						szTmp2[j] = '\0';

					if (k == i)
						strcat(szTmp2, YINJIESTR_CSZ[res1]);
					else if (k == (i + 1))
						strcat(szTmp2, YINJIESTR_CSZ[res2]);
					else
						strcat(szTmp2, YINJIESTR_CSZ[pnYj[k]]);

					strcat(szTmp2, " ");
					strcat(szTmp1, szTmp2);
				}
				printf ("%-20s \n", szTmp1);
				/************************END LISTING HERE*****************************/
				}

				if (nMode == ENUM_SIMP_W)
				{
					pnYj[i]	    = res1;
					pnYj[i + 1] = res2;
					*pnbFanganFlag = TRUE;
				}
				nRet	    = TRUE;
			}
		}
	}
	return (nRet);
}


/*
**  Is [*pnYj] Enao Form? If yes, return TRUE, fill pnFanganFlag and pnFanganYj
**			  else,	  return FALSE
*/
JINT EnumEnaoForm(UCHAR* pszHz, JINT *pnYj, JINT nYjNum, JINT *pnbEnaoFlag, JINT *pnFanganYj, JINT nMode, JINT nDspMode)
{
	JINT	i, j, k, tmp1, tmp2;
	CHAR	ch1, ch2;
	JINT	res1, res2;
	JINT	nGNRAOEIUVnum = 0;

	CHAR	szTmp1[43], szTmp2[7];
	JINT	nYjNumAlt;

	if ((nMode == ENUM_SIMP) || (nMode == ENUM_SIMP_W))		/* Simple Mode */
		nYjNumAlt = 2;
	else
		nYjNumAlt = nYjNum;

	for (i = 0; (i < (nYjNumAlt - 1)) && (nYjNumAlt >= 2); i++)
	{
		/* Get Last char of first Yinjie string and first char of second Yinjie string */
		ch1 = LastChar (pnYj[i]);
		ch2 = FirstChar(pnYj[i + 1]);
		res1 = res2 = 0xFFFF;

		tmp1 = strcmp("a", YINJIESTR_CSZ[ pnYj[i] ]);
		tmp2 = strcmp("e", YINJIESTR_CSZ[ pnYj[i] ]);
		if ( ((tmp1 == 0) || (tmp2 == 0)) && (ch2 == 'n') )
		{
			res2 = ValidButFirstChar(pnYj[i + 1]);

			if (res2 != 0xFFFF)
			{
				if (tmp1 == 0)
					res1 = 2;	/* "an" in YINJIESTR_CSZ */
				else if (tmp2 == 0)
					res1 = 81;	/* "en" in YINJIESTR_CSZ */

				if (nDspMode == F_PRINT)
				{
				/***********************LIST ENAO FORM ITEMS**************************/
				printf ("%-8s  ", pszHz);

				for (k = 0; k < 43; k++)
					szTmp1[k] = '\0';
				for (k = 0; k < 7; k++)
					szTmp2[k] = '\0';

				for (k = 0; k < nYjNum; k++)
				{
					for (j = 0; j < 7; j++)
						szTmp2[j] = '\0';
					strcat(szTmp2, YINJIESTR_CSZ[pnYj[k]]);
					strcat(szTmp2, " ");
					strcat(szTmp1, szTmp2);
				}
				printf ("%-20s | ", szTmp1);

				for (k = 0; k < 43; k++)
					szTmp1[k] = '\0';
				for (k = 0; k < 7; k++)
					szTmp2[k] = '\0';
				for (k = 0; k < nYjNum; k++)
				{
					for (j = 0; j < 7; j++)
						szTmp2[j] = '\0';

					if (k == i)
						strcat(szTmp2, YINJIESTR_CSZ[res1]);
					else if (k == (i + 1))
						strcat(szTmp2, YINJIESTR_CSZ[res2]);
					else
						strcat(szTmp2, YINJIESTR_CSZ[pnYj[k]]);

					strcat(szTmp2, " ");
					strcat(szTmp1, szTmp2);
				}
				printf ("%-20s \n", szTmp1);
				/************************END LISTING HERE*****************************/
				}

				if (nMode == ENUM_SIMP_W)
				{
					pnYj[i]	    = res1;
					pnYj[i + 1] = res2;
				}

				*pnbEnaoFlag = TRUE;
			}
		}
	}
	return (*pnbEnaoFlag);
}


VOID QuickSort(JINT nFirst, JINT nLast)
{
	JINT	nLow, nHigh, t1;

	CizuItem   czTmp, czMidSeptor;

	nLow  = nFirst;
	nHigh = nLast;
	t1 = (nFirst + nLast) /2;

	CopyStructCZ(&(czCZ[t1]), &(czMidSeptor));

	do
	{
		while( CompIntArray(czCZ[nLow].nYj,  czMidSeptor.nYj) < 0)
			nLow ++;

		while( CompIntArray(czCZ[nHigh].nYj, czMidSeptor.nYj) > 0)
			nHigh --;

		if (nLow <= nHigh)
		{
			nSortNumber++;
			if (nSortNumber % 1000 == 0)
				fprintf (stderr, "\b\b\b\b\b\b\b%07d", nSortNumber);

			CopyStructCZ(&(czCZ[nLow]),  &czTmp );
			CopyStructCZ(&(czCZ[nHigh]), &(czCZ[nLow]) );
			CopyStructCZ(&(czTmp),	     &(czCZ[nHigh]) );

			nLow++;
			nHigh--;
		}
	} while (nLow < nHigh);

	if (nFirst < nHigh)
		QuickSort (nFirst, nHigh);
	if (nLow < nLast)
		QuickSort (nLow, nLast);
}

/*
**  Return 1 if *pnArray1 > *pnArray2, return -1 if *pnArray1 < *pnArray2.
**  return 0 if *pnArray1 == *pnArray2.
**  The max length of pnArray is 9[0~8],
*/
JINT CompIntArray(JINT* pnArray1, JINT* pnArray2)
{
	JINT	i = 0;
	while ((pnArray1[i] == pnArray2[i]) && (pnArray1[i] != 0xFFFF))
	{
		i++;
	}

	if ((pnArray1[i] > pnArray2[i]) && (pnArray1[i] != 0xFFFF))
		return 1;
	if ((pnArray1[i] > pnArray2[i]) && (pnArray1[i] == 0xFFFF))
		return -1;
	if ((pnArray2[i] > pnArray1[i]) && (pnArray2[i] != 0xFFFF))
		return -1;
	if ((pnArray2[i] > pnArray1[i]) && (pnArray2[i] == 0xFFFF))
		return 1;

	return 0;
}

/*
**  Build Single Hanzi Database to struct Array shSH[NUM_YINJIE]
**
**  !!! This function was rename as _Old, because it is replaced
**  !!! by new BuildSingleHzDB() to process frequence data of
**  !!! Single Hanzi !!!!    ==> Scott Ma  98-05-20
*/
VOID BuildSingleHzDB_Old(JINT nDspMode)
{
	JINT	i, j, k;
	JINT	nHzcode, nYjcode;

	k = 0;
	for (i = 0xB0; i <= 0xF7; i++)
	{
		for (j = 0xA1; j <= 0xFE; j++)
		{
			if (!( (i == 0xD7) && (j >= 0xFA) ))
			{
				nHzcode = (i << 8) + j;
				nYjcode = Hzcode2244ToYjcode(nHzcode);

				if ((nYjcode >= 0) && (nYjcode <= 414))
				{
					shSH[nYjcode].szHanzi[2 * shSH[nYjcode].nHzNum]	    = (UCHAR)i;
					shSH[nYjcode].szHanzi[2 * shSH[nYjcode].nHzNum + 1] = (UCHAR)j;
					shSH[nYjcode].nHzNum ++;
				}
			}
		}
	}

	k = 0;
	for (i = 0x2001; i <= 0x2244; i++)
	{
		nYjcode = Hzcode2244ToYjcode(i);
		if ((nYjcode >= 0) && (nYjcode <= 414))
		{
			shSH[nYjcode].szHanzi[2 * shSH[nYjcode].nHzNum]	    = (UCHAR)((i >> 8) & 0x00FF);
			shSH[nYjcode].szHanzi[2 * shSH[nYjcode].nHzNum + 1] = (UCHAR)(i & 0x00FF);

			shSH[nYjcode].nHzNum ++;
		}
	}

	if ((nDspMode == SINGLEHZ_DSP_SIMP) || (nDspMode == SINGLEHZ_DSP_FULL))
	{
		for (i = 0; i < 83; i++)
		{
			for (j = 0; j < 5; j++)
				printf ("[%6s] %3d  ", YINJIESTR_CSZ[i * 5 + j], shSH[i * 5 + j].nHzNum);
			printf ("\n");
		}
	}

	if (nDspMode == SINGLEHZ_DSP_FULL)
	{
		for (i = 0; i < 415; i++)
			printf ("[%s] %3d\n%s\n\n", YINJIESTR_CSZ[i], shSH[i].nHzNum, RecovDyz2244(shSH[i].szHanzi));
	}
}



/*
**  Build Single Hanzi Database to struct Array shSH[NUM_YINJIE]
**
**  This function was added to process Frequence Data of Single Hanzi  - Scott Ma 98-05-20
*/
VOID BuildSingleHzDB(JINT nDspMode)
{
	FILE*	pfShFile;
	CHAR	szShName[] = "SingleHz.txt";
	UCHAR  *chFileBuf;
	JINT	nSize, nRes, nLen, i, j, t1;
	UCHAR	szLineBuf[256];
	UCHAR	szPyStr[8];
	JINT	nCurYj;
	JINT	nHzcode;


	pfShFile = fopen(szShName, "rb");
	if (pfShFile == NULL)
	{
		fprintf(stderr, "Failed to open File < %s >.\n", szShName);
		exit(FALSE);
	}

	fseek(pfShFile, 0, SEEK_END);
	nSize = (JINT)ftell(pfShFile);

	fseek(pfShFile, 0, SEEK_SET);

	nCurYj = -1;
	for(t1 = 1; t1 == 1; )
	{
		memset(szLineBuf, 0, 256);
		t1 = GetNextLine(pfShFile, (CHAR*)szLineBuf);
		nLen = strlen((CHAR*)szLineBuf);

		i = 0;
		if((nLen >= 1) && (szLineBuf[0] == '['))
		{
			/* Lines Start with '[' */
			memset(szPyStr, 0, 8);
			for(i = 0; ((i < 6) && (szLineBuf[i + 1] != ']')); i++ )
				szPyStr[i] = szLineBuf[i + 1];

			nRes = FastMatchYinJieStr((CHAR*)szPyStr);
			if ((nRes >= 0) && (nRes <= 414))
				nCurYj = nRes;
			else
				nCurYj = -1;
		}
		else if ((nLen >= 1) && (szLineBuf[0] == '#'))
		{
			/* Just skip Lines start with '#' */
		}
		else if (nLen >= 1)
		{
			/* Normal Lines */
			if((nCurYj >= 0) && (nCurYj <= 414))
			{
				for(i = 0; i < nLen;  )
				{
					if ((szLineBuf[i] >= 0xA1) && (szLineBuf[i + 1] >= 0xA1))    /* It is a MSB of Chinese */
					{
						nHzcode = 0;
						nHzcode = (szLineBuf[i] << 8) + szLineBuf[i + 1];
						nRes = EncodeDyzTo2244(nHzcode, nCurYj);
						if(nRes != 0xFFFF)	  /* It is really a DuoYinZi!! */
							nHzcode = nRes;

						shSH[nCurYj].szHanzi[2 * shSH[nCurYj].nHzNum]	  = (UCHAR)((nHzcode & 0xFF00) >> 8);
						shSH[nCurYj].szHanzi[2 * shSH[nCurYj].nHzNum + 1] = (UCHAR)(nHzcode & 0x00FF);
						shSH[nCurYj].nHzNum ++;
						i += 2;
					}
					else
						i++;
				}
			}
		}
		else
		{
			/* NULL Lines, just skip it */
		}
	}

	fclose(pfShFile);

	if ((nDspMode == SINGLEHZ_DSP_SIMP) || (nDspMode == SINGLEHZ_DSP_FULL))
	{
		for (i = 0; i < 83; i++)
		{
			for (j = 0; j < 5; j++)
				printf ("[%6s] %3d  ", YINJIESTR_CSZ[i * 5 + j], shSH[i * 5 + j].nHzNum);
			printf ("\n");
		}
	}

	if (nDspMode == SINGLEHZ_DSP_FULL)
	{
		for (i = 0; i < 415; i++)
			printf ("[%s] %3d\n%s\n\n", YINJIESTR_CSZ[i], shSH[i].nHzNum, RecovDyz2244(shSH[i].szHanzi));
	}
}


/*
**  Xi'an => xian;   Qi'ang => qiang;	 Ji'an => jian
*/
JINT EnumXianForm(UCHAR* pszHz, JINT *pnYj, JINT nYjNum, JINT *pnbXianFlag, JINT *pnXianYj, JINT nMode, JINT nDspMode)
{
	JINT	j, t2;
	JINT	res1;
	CHAR	szCombYJ[20];

	for (j = 0; j < 20; j++)
		szCombYJ[j] = '\0';

	if( (pnYj[0] != 0xFFFF) && (pnYj[1] != 0xFFFF) )
		strcat( strcat(szCombYJ, YINJIESTR_CSZ[pnYj[0]]),
					 YINJIESTR_CSZ[pnYj[1]]);

	if (strlen(szCombYJ) <= 6 )
	{
		res1 = FastMatchYinJieStr (szCombYJ);
		if (res1 != -1)
		{
			if (nMode == ENUM_SIMP_W)
			{
				if (nYjNum > 2)
				{
					*pnbXianFlag = 1;
					pnXianYj[0] = res1;
					for (j = 2; j < MAX_CIZU_HZ_NUM; j++)
						pnXianYj[j - 1] = pnYj[j];
				}

				if (nYjNum == 2)
				{
					t2 = shSH[res1].nXianFormNum;
					shSH[res1].szXianFormList[4 * t2 + 0] = (UCHAR)pszHz[0];
					shSH[res1].szXianFormList[4 * t2 + 1] = (UCHAR)pszHz[1];
					shSH[res1].szXianFormList[4 * t2 + 2] = (UCHAR)pszHz[2];
					shSH[res1].szXianFormList[4 * t2 + 3] = (UCHAR)pszHz[3];
					shSH[res1].nXianFormNum ++;
				}
			}

			if (nDspMode == F_PRINT)
				printf ("%s\n", pszHz);

			return TRUE;
		}
	}
	return FALSE;
}



VOID ParseSample( )
{
	CHAR	szSampleName[40] = "Sample.txt";
	FILE*	pf;
	JINT	t, m, k, nTmp;
	CHAR	szLine[256];
	JINT	nOutYj[256];
	CHAR	szDecomp[512];
	JINT	nLuNine[9];
	SysCandi *psc;
	JWORD	wOneCandi[9];

	pf = fopen(szSampleName, "rb");
	if (pf == NULL)
	{
		fprintf(stderr, "Failed to open Sample File.\n");
		exit(FALSE);
	}

	for (t = 1; t == 1;  )
	{
		for(m = 0; m < 256; m++)
		{
			szLine[m] = '\0';
			nOutYj[m] = 0xFFFF;
		}

		t = GetNextLine(pf, szLine);
		ParseRawInputStr(szLine, nOutYj);
		for(m = 0; m < 512; m++)
			szDecomp[m] = '\0';
		DecompPeIntArray (nOutYj, szDecomp);
		printf("[Decomp] is %s\n", szDecomp);

		for(m = 0; m < 9; m++)
			nLuNine[m] = 0xFFFF;

		for(m = 0; (m < 9) && (nOutYj[m] != 0); m++)
		{
			nLuNine[m] = (nOutYj[m] & 0x01FF);

			if ((nLuNine[m] < 0) || (nLuNine[m] > 475))
			{
				printf("Error!! in nLuNine\n");
				exit(FALSE);
			}
		}

		psc = LookupSysCiku(nLuNine, m, LU_MATCH_WIDELY);
		AdjustFreq((JWORD*)&(psc->pwDhCandi[psc->nSizDhCandi - 4]), 2);

		printf("\nStruct psc Info for String[%s]\n", szLine);
		printf("====================================================\n");

		for (k = 0; k < psc->nNumMhCandi; k++)
		{
			for (m = 0; m < 9; m++)
				wOneCandi[m] = 0x0000;
			nTmp = GetXrdCandi(psc, k, wOneCandi);

			printf( "%d %s\n", nTmp, RecovDyz2244((UCHAR*)wOneCandi) );
		}
		printf("==============\n");

		for (k = psc->nNumMhCandi; k < (psc->nNumMhCandi + psc->nNumDhCandi); k++)
		{
			for (m = 0; m < 9; m++)
				wOneCandi[m] = 0x0000;
			nTmp = GetXrdCandi(psc, k, wOneCandi);
			printf( "%d %s\n", nTmp, RecovDyz2244((UCHAR*)wOneCandi) );
		}
		printf("=============\n");

		for ( k = (psc->nNumMhCandi + psc->nNumDhCandi);
			k < (psc->nNumMhCandi + psc->nNumDhCandi + psc->nNumShCandi); k++ )
		{
			for (m = 0; m < 9; m++)
				wOneCandi[m] = 0x0000;
			nTmp = GetXrdCandi(psc, k, wOneCandi);
			printf( "%d%s  ", nTmp, RecovDyz2244((UCHAR*)wOneCandi) );
			if ( (k - psc->nNumMhCandi - psc->nNumDhCandi) % 20 == 0)
				printf("\n");
		}
		printf("\n************\n");
		/*
		ListSysCandiInfo(psc);
		*/
	}

	fclose (pf);
}


/*
**  List All Those Information in Struct SysCandi
*/
VOID ListSysCandiInfo(SysCandi *psc)
{
	JINT	i, k, m, n;
	JWORD	wMh[9], wDh[3], wSh[2];

	for(i = 0; i < psc->nLenYj; i++)
	{
		if ((psc->nOrgYj[i] >= 450) && (psc->nOrgYj[i] <= 475) )
			printf("%s ", SHENGMUSTR[psc->nOrgYj[i] - 450]);
		else if ((psc->nOrgYj[i] >= 0) && (psc->nOrgYj[i] < 415) )
			printf("%s ", YINJIESTR_CSZ[psc->nOrgYj[i]]);
	}
	printf("\n\n");

	for(n = 0; n < 9; n++)
		*(wMh + n) = 0x0000;
	for(n = 0; n < 3; n++)
		*(wDh + n) = 0x0000;
	for(n = 0; n < 2; n++)
		*(wSh + n) = 0x0000;

	i = m = 0;
	for(k = 1; i < psc->nNumMhCandi; k++)
	{
		if (psc->pwMhCandi[k] == 0x0000)
		{
			printf( "%s\n", RecovDyz2244((UCHAR*)wMh) );
			i++;
			k++;
			m = 0;
			for(n = 0; n < 9; n++)
				*(wMh + n) = 0x0000;
		}
		else
			wMh[m++] = psc->pwMhCandi[k];
	}
	printf("\n");

	i = m = 0;
	for(k = 1; i < psc->nNumDhCandi; k++)
	{
		if (psc->pwDhCandi[k] == 0x0000)
		{
			printf( "%s\n", RecovDyz2244((UCHAR*)wDh) );
			i++;
			k++;
			m = 0;
			for(n = 0; n < 3; n++)
				*(wDh + n) = 0x0000;
		}
		else
			wDh[m++] = psc->pwDhCandi[k];
	}
	printf("\n");

	i = m = 0;
	for(k = 0; i < psc->nNumShCandi; k++)
	{
		if (psc->pwShCandi[k] == 0x0000)
		{
			printf( "%s  ", RecovDyz2244((UCHAR*)wSh) );
			i++;
			m = 0;
			for(n = 0; n < 2; n++)
				*(wSh + n) = 0x0000;
		}
		else
			wSh[m++] = psc->pwShCandi[k];
	}
	printf("\n\n");
}



/*
**  Get the Xrd Candidates which store in structure psc. The content is to be
**  store to pwOneCandi.
**  Notice:  Range of nXrd is between [0 ~ (nTmp - 1)].
**	     Mh -> Dh -> Sh
**  Return:  Valid Length of this candidate in JWORD.
*/
JINT GetXrdCandi(SysCandi* psc, JINT nXrd, JWORD* pwOneCandi)
{
	JINT	i, k, m, nTmp;
	JINT	nRet;

	nRet  = 0;
	nTmp  = psc->nNumMhCandi + psc->nNumDhCandi + psc->nNumShCandi;

	if ((nXrd < 0) || (nXrd > (nTmp - 1)))
		return nRet;

	if (nXrd < psc->nNumMhCandi)
	{
		m = 0;							  /* [0 ~ (nNumMhCandi - 1)] */
		for (k = 0; k < psc->nSizMhCandi; k++)
		{
			if (m == nXrd)
			{
				k++;
				for(i = 0; psc->pwMhCandi[k] != 0x0000;	 )
					pwOneCandi[i++] = psc->pwMhCandi[k++];
				nRet = i;
				break;
			}
			else if (psc->pwMhCandi[k] == 0x0000)
				m++;
		}
	}
	else if ( (nXrd >= psc->nNumMhCandi) && (nXrd < (psc->nNumMhCandi + psc->nNumDhCandi)) )
	{
		m = psc->nNumMhCandi;		  /* [nNumMhCandi ~ (nNumMhCandi + nNumDhCandi - 1)] */
		for (k = 0; k < psc->nSizDhCandi; k++)
		{
			if (m == nXrd)
			{
				k++;
				for(i = 0; psc->pwDhCandi[k] != 0x0000;	 )
					pwOneCandi[i++] = psc->pwDhCandi[k++];
				nRet = i;
				break;
			}
			else if (psc->pwDhCandi[k] == 0x0000)
				m++;
		}
		nRet  = 2;
	}
	/*
	**  Special Consideration for Single Hanzi Area: Because there is 'Xian' Question
	**  Here!!!! nRet may be 2.
	*/
	else	   /* Single Hanzi Area */
	{
		m = psc->nNumMhCandi + psc->nNumDhCandi;
		for (k = 0; k < psc->nSizShCandi; k++)
		{
			if (m == nXrd)
			{
				for(i = 0; psc->pwShCandi[k] != 0x0000;	 )
					pwOneCandi[i++] = psc->pwShCandi[k++];
				nRet = i;
				break;
			}
			else if (psc->pwShCandi[k] == 0x0000)
				m++;
		}
	}

	return nRet;
}


int main(int argc, char **argv)
{
	CHAR	 szSysCikuName[40] = "PyCiku.dat";

	CHAR	 szUdcName[40] = "UdCiku.dat";
	JINT	 nRes;

	CreateUdCikuFile();

	nRes = ReadUdcData(szUdcName);
	if (nRes != TRUE)
		printf("Failed in ReadUdcData().\n");

	nRes = WriteUdcData(szUdcName, 0);
	if (nRes != TRUE)
		printf("Failed in WriteUdcData().\n");

	CreateAllData();
	CreateCikuFile();
	exit(0);

	/*
	GetCikuData (szSysCikuName);
	ParseSample();
	WriteCikuData (szSysCikuName, 0);
	*/
}

