/******************************Module*Header*******************************\
* Module Name: sjis.c
*
* Single byte <--> Double byte code.  Not needed in final Pegasus DLL
*
* Created: 02-Oct-1996 08:28:15
* Author: Patrick Haluptzok patrickh
*
* Copyright (c) 1996 Microsoft Corporation
\**************************************************************************/

#include "common.h"
#include "xjis.h"

const WORD mpSbcsDbcs[CHAR_LASTSBCS - CHAR_FIRSTSBCS + 1] =
{
	0x8140, // 0x20
	0x8149, // 0x21
	0x8168, // 0x22
	0x8194, // 0x23
	0x8190, // 0x24
	0x8193, // 0x25
	0x8195, // 0x26
	0x8166, // 0x27
	0x8169, // 0x28
	0x816a, // 0x29
	0x8196, // 0x2a
	0x817b, // 0x2b
	0x8143, // 0x2c
    0x817c, // 0x2d
	0x8144, // 0x2e
	0x815e, // 0x3f
	0x824f, // 0x30
	0x8250, // 0x31
	0x8251, // 0x32
	0x8252, // 0x33
	0x8253, // 0x34
	0x8254, // 0x35
	0x8255, // 0x36
	0x8256, // 0x37
	0x8257, // 0x38
	0x8258, // 0x39
	0x8146, // 0x3a
	0x8147, // 0x3b
	0x8183, // 0x3c
	0x8181, // 0x3d
	0x8184, // 0x3e
	0x8148, // 0x3f
	0x8197, // 0x40
	0x8260, // 0x41
	0x8261, // 0x42
	0x8262, // 0x43
	0x8263, // 0x44
	0x8264, // 0x45
	0x8265, // 0x46
	0x8266, // 0x47
	0x8267, // 0x48
	0x8268, // 0x49
	0x8269, // 0x4a
	0x826a, // 0x4b
	0x826b, // 0x4c
	0x826c, // 0x4d
	0x826d, // 0x4e
	0x826e, // 0x4f
	0x826f, // 0x50
	0x8270, // 0x51
	0x8271, // 0x52
	0x8272, // 0x53
	0x8273, // 0x54
	0x8274, // 0x55
	0x8275, // 0x56
	0x8276, // 0x57
	0x8277, // 0x58
	0x8278, // 0x59
	0x8279, // 0x5a
	0x816d, // 0x5b
	0x818f, // 0x5c
	0x816e, // 0x5d
	0x814f, // 0x5e
	0x8151, // 0x5f
	0x814d, // 0x60
	0x8281, // 0x61
	0x8282, // 0x62
	0x8283, // 0x63
	0x8284, // 0x64
	0x8285, // 0x65
	0x8286, // 0x66
	0x8287, // 0x67
	0x8288, // 0x68
	0x8289, // 0x69
	0x828a, // 0x6a
	0x828b, // 0x6b
	0x828c, // 0x6c
	0x828d, // 0x6d
	0x828e, // 0x6e
	0x828f, // 0x6f
	0x8290, // 0x70
	0x8291, // 0x71
	0x8292, // 0x72
	0x8293, // 0x73
	0x8294, // 0x74
	0x8295, // 0x75
	0x8296, // 0x76
	0x8297, // 0x77
	0x8298, // 0x78
	0x8299, // 0x79
	0x829a, // 0x7a
	0x816f, // 0x7b
	0x8162, // 0x7c
	0x8170, // 0x7d
	0x8160  // 0x7e
};

