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

JINT	GbkHzcodeToYjcode(JINT nHzcode);
JINT	GetNextLine(FILE* pfFile, CHAR* szBuf);
VOID	ProcGbkHz(VOID);
VOID	ReadGbkLine(VOID);
VOID	CreateGbkHzcodeToYj();
VOID	TestGbkHzcodeToYj();
JINT	FastMatchYinJieStr(CHAR* szPystr);
JINT	HzcodeToYjcode(JINT nHzcode);
VOID	Show32To9Int(JUINT *pnHzYj32);

static	UCHAR	szGbkLine[30000][40];
static	JWORD	wGbkCode[30000];
static	JINT	nGbkYj[30000];
static	JINT	nGbkLine;

JINT	nGbkNumByYj[NUM_YINJIE];
JWORD	wGbkHzByYj[NUM_YINJIE][400];
JINT	nYj[0xFFFF];

VOID ProcGbkHz(VOID)
{
	JINT	i, nTmp, nTmp2, nTmp3;

	ReadGbkLine();

	memset (nGbkNumByYj, '\0', NUM_YINJIE * sizeof(JINT));
	for (i = 0; i < NUM_YINJIE; i++)
		memset (wGbkHzByYj[i], '\0', 400 * sizeof(JWORD));

	nTmp2 = nTmp3 = 0;
	nTmp = 0;
	for (i = 0; i < nGbkLine; i++)
	{
		if (nGbkYj[i] != 0xFFFF)
		{
			/* From 0xB0A1 to 0xF7FF was processed as Normal GB2312 Hanzi */
			if( (wGbkCode[i] >= 0x8140) && ( ! ( ((wGbkCode[i] & 0xFF00) >= 0xB000) && ((wGbkCode[i] & 0xFF00) <= 0xF700)
							  && ((wGbkCode[i] & 0x00FF) >= 0x00A1))) )
			{
				wGbkHzByYj[nGbkYj[i]][nGbkNumByYj[nGbkYj[i]]] = wGbkCode[i];
				nGbkNumByYj[nGbkYj[i]] ++;
				nTmp2 ++;
			}
		}
		else
		{
		/*	printf ("!!%s", szGbkLine[i]);	*/
			nTmp ++;
		}
	}
	printf ("Total %d Non_Standard Yinjie in < GBK.txt >\n", nTmp);

	for (i = 0; i < NUM_YINJIE; i++)
	{
		if ((i != 0) && (i % 5 == 0))
			printf ("\n");
		printf("%3d|%-6s[%3d] ", i, YINJIESTR_CSZ[i], nGbkNumByYj[i]);
	}
	printf("\n");

	/**
	CreateGbkHzcodeToYj();
	TestGbkHzcodeToYj();
	**/
}


VOID ReadGbkLine(VOID)
{
	FILE*	pfGbk;
	CHAR	szGbkName[] = "GBK.txt";
	UCHAR	szTmp[40];
	JINT	i, k, m, t2, t3;
	JINT	nTmp, nInvalidNum;

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

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

		if (t3 > 2)
		{
			for (m = 0; m < t3; m++)
				szGbkLine[k][m] = szTmp[m];
			k++;
		}
	}

	fclose (pfGbk);
	nGbkLine = k;
	printf("nGbkLine is %d\n", nGbkLine);

	/* Get GBK Hanzi Code. */
	memset (wGbkCode, 0, sizeof(JWORD) * 30000);
	for (i = 0; i < nGbkLine; i++)
		wGbkCode[i] = (JWORD)(((JWORD)szGbkLine[i][7] << 8) + szGbkLine[i][8]);

	/* Get GBK Yinjie Code. If not a standard Yinjie, use 0xFFFF instead */
	nInvalidNum = 0;
	memset (nGbkYj, 0, sizeof(JINT) * 30000);
	for (i = 0; i < nGbkLine; i++)
	{
		memset(szTmp, '\0', 40);
		for (k = 10; (szGbkLine[i][k] >= 'a') && (szGbkLine[i][k] <= 'z'); k++)
			szTmp[k - 10] = szGbkLine[i][k];

		nTmp = FastMatchYinJieStr((CHAR*)szTmp);
		if (nTmp == -1)
		{
			nGbkYj[i] = 0xFFFF;
			nInvalidNum ++;
		}
		else
			nGbkYj[i] = nTmp;
	}

	printf("nInvalidNum in GBK.txt is %d\n", nInvalidNum);
}