const WORD mpchkatawkata[CHAR_LASTKATA - CHAR_FIRSTKATA + 1] =
{
	0x8142, // 0xa1
	0x8175, // 0xa2
	0x8176, // 0xa3
	0x8141, // 0xa4
	0x8145, // 0xa5
	0x8392, // 0xa6
	0x8340, // 0xa7
	0x8342, // 0xa8
	0x8344, // 0xa9
	0x8346, // 0xaa
	0x8348, // 0xab
	0x8383, // 0xac
	0x8385, // 0xad
	0x8387, // 0xae
	0x8362, // 0xaf
	0x815B, // 0xb0
	0x8341, // 0xb1
	0x8343, // 0xb2
	0x8345, // 0xb3
	0x8347, // 0xb4
	0x8349, // 0xb5
	0x834a, // 0xb6
	0x834c, // 0xb7
	0x834e, // 0xb8
	0x8350, // 0xb9
	0x8352, // 0xba
	0x8354, // 0xbb
	0x8356, // 0xbc
	0x8358, // 0xbd
	0x835a, // 0xbe
	0x835c, // 0xbf
	0x835e, // 0xc0
	0x8360, // 0xc1
	0x8363, // 0xc2
	0x8365, // 0xc3
	0x8367, // 0xc4
	0x8369, // 0xc5
	0x836a, // 0xc6
	0x836b, // 0xc7
	0x836c, // 0xc8
	0x836d, // 0xc9
	0x836e, // 0xca
	0x8371, // 0xcb
	0x8374, // 0xcc
	0x8377, // 0xcd
	0x837a, // 0xce
	0x837d, // 0xcf
	0x837e, // 0xd0
	0x8380, // 0xd1
	0x8381, // 0xd2
	0x8382, // 0xd3
	0x8384, // 0xd4
	0x8386, // 0xd5
	0x8388, // 0xd6
	0x8389, // 0xd7
	0x838a, // 0xd8
	0x838b, // 0xd9
	0x838c, // 0xda
	0x838d, // 0xdb
	0x838f, // 0xdc
	0x8393, // 0xdd
	0x814a, // 0xde
	0x814b  // 0xdf
};

// mpwkanachkana and mpwpuncchpunc convert double byte characters back to single byte.

const BYTE mpwkanachkana[KANA_LASTMAP - KANA_FIRSTMAP + 1] =
{
0xA7,   // 0x8340
0xB1,   // 0x8341
0xA8,   // 0x8342
0xB2,   // 0x8343
0xA9,   // 0x8344
0xB3,   // 0x8345
0xAA,   // 0x8346
0xB4,   // 0x8347
0xAB,   // 0x8348
0xB5,   // 0x8349
0xB6,   // 0x834a
0,      // 0x834b
0xB7,   // 0x834c
0,      // 0x834d
0xB8,   // 0x834e
0,      // 0x834f
0xB9,   // 0x8350
0,      // 0x8351
0xBA,   // 0x8352
0,      // 0x8353
0xBB,   // 0x8354
0,      // 0x8355
0xBC,   // 0x8356
0,      // 0x8357
0xBD,   // 0x8358
0,      // 0x8359
0xBE,   // 0x835a
0,      // 0x835b
0xBF,   // 0x835c
0,      // 0x835d
0xC0,   // 0x835e
0,      // 0x835f
0xC1,   // 0x8360
0,      // 0x8361
0xAF,   // 0x8362
0xC2,   // 0x8363
0,      // 0x8364
0xC3,   // 0x8365
0,      // 0x8366
0xC4,   // 0x8367
0,      // 0x8368
0xC5,   // 0x8369
0xC6,   // 0x836a
0xC7,   // 0x836b
0xC8,   // 0x836c
0xC9,   // 0x836d
0xCA,   // 0x836e
0,      // 0x836f
0,      // 0x8370
0xCB,   // 0x8371
0,      // 0x8372
0,      // 0x8373
0xCC,   // 0x8374
0,      // 0x8375
0,      // 0x8376
0xCD,   // 0x8377
0,      // 0x8378
0,      // 0x8379
0xCE,   // 0x837a
0,      // 0x837b
0,      // 0x837c
0xCF,   // 0x837d
0xD0,   // 0x837e
0,      // 0x837f
0xD1,   // 0x8380
0xD2,   // 0x8381
0xD3,   // 0x8382
0xAC,   // 0x8383
0xD4,   // 0x8384
0xAD,   // 0x8385
0xD5,   // 0x8386
0xAE,   // 0x8387
0xD6,   // 0x8388
0xD7,   // 0x8389
0xD8,   // 0x838a
0xD9,   // 0x838b
0xDA,   // 0x838c
0xDB,   // 0x838d
0,      // 0x838e
0xDC,   // 0x838f
0,      // 0x8390
0,      // 0x8391
0xA6,   // 0x8392
0xDD    // 0x8393
};

const BYTE mpwpuncchpunc[PUNC_LASTMAP - PUNC_FIRSTMAP + 1] = {
0x20,   // 0x8140
0xA4,   // 0x8141
0xA1,   // 0x8142
0x2C,   // 0x8143 ,
0x2E,   // 0x8144 .
0xA5,   // 0x8145
0x3A,   // 0x8146 :
0x3B,   // 0x8147 ;
0x3F,   // 0x8148 ?
0x21,   // 0x8149 !
0xDE,   // 0x814A
0xDF,   // 0x814B
0,      // 0x814C
0x60,   // 0x814D
0,      // 0x814E
0x5E,   // 0x814F ^
0,      // 0x8150
0x5F,   // 0x8151
0,      // 0x8152
0,      // 0x8153
0,      // 0x8154
0,      // 0x8155
0,      // 0x8156
0,      // 0x8157
0,      // 0x8158
0,      // 0x8159
0,      // 0x815A
0xB0,   // 0x815B
0,      // 0x815C
0x2D,   // 0x815D -
0x2F,   // 0x815E /
0x5C,   // 0x815F
0x7E,   // 0x8160
0,      // 0x8161
0x7C,   // 0x8162
0,      // 0x8163
0,      // 0x8164
0x27,   // 0x8165
0x27,   // 0x8166
0x22,   // 0x8167
0x22,   // 0x8168
0x28,   // 0x8169 (
0x29,   // 0x816A )
0,      // 0x816B
0,      // 0x816C
0x5B,   // 0x816D [
0x5D,   // 0x816E ]
0x7B,   // 0x816F {
0x7D,   // 0x8170 }
0,      // 0x8171
0,      // 0x8172
0,      // 0x8173
0,      // 0x8174
0xA2,   // 0x8175
0xA3,   // 0x8176
0,      // 0x8177
0,      // 0x8178
0,      // 0x8179
0,      // 0x817A
0x2B,   // 0x817B +
0x2D,   // 0x817C -
0,      // 0x817D
0,      // 0x817E
0,      // 0x817F
0,      // 0x8180
0x3D,   // 0x8181 =
0,      // 0x8182
0x3C,   // 0x8183 <
0x3E,   // 0x8184 >
0,      // 0x8185
0,      // 0x8186
0,      // 0x8187
0,      // 0x8188
0,      // 0x8189
0,      // 0x818A
0,      // 0x818B
0,      // 0x818C
0,      // 0x818D
0,      // 0x818E
0x5C,   // 0x818F
0x24,   // 0x8190 $
0,      // 0x8191
0,      // 0x8192
0x25,   // 0x8193 %
0x23,   // 0x8194 #
0x26,   // 0x8195 &
0x2A,   // 0x8196 *
0x40    // 0x8197 @
};

// Maps a 'syv' to a wide XJIS value.  Single byte codes are converted to double
// byte in the process.  So no half-width characters should make it past this function

WORD XJISFromSYV(SYV syv)
{
	WORD	wRet;

	syv &= 0x0000ffff;

	if (syv < 0x0100)
	{
		if (syv >= CHAR_FIRSTSBCS && syv <= CHAR_LASTSBCS)
			wRet = mpSbcsDbcs[(int)(syv - CHAR_FIRSTSBCS)];
		else if (syv >= CHAR_FIRSTKATA && syv <= CHAR_LASTKATA)
			wRet = mpchkatawkata[(int)(syv - CHAR_FIRSTKATA)];
		else
			wRet = 0;
	}
	else
		wRet = (WORD) syv;

	return wRet;
}

/******************************Public*Routine******************************\
* IsSupportedCharWORD
*
* This tells if the DBCS character is supported by Rodan.  This is used to
* filter training data and testing data when determining our accuracy
* numbers.
*
* History:
*  05-Dec-1994 -by- Patrick Haluptzok patrickh
* Put it here
\**************************************************************************/