/*
**  Create (JUINT)GBKHZCODETOYJ[] array to replace GBHZCODETOYJ[].
**  From 0x8140 to 0xFEFE, not include 0xA140 to 0xA9FE.
**  Notice: Reserved Area I and Reserved Area II are also included
**  In this Array.
**
**  This data is needed in file < PyBasic.h >
*/
VOID CreateGbkHzcodeToYj()
{
	JINT	i, j, k, w, nTmp, nHzcode;
	JUINT	nHzYj32[32];

	/* Init nYj[] Array */
	for (i = 0; i < 0xFFFF; i++)
		nYj[i] = 0x01FF;

	/* Fill nYj[] with data come from nGbkYj[] */
	w = 0;
	for (i = 0; i < nGbkLine; i++)
		if ((nGbkYj[i] >= 0) && (nGbkYj[i] < NUM_YINJIE))
		{
			nYj[wGbkCode[i]] = nGbkYj[i];
			w++;
		}
	printf("Valid Yinjie in nGbkYj is %d\n", w);

	/* I => High, J => Low */
	/* Recover these GB Info by GOOD data */
	w = 0;
	for (i = 0xB0; i <= 0xF7; i++)
		for (j = 0xA1; j <= 0xFE; j++)
		{
			nHzcode = (i << 8) + j;
			nTmp	= HzcodeToYjcode(nHzcode);
			if ((nTmp >= 0) && (nTmp < NUM_YINJIE))
			{
				nYj[nHzcode] = nTmp;
				w++;
			}
		}
	printf("Valid Yinjie in HzcodeToYjcode() is %d\n", w);


	/* [0x8140 ~ 0xA0FE], include 0x??7F */
	/* 32 * 191 */
	w = 0;
	for (k = 0; k < 32; k++)
		nHzYj32[k] = 0x01FF;

	for (i = 0x81; i <= 0xA0; i++)
	{
		for (j = 0x40; j <= 0xFE; j++)
		{
			nHzcode	   = (i << 8) + j;
			nHzYj32[w] = nYj[nHzcode];
			w++;
			if (w == 32)
			{
				Show32To9Int(nHzYj32);
				w = 0;
				for (k = 0; k < 32; k++)
					nHzYj32[k] = 0x01FF;
			}
		}
	}
	if (w != 0)
		Show32To9Int(nHzYj32);
	printf("\n**0x8140 ~ 0xA0FE**\n");

	/* 85 * 191 */
	w = 0;
	for (k = 0; k < 32; k++)
		nHzYj32[k] = 0x01FF;

	for (i = 0xAA; i <= 0xFE; i++)
	{
		for (j = 0x40; j <= 0xFE; j++)
		{
			nHzcode	   = (i << 8) + j;
			nHzYj32[w] = nYj[nHzcode];
			w++;
			if (w == 32)
			{
				Show32To9Int(nHzYj32);
				w = 0;
				for (k = 0; k < 32; k++)
					nHzYj32[k] = 0x01FF;
			}
		}
	}
	if (w != 0)
		Show32To9Int(nHzYj32);
	printf("\n**0xAA40 ~ 0xFEFE**\n");
}


/*
**  pnHzYj32 point to a 32 int array which indicates the Yinjie code.
*/
VOID Show32To9Int(JUINT *pnHzYj32)
{
	JUINT	nNine[9];
	JUINT	i, nFrom, nTo, nToMode, nTmp1, nTmp2;

	for (i = 0; i < 9; i++)
		nNine[i] = 0x00000000;

	for (i = 0; i < 32; i++)
	{
		nFrom = (i * 9) / 32;
		nTo   = ((i + 1) * 9) / 32;
		if (nFrom == nTo)
		{
			nToMode = 32 - (((i + 1) * 9) % 32);
			nTmp1	= nNine[nFrom];
			nTmp2	= pnHzYj32[i] << nToMode;
			nTmp2  |= nTmp1;
			nNine[nFrom] |= nTmp2;
		}
		else /* (nTo > nFrom) */
		{
			nToMode = ((i + 1) * 9) % 32;

			nTmp1	= nNine[nFrom];
			nTmp2	= pnHzYj32[i] >> nToMode;
			nTmp2  |= nTmp1;
			nNine[nFrom] |= nTmp2;

			nTmp1	= nNine[nTo];
			nTmp2	= pnHzYj32[i] << (32 - nToMode);
			nTmp2  |= nTmp1;
			nNine[nTo] |= nTmp2;
		}
	}

	printf("    ");
	for (i = 0; i < 9; i++)
		printf("0x%08X, ", nNine[i]);
	printf("\n");
}


VOID TestGbkHzcodeToYj()
{
	UCHAR	chHz[3];
	JINT	nHzcode;
	JINT	nYj;
	JINT	w;

	w = 0;
	chHz[2] = '\0';
	for (chHz[0] = 0x81; chHz[0] <= 0xFE; chHz[0]++)
	{
		for (chHz[1] = 0x40; chHz[1] <= 0xFE; chHz[1]++)
		{
			nHzcode = ((JINT)chHz[0] << 8) + (JINT)chHz[1];
			nYj	= GbkHzcodeToYjcode(nHzcode);
			printf("0x%02X%02X  %s	", (JUINT)chHz[0], (JUINT)chHz[1], chHz);
			if (nYj == 0x01FF)
				printf("[NONE]\n");
			else if ((nYj >= 0) && (nYj < NUM_YINJIE ))
			{
				printf("%s\n", YINJIESTR_CSZ[nYj]);
				w++;
			}
			else
				printf("*Error*\n");
		}
	}

	printf("Valid Yinjie in GBKHZCODETOYJ[] is %d", w);
}