BOOL SupportedXJIS(WORD wxjis)
{
	if (wxjis < 0x824f)
    {
        switch (wxjis)     // Not all punc/symbols are supported.
        {
			case 0x8141:
			case 0x8142:
			case 0x8143:
			case 0x8144:
			case 0x8145:
			case 0x8146:
			case 0x8147:
			case 0x8148:
			case 0x8149:
			case 0x814a:
            case 0x814b:
            case 0x814f:  // '^' Needed for circle gesture, it's a math symbol.
			case 0x8154:
			case 0x8155:
			case 0x8156:
			case 0x8158:
			case 0x8159:
			case 0x815b:
			case 0x815c:
			case 0x815d:
			case 0x815e:
			case 0x815f:
            case 0x8160:
            case 0x8163:
			case 0x8165:
			case 0x8166:
			case 0x8167:
			case 0x8168:
			case 0x8169:
			case 0x816a:
			case 0x816d:
			case 0x816e:
			case 0x816f:
			case 0x8170:
			case 0x8173:
			case 0x8174:
			case 0x8175:
			case 0x8176:
			case 0x817b:
			case 0x817c:
			case 0x817e:
			case 0x8180:
			case 0x8181:
			case 0x8183:
			case 0x8184:
			case 0x818e:
			case 0x818f:
			case 0x8190:
			case 0x8191:
			case 0x8192:
			case 0x8193:
			case 0x8194:
			case 0x8195:
			case 0x8196:
			case 0x8197:
			case 0x81a7:
				return(TRUE);
        }
    }
    else if (wxjis >= 0x824f && wxjis <= 0x8258)
    {
        return(TRUE); // All numbers
    }
    else if (wxjis >= 0x8260 && wxjis <= 0x8279)
    {
        return(TRUE); // All upper
    }
    else if (wxjis >= 0x8281 && wxjis <= 0x829a)
    {
        return(TRUE); // All lower
    }
    else if (wxjis >= 0x829f && wxjis <= 0x82f1)
    {
        return(TRUE); // All hira
    }
    else if (wxjis >= 0x8340 && wxjis <= 0x8396)
    {
        return(TRUE); // All kata
    }
    else if (wxjis >= 0x889f && wxjis <= 0x9872)
    {
        return(TRUE); // All JIS1 supported
    }
	else if (wxjis > 0x9872)
    {
        return(TRUE);  // All JIS2 supported
    }

	return(FALSE);
}

// Convert the XJIS value to a TOKEN

WORD TokenFromWORD(WORD wDbcs)
{
	WORD	imatch, itoken;

	for (itoken = 0; itoken <= (TOKEN_LAST - TOKEN_FIRST); itoken++)
	{
		for (imatch = 0; imatch < KANJI_MATCHMAX; imatch++)
		{
			if (mptokenwmatches[itoken][imatch] == 0)
				break;
			else if (mptokenwmatches[itoken][imatch] == wDbcs)
				return (TOKEN_FIRST + itoken);
		}
	}

	return 0;
}

SYV SBCSFromDBCS(wchar_t wDbcs)
{
	SYV syvRet;

	if (wDbcs >= KANA_FIRSTMAP && wDbcs <= KANA_LASTMAP)
		syvRet = SyvCharacterToSymbol(mpwkanachkana[wDbcs - KANA_FIRSTMAP]);
	else if ((wDbcs >= 0x824f && wDbcs <= 0x8258) ||
		// numeral
		(wDbcs >= 0x8260 && wDbcs <= 0x8279))
		// upper-case
		syvRet = SyvCharacterToSymbol((char)(wDbcs - 0x821f));
	else if (wDbcs >= 0x8281 && wDbcs <= 0x829a)
		// lower-case
		syvRet = SyvCharacterToSymbol((char)(wDbcs - 0x8220));
	else if (wDbcs >= PUNC_FIRSTMAP && wDbcs <= PUNC_LASTMAP)
		syvRet = SyvCharacterToSymbol(mpwpuncchpunc[wDbcs - PUNC_FIRSTMAP]);
	else
		syvRet = SyvKanjiToSymbol(wDbcs);

    // Added following "if" 5/18/95, Angshuman
    if (syvRet == 0x00010000)
        syvRet = SyvKanjiToSymbol(wDbcs);

	return(syvRet);
}

WORD GetFirstMatch(WORD wdbcs)
{
		WORD	wMatch;
const	WORD   *rgwMatches;

	if (wMatch = TokenFromWORD(wdbcs))
	{
		rgwMatches = pwListFromToken(wMatch);
		wdbcs = rgwMatches[0];
	}

	return wdbcs;
}

/******************************Public*Routine******************************\
* StaticNumberOfSamples
*
* Returns the number of samples on which we trained for each glyph
*
* History:
*  27-Nov-1995 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/

extern const unsigned short gaiStaticLabelCnt[][2];
extern int giStaticLabelCnt;

int StaticNumberOfSamples(WORD wCurrent)
{
	int		iMin;
	int		iMax;
	int		iNew;
	WORD	wNew;

	iMin = 0;
    iMax = giStaticLabelCnt - 1;

	while (iMin < iMax)
	{
		iNew = (iMin + iMax) / 2;

        wNew = gaiStaticLabelCnt[iNew][0];

		if (wNew < wCurrent)
		{
			iMin = iNew + 1;
			continue;
		}
		else if (wNew > wCurrent)
		{
			iMax = iNew - 1;
			continue;
		}

        return(gaiStaticLabelCnt[iNew][1]);
	}

    return gaiStaticLabelCnt[iMin][0] == wCurrent ? gaiStaticLabelCnt[iMin][1] : 1;
}
