Milán Major

netscape-revival

1 branch
Code

lib/libi18n/fe_ccc.c

/* -*- Mode: C; tab-width: 4 -*- */
/*	fe_ccc.c	*/
/* Test harness code to be replaced by FE specific code	*/

/* #define USE_NPC 1  */

#include "intlpriv.h"

#ifndef STANDALONE_TEST
#include <stdio.h>
#include "xp.h"
#endif /* ! STANDALONE_TEST */

#ifdef XP_MAC
#include "resgui.h"
#endif

#ifdef USE_NPC
#include "npc.h"
#endif

#ifdef XP_UNIX
#ifdef DEBUG
#if 0
#define UNICODE_INIT_TEST	/* Turn this off unless testing unicode*/
#endif
#endif
#endif


/* for XP_GetString() */
#include "xpgetstr.h"
extern int XP_DOCINFO_1;
extern int XP_DOCINFO_2;
extern int XP_DOCINFO_3;
extern int XP_DOCINFO_4;
extern int MK_OUT_OF_MEMORY;


static unsigned char *
mz_b52b5(CCCDataObject *obj, const unsigned char *kscbuf, int32 kscbufsz);

static unsigned char *
mz_cns2cns(CCCDataObject *obj, const unsigned char *cnsbuf, int32 cnsbufsz);

static unsigned char *
mz_euc2euc(CCCDataObject *obj, const unsigned char *eucbuf, int32 eucbufsz);

static unsigned char *
mz_gb2gb(CCCDataObject *obj, const unsigned char *kscbuf, int32 kscbufsz);

static unsigned char *
mz_ksc2ksc(CCCDataObject *obj, const unsigned char *kscbuf, int32 kscbufsz);

static unsigned char *
mz_sjis2sjis(CCCDataObject *obj, const unsigned char *sjisbuf, int32 sjisbufsz);


static int haveBig5 = 0;


csinfo_t csinfo_tbl[] =
{
/* b = bytes; c = columns                                               */
/* charset ID    b c  range 1       b c  range 2       b c  range 3     */
{CS_SJIS,      {{2,2,{0x81,0x9f}}, {2,2,{0xe0,0xfc}}, {0,0,{0x00,0x00}}}},
{CS_EUCJP,     {{2,2,{0xa1,0xfe}}, {2,1,{0x8e,0x8e}}, {3,2,{0x8f,0x8f}}}},
{CS_KSC_8BIT,  {{2,2,{0xa1,0xfe}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_GB_8BIT,   {{2,2,{0xa1,0xfe}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_CNS_8BIT,  {{2,2,{0xa1,0xfe}}, {4,2,{0x8e,0x8e}}, {0,0,{0x00,0x00}}}},
{CS_BIG5,      {{2,2,{0xa1,0xfe}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_CNS11643_1,{{2,2,{0x21,0x7e}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_CNS11643_2,{{2,2,{0x21,0x7e}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_JISX0208,  {{2,2,{0x21,0x7e}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_KSC5601,   {{2,2,{0x21,0x7e}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_JISX0212,  {{2,2,{0x21,0x7e}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_GB2312,    {{2,2,{0x21,0x7e}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}},
{CS_UTF8,	   {{2,2,{0xC0, 0xDF}},{3,2,{0xE0,0xEF}},{0,0,{0x00,0x00}}}},
{0,            {{0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}, {0,0,{0x00,0x00}}}}
};

			/* Charset names and aliases from RFC 1700. Names are case
			 * insenstive. Currently searches table linearly, so keep commonly used names at the beginning.
			 */
csname2id_t csname2id_tbl[] = {
											/* default if not specified */
			{"RESERVED", CS_DEFAULT},			/* or unknown charset		*/

			{"us-ascii", CS_ASCII},
			{"iso-8859-1", CS_LATIN1},
			{"iso-2022-jp", CS_JIS},
			{"iso-2022-jp-2", CS_JIS},		/* treat same as iso-2022-jp*/
			{"Shift_JIS", CS_SJIS},
			{"x-euc-jp", CS_EUCJP},
			{"jis_x0208-1983", CS_JISX0208},
			{"x-jisx0208-11", CS_JISX0208_11},
			{"jis_x0201", CS_JISX0201},
			{"jis_x0212-1990", CS_JISX0212},
			{"x-mac-roman", CS_MAC_ROMAN}, 
			{"iso-8859-2", CS_LATIN2},
			{"iso-8859-3", CS_8859_3},
			{"iso-8859-4", CS_8859_4},
			{"iso-8859-5", CS_8859_5},
			{"iso-8859-6", CS_8859_6},
			{"iso-8859-7", CS_8859_7},
			{"iso-8859-8", CS_8859_8},
			{"iso-8859-9", CS_8859_9},
			{"x-mac-ce", CS_MAC_CE},
			{"euc-kr", CS_KSC_8BIT},
			{"ks_c_5601-1987", CS_KSC5601},
			{"x-ksc5601-11", CS_KSC5601_11},
			{"gb2312", CS_GB_8BIT},
			{"gb_2312-80", CS_GB2312},
			{"x-gb2312-11", CS_GB2312_11},
			{"x-euc-tw", CS_CNS_8BIT},
			{"x-cns11643-1", CS_CNS11643_1},
			{"x-cns11643-2", CS_CNS11643_2},
			{"x-cns11643-1110", CS_CNS11643_1110},
			{"iso-2022-kr", CS_2022_KR},
			{"big5", CS_BIG5},
			{"x-x-big5", CS_X_BIG5},
			{"x-tis620", CS_TIS620},
			{"adobe-symbol-encoding", CS_SYMBOL},
			{"x-dingbats", CS_DINGBATS},
			{"x-dectech", CS_DECTECH},
			{"koi8-r", CS_KOI8_R},
/*			{"iso-8859-5-windows-latin-5", CS_CP_1251},	*/
			{"x-mac-cyrillic", CS_MAC_CYRILLIC}, 
			{"x-mac-greek", CS_MAC_GREEK}, 
			{"x-mac-turkish", CS_MAC_TURKISH}, 
			{"windows-1250", CS_CP_1250},
			{"windows-1251", CS_CP_1251}, /* cyrillic */

#ifdef NOTDEF /* for auto Japanese codeset detection. when we have time. */
			{"x-japan", CS_JAPAN},
#endif /* NOTDEF */
											/* aliases for us-ascii: */
			{"ansi_x3.4-1968", CS_ASCII},
			{"iso-ir-6", CS_ASCII},
			{"ansi_x3.4-1986", CS_ASCII},
			{"iso_646.irv:1991", CS_ASCII},
			{"ascii", CS_ASCII},
			{"iso646-us", CS_ASCII},
			{"us", CS_ASCII},
			{"ibm367", CS_ASCII},
			{"cp367", CS_ASCII},
			{"csASCII", CS_ASCII},
											/* aliases for iso_8859-1:	*/
			{"latin1", CS_LATIN1},
			{"iso_8859-1", CS_LATIN1},
			{"iso_8859-1:1987", CS_LATIN1},
			{"iso-ir-100", CS_LATIN1},
			{"l1", CS_LATIN1},
			{"ibm819", CS_LATIN1},
			{"cp819", CS_LATIN1},
			
											/* aliases for ISO_8859-2:	*/
			{"latin2", CS_LATIN2},			
			{"iso_8859-2", CS_LATIN2},
			{"iso_8859-2:1987", CS_LATIN2},
			{"iso-ir-101", CS_LATIN2},
			{"l2", CS_LATIN2},											
											/* aliases for KS_C_5601-1987:	*/
			{"ks_c_5601-1987", CS_KSC5601},
			{"iso-ir-149", CS_KSC5601},
			{"ks_c_5601-1989", CS_KSC5601},
			{"ks_c_5601", CS_KSC5601},
			{"korean", CS_KSC5601},
			{"csKSC56011987", CS_KSC5601},
											/* aliases for iso-2022-kr:	*/
			{"csISO2022KR", CS_2022_KR},
											/* aliases for euc-kr:	*/
			{"csEUCKR", CS_KSC_8BIT},
											/* aliases for iso-2022-jp:	*/
			{"csISO2022JP", CS_JIS},
											/* aliases for iso-2022-jp-2:	*/
			{"csISO2022JP2", CS_JIS},
											/* aliases for GB_2312-80:	*/
			{"iso-ir-58", CS_GB2312},
			{"chinese", CS_GB2312},
			{"csISO58GB231280", CS_GB2312},
											/* aliases for gb2312:	*/
			{"csGB2312", CS_GB_8BIT},
											/* aliases for big5:	*/
			{"csBig5", CS_BIG5},
											/* aliases for iso-8859-7:	*/
			{"iso-ir-126", CS_8859_7},
			{"iso_8859-7", CS_8859_7},
			{"iso_8859-7:1987", CS_8859_7},
			{"elot_928", CS_8859_7},
			{"ecma-118", CS_8859_7},
			{"greek", CS_8859_7},
			{"greek8", CS_8859_7},
			{"csISOLatinGreek", CS_8859_7},
											/* aliases for iso-8859-5:	*/
			{"iso-ir-144", CS_8859_5},
			{"iso_8859-5", CS_8859_5},
			{"iso_8859-5:1988", CS_8859_5},
			{"cyrillic", CS_8859_5},
			{"csISOLatinCyrillic", CS_8859_5},
											/* aliases for jis_x0212-1990:	*/
			{"x0212", CS_JISX0212},
			{"iso-ir-159", CS_JISX0212},
			{"csISO159JISX02121990", CS_JISX0212},
											/* aliases for jis_x0201:	*/
			{"x0201", CS_JISX0201},
			{"csHalfWidthKatakana", CS_JISX0201},
											/* aliases for koi8-r:	*/
			{"csKOI8R", CS_KOI8_R},
											/* aliases for Shift_JIS:	*/
			{"x-sjis", CS_SJIS},
			{"ms_Kanji", CS_SJIS},
			{"csShiftJIS", CS_SJIS},
											/* aliases for x-euc-jp:	*/
			{"Extended_UNIX_Code_Packed_Format_for_Japanese", CS_EUCJP},
			{"csEUCPkdFmtJapanese", CS_EUCJP},
			{"euc-jp", CS_EUCJP},

											/* aliases for adobe-symbol-encoding:	*/
			{"csHPPSMath", CS_SYMBOL},
											/* aliases for iso-8859-5-windows-latin-5:	*/
			{"csWindows31Latin5", CS_CP_1251},

			{"UNICODE-1-1-UTF-8", CS_UTF8},

			{"x-user-defined", CS_USER_DEFINED_ENCODING},											
			{"x-user-defined", CS_USRDEF2},											

											/* windows additions */
			{"ISO-8859-1-Windows-3.0-Latin-1", CS_LATIN1},
			{"ISO-8859-1-Windows-3.1-Latin-1", CS_LATIN1},
			{"ISO-8859-2-Windows-Latin-2", CS_LATIN2},
			{"iso-8859-5-windows-latin-5", CS_CP_1251},
			{"Windows-31J", CS_SJIS},
			{"x-cp1250", CS_CP_1250},
			{"x-cp1251", CS_CP_1251},
			{"windows-1253", CS_8859_7},  /* greek */
			{"windows-1254", CS_8859_9},  /* turkish */

			{"CN-GB", CS_GB_8BIT},  /* Simplified Chinese */
			{"CN-GB-ISOIR165", CS_GB_8BIT},  /* Simplified Chinese */
			{"CN-Big5", CS_BIG5},  /* Traditional Chinese */

			{"", 	CS_UNKNOWN}
};
		/* Table that maps the FROM char, codeset to all other relevant info:
		 *	- TO character codeset
		 *	- Fonts (fixe & proportional) for TO character codeset
		 *	- Type of conversion (func for Win/Mac, value for X)
		 *	- Argument for conversion routine.  Routine-defined.
		 *
		 * Not all of these may be available.  Depends upon available fonts,
		 * scripts, codepages, etc.  Need to query system to build valid table.
		 *
		 * What info do I need to make the font change API on the 3 platforms?
		 *  Is just a 32bit font ID sufficient?
		 *
		 * Some X Windows can render Japanese in either EUC or SJIS, how do we
		 * choose?
		 */
#ifndef XP_UNIX
cscvt_t		cscvt_tbl[] = {
		/* The ***first*** match of a "FROM" encoding (1st col.) will be
		 * used as the URL->native encoding.  Be careful of the
		 * ordering.
		 * Additional entries for the same "FROM" encoding, specifies
		 * how to convert going out (e.g., sending mail, news or forms).
		 */
#ifdef XP_MAC
		{CS_LATIN1,		CS_MAC_ROMAN,	0, (CCCFunc)One2OneCCC,	xlat_LATIN1_TO_MAC_ROMAN},
		{CS_ASCII,		CS_MAC_ROMAN,	0, (CCCFunc)One2OneCCC,	xlat_LATIN1_TO_MAC_ROMAN},
		{CS_MAC_ROMAN,	CS_MAC_ROMAN,	0, (CCCFunc)0,			0},
		{CS_MAC_ROMAN,	CS_LATIN1,		0, (CCCFunc)One2OneCCC,	xlat_MAC_ROMAN_TO_LATIN1},
		{CS_MAC_ROMAN,	CS_ASCII,		0, (CCCFunc)One2OneCCC,	xlat_MAC_ROMAN_TO_LATIN1},

		{CS_LATIN2,		CS_MAC_CE,		0, (CCCFunc)One2OneCCC, xlat_LATIN2_TO_MAC_CE},
		{CS_MAC_CE,		CS_MAC_CE,		0, (CCCFunc)0,			0},
		{CS_MAC_CE,		CS_LATIN2,		0, (CCCFunc)One2OneCCC, xlat_MAC_CE_TO_LATIN2},
		{CS_MAC_CE,		CS_ASCII,		0, (CCCFunc)One2OneCCC, xlat_MAC_CE_TO_LATIN2},

		{CS_CP_1250,	CS_MAC_CE,		0, (CCCFunc)One2OneCCC, xlat_CP_1250_TO_MAC_CE},
		{CS_MAC_CE,		CS_CP_1250,		0, (CCCFunc)One2OneCCC, xlat_MAC_CE_TO_CP_1250},

		{CS_8859_5,		CS_MAC_CYRILLIC,0, (CCCFunc)One2OneCCC, xlat_8859_5_TO_MAC_CYRILLIC},
		{CS_MAC_CYRILLIC,CS_MAC_CYRILLIC,		0, (CCCFunc)0,			0},
		{CS_MAC_CYRILLIC,CS_8859_5,		0, (CCCFunc)One2OneCCC, xlat_MAC_CYRILLIC_TO_8859_5},
		{CS_MAC_CYRILLIC,CS_ASCII,		0, (CCCFunc)One2OneCCC, xlat_MAC_CYRILLIC_TO_8859_5},

		{CS_CP_1251,	CS_MAC_CYRILLIC,0, (CCCFunc)One2OneCCC, xlat_CP_1251_TO_MAC_CYRILLIC},
		{CS_MAC_CYRILLIC,CS_CP_1251,	0, (CCCFunc)One2OneCCC, xlat_MAC_CYRILLIC_TO_CP_1251},

		{CS_KOI8_R,		CS_KOI8_R,		0, (CCCFunc)0, 			0},
		{CS_KOI8_R,		CS_MAC_CYRILLIC,0, (CCCFunc)One2OneCCC, xlat_KOI8_R_TO_MAC_CYRILLIC},
		{CS_MAC_CYRILLIC,CS_KOI8_R,		0, (CCCFunc)One2OneCCC, xlat_MAC_CYRILLIC_TO_KOI8_R},

		{CS_8859_7,		CS_MAC_GREEK,	0, (CCCFunc)One2OneCCC, xlat_8859_7_TO_MAC_GREEK},
		{CS_MAC_GREEK,	CS_MAC_GREEK,	0, (CCCFunc)0,			0},
		{CS_MAC_GREEK,	CS_8859_7,		0, (CCCFunc)One2OneCCC, xlat_MAC_GREEK_TO_8859_7},
		{CS_MAC_GREEK,	CS_ASCII,		0, (CCCFunc)One2OneCCC, xlat_MAC_GREEK_TO_8859_7},


		{CS_8859_9,		CS_MAC_TURKISH,	0, (CCCFunc)One2OneCCC, xlat_8859_9_TO_MAC_TURKISH},
		{CS_MAC_TURKISH,CS_MAC_TURKISH,	0, (CCCFunc)0,			0},
		{CS_MAC_TURKISH,CS_8859_9,		0, (CCCFunc)One2OneCCC, xlat_MAC_TURKISH_TO_8859_9},
		{CS_MAC_TURKISH,CS_ASCII,		0, (CCCFunc)One2OneCCC, xlat_MAC_TURKISH_TO_8859_9},



/*	ftang: Add CS_USER_DEFINED_ENCODING. Do we need this in here ? */

		{CS_USER_DEFINED_ENCODING,	CS_USER_DEFINED_ENCODING,	0, (CCCFunc)0,			0},	

#endif /* XP_MAC */

#ifdef XP_MAC
		/* How about GB ??? */
		{CS_GB_8BIT,	CS_GB_8BIT,		0, (CCCFunc)mz_gb2gb,		0},
#endif /* XP_MAC */

#ifdef XP_WIN
		{CS_LATIN1,		CS_LATIN1,		0,	(CCCFunc)0,			0},
		{CS_LATIN1,		CS_ASCII,		0, 	(CCCFunc)0,			0},
		{CS_ASCII,		CS_LATIN1,		0, 	(CCCFunc)0,			0},
		{CS_ASCII,		CS_ASCII,		0, 	(CCCFunc)0,			0},

		/* Latin2 <-> Win-Latin2 */
		{CS_CP_1250,	CS_CP_1250,		0, (CCCFunc)0,			0},
		{CS_CP_1250,	CS_LATIN2,		0, (CCCFunc)One2OneCCC,	0},
		{CS_LATIN2,		CS_CP_1250,		0, (CCCFunc)One2OneCCC,	0},
		{CS_LATIN2,		CS_LATIN2,		0,	(CCCFunc)0,			0},
		{CS_LATIN2,		CS_ASCII,		0,	(CCCFunc)0,			0},
		/* ISO, KOI, Windows Cyrillic */
		{CS_CP_1251,	CS_CP_1251,		0, (CCCFunc)0,			0},
		{CS_8859_5,		CS_CP_1251,		0, (CCCFunc)One2OneCCC, 0},
		{CS_CP_1251,	CS_8859_5,		0, (CCCFunc)One2OneCCC, 0},
		{CS_CP_1251,	CS_CP_1251,		0, (CCCFunc)0,			0},
		{CS_KOI8_R,		CS_KOI8_R,		0, (CCCFunc)0,			0},
		{CS_CP_1251,	CS_KOI8_R,		0, (CCCFunc)One2OneCCC, 0},
		{CS_KOI8_R,		CS_CP_1251,		0, (CCCFunc)One2OneCCC, 0},
		/* ISO,Windows Greek */
		{CS_8859_7,		CS_8859_7,		0, (CCCFunc)0,			0},
		/* ISO, Windows Turkish */
		{CS_8859_9,		CS_8859_9,		0, (CCCFunc)0,			0},

		{CS_UTF8,		CS_UTF8,		0, (CCCFunc)0,			0},
		
		{CS_USER_DEFINED_ENCODING,	CS_USER_DEFINED_ENCODING,	0, (CCCFunc)0,			0},	
#endif /* XP_WIN */
		{CS_SJIS,		CS_SJIS,		1, (CCCFunc)mz_sjis2sjis,	0},
		{CS_SJIS,		CS_JIS,			1, (CCCFunc)mz_sjis2jis,	0},
		{CS_JIS,		CS_SJIS,		1, (CCCFunc)jis2other,	0},
		{CS_EUCJP,		CS_SJIS,		1, (CCCFunc)mz_euc2sjis,	0},
		{CS_JIS,		CS_EUCJP,		1, (CCCFunc)jis2other,	1},
		{CS_EUCJP,		CS_JIS,			1, (CCCFunc)mz_euc2jis,	0},
		{CS_SJIS,		CS_EUCJP,		1, (CCCFunc)mz_sjis2euc,	0},
		{CS_KSC_8BIT,	CS_KSC_8BIT,	0, (CCCFunc)mz_ksc2ksc,		0},
		{CS_BIG5,		CS_BIG5,		0, (CCCFunc)mz_b52b5,	0},
		{CS_GB_8BIT,	CS_GB_8BIT,		0, (CCCFunc)mz_gb2gb,		0},

		{CS_2022_KR,	CS_KSC_8BIT,	0, (CCCFunc)mz_iso2euckr,0},
		{CS_KSC_8BIT,	CS_2022_KR,		0, (CCCFunc)mz_euckr2iso,0},
		{CS_BIG5,		CS_CNS_8BIT,	0, (CCCFunc)mz_b52cns,0},
		{CS_CNS_8BIT,	CS_BIG5,		0, (CCCFunc)mz_cns2b5,0},

		/* auto-detect Japanese conversions						*/
		{CS_SJIS_AUTO,		CS_SJIS,		1, (CCCFunc)autoJCCC,	0},
		{CS_JIS_AUTO,		CS_SJIS,		1, (CCCFunc)autoJCCC,	0},
		{CS_EUCJP_AUTO,		CS_SJIS,		1, (CCCFunc)autoJCCC,	0},
		{0,					0,				1, (CCCFunc)0,			0}
};

#else /* XP_UNIX */

cscvt_t		cscvt_tbl[] = {

#ifndef USE_NPC

		/* "FROM" encoding (1st col.) must be unique		*/

		{CS_LATIN1,		CS_LATIN1,		0, NULL,			0},
		{CS_LATIN1,		CS_ASCII,		0, NULL,			0},
		{CS_LATIN2,		CS_LATIN2,		0, NULL,			0},
		{CS_LATIN2,		CS_ASCII,		0, NULL,			0},
		{CS_ASCII,		CS_LATIN1,		0, NULL,			0},
		{CS_EUCJP,		CS_EUCJP,		1, mz_euc2euc,		0},
		{CS_JIS,		CS_EUCJP,		1, jis2other,		1},
		{CS_SJIS,		CS_EUCJP,		1, mz_sjis2euc,		0},
		{CS_EUCJP,		CS_SJIS,		1, mz_euc2sjis,		0},
		{CS_JIS,		CS_SJIS,		1, jis2other,		0},
		{CS_SJIS,		CS_SJIS,		1, mz_sjis2sjis,	0},
		{CS_EUCJP,		CS_JIS,			1, mz_euc2jis,		0},
		{CS_SJIS,		CS_JIS,			1, mz_sjis2jis,		0},
		{CS_KSC_8BIT,	CS_KSC_8BIT,	0, mz_ksc2ksc,		0},
		{CS_GB_8BIT,	CS_GB_8BIT,		0, mz_gb2gb,		0},
		{CS_CNS_8BIT,	CS_CNS_8BIT,	0, mz_cns2cns,		0},
		{CS_2022_KR,	CS_KSC_8BIT,	0, mz_iso2euckr,	0},
		{CS_KSC_8BIT,	CS_2022_KR,		0, mz_euckr2iso,	0},
		{CS_BIG5,		CS_CNS_8BIT,	0, mz_b52cns,		0},
		{CS_CNS_8BIT,	CS_BIG5,		0, mz_cns2b5,		0},
		{CS_BIG5,		CS_BIG5,		0, mz_b52b5,		0},
		{CS_KOI8_R,		CS_KOI8_R,		0, NULL,			0},	
		{CS_8859_5,		CS_8859_5,		0, NULL,			0},	
		{CS_8859_7,		CS_8859_7,		0, NULL,			0},	
		{CS_8859_9,		CS_8859_9,		0, NULL,			0},	
		{CS_USRDEF2,	CS_USRDEF2,		0, NULL,			0},	

		/* auto-detect Japanese conversions					*/

		{CS_JIS_AUTO,	CS_EUCJP,		1, autoJCCC,		1},
		{CS_SJIS_AUTO,	CS_EUCJP,		1, autoJCCC,		0},
		{CS_EUCJP_AUTO,	CS_EUCJP,		1, autoJCCC,		0},
		{CS_EUCJP_AUTO,	CS_SJIS,		1, autoJCCC,		0},
		{CS_JIS_AUTO,	CS_SJIS,		1, autoJCCC,		0},
		{CS_SJIS_AUTO,	CS_SJIS,		1, autoJCCC,		0},

#else /* USE_NPC */

		{CS_LATIN1,		CS_LATIN1,		0, intl_ISO88591ToNPC,	0},

		/*
		{CS_JIS,		CS_LATIN1,		0, intl_JISToNPC,		0},
		{CS_SJIS,		CS_LATIN1,		0, intl_SJISToNPC,		0},
		{CS_EUCJP,		CS_LATIN1,		0, intl_EUCJPToNPC,		0},
		*/

		/*
		{CS_2022_KR,	CS_LATIN1,		0, intl_2022KRToNPC,	0},
		{CS_ASCII,		CS_LATIN1,		0, intl_ASCIIToNPC,		0},
		{CS_BIG5,		CS_LATIN1,		0, intl_BIG5ToNPC,		0},
		{CS_GB_8BIT,	CS_LATIN1,		0, intl_EUCCNToNPC,		0},
		{CS_KSC_8BIT,	CS_LATIN1,		0, intl_EUCKRToNPC,		0},
		{CS_CNS_8BIT,	CS_LATIN1,		0, intl_EUCTWToNPC,		0},
		{CS_LATIN2,		CS_LATIN1,		0, intl_ISO88592ToNPC,	0},
		*/

#endif /* USE_NPC */

		{0,				0,				0, NULL,			0}

};

#endif /* XP_UNIX */

	/* Maps a window encoding to the MIME encoding used for posting
	 * news and internet email.  String is for the MIME charset string.
	 */
csmime_t	csmime_tbl[] = {
			{CS_ASCII,		CS_ASCII,	"us-ascii"		},
			
			{CS_LATIN1,		CS_LATIN1,	"iso-8859-1"	},
			
			{CS_JIS,		CS_JIS,		"iso-2022-jp"	},
			{CS_SJIS,		CS_JIS,		"iso-2022-jp"	},
			{CS_EUCJP,		CS_JIS,		"iso-2022-jp"	},
			
			{CS_KSC_8BIT,	CS_KSC_8BIT,"euc-kr"		},
			
			{CS_GB_8BIT,	CS_GB_8BIT,	"gb2312"		},
			
			{CS_BIG5,		CS_BIG5,	"big5"		},
			{CS_CNS_8BIT,	CS_BIG5,	"big5"		},
			
			{CS_MAC_ROMAN,	CS_LATIN1,	"iso-8859-1"	},
			
			{CS_LATIN2,		CS_LATIN2, 	"iso-8859-2"	},
			{CS_MAC_CE,		CS_LATIN2,	"iso-8859-2"	},
			{CS_CP_1250,	CS_LATIN2, 	"iso-8859-2"	},
			
			{CS_8859_5,			CS_KOI8_R,	"koi8-r"	},
			{CS_KOI8_R,			CS_KOI8_R,	"koi8-r"	},
			{CS_MAC_CYRILLIC,	CS_KOI8_R,	"koi8-r"	},
			{CS_CP_1251,		CS_KOI8_R,	"koi8-r"	},
			
			{CS_8859_7,		CS_8859_7,	"iso-8859-7"	},
			{CS_MAC_GREEK,	CS_8859_7,	"iso-8859-7"	},

			{CS_8859_9,		CS_8859_9, 	"iso-8859-9"	},
			{CS_MAC_TURKISH,CS_8859_9,	"iso-8859-9"	},
			
			{0,				0,			""				}
};

#ifdef XP_UNIX
cslocale_t	cslocale_tbl[] = {
	{CS_LATIN1,	"C",			"*8859-1*, *jisx208*, *jisx201*" },
	{CS_EUCJP,	"jp_JP.EUC",	"*8859-1*, *jisx208*, *jisx201*" },
	{CS_SJIS,	"jp_JP.SJIS",	"*8859-1*, *jisx208*, *jisx201*" },
	{CS_LATIN2, "C",			"*8859-2*, *jisx208*, *jisx201*" },
	{CS_KSC_8BIT,	"ko_KR.euc",	"*8859-1*, *ksc5601*" },
	{CS_GB_8BIT,	"zh_CN.ugb",	"*8859-1*, *gb2312*" },
	{CS_CNS_8BIT,	"zh_TW.ucns",	"*8859-1*, *cns11643*" },
	{CS_BIG5,		"zh_TW.ucns",	"*8859-1*, *cns11643*" },
	{0,			0,				0}
};
#endif /* XP_UNIX */


static int16 *availableFontCharSets = NULL;


	/* returns Handle to 256 x 1Byte table for converting 1Byte char. encodings	*/

char ** 
INTL_GetSingleByteTable(int16 from_csid, int16 to_csid, int32 resourceid)
{
#if defined(XP_MAC) || defined(XP_WIN) 
	return FE_GetSingleByteTable(from_csid, to_csid,resourceid);
#else
	return(NULL);
#endif
}

	
char *INTL_LockTable(char **cvthdl)
{
#ifdef XP_WIN
	return FE_LockTable(cvthdl);
#else
	return *cvthdl;
#endif
}

        /* INTL_FreeSingleByteTable(char **cvthdl)
         * mac-specific, at present. Sets the conversion table resource
         * in memory as purgeable when it is no longer in use. To be
         * called by cvchcode.c and pa_amp.c
         */

void INTL_FreeSingleByteTable(char **cvthdl) {
#ifdef XP_MAC
	FE_FreeSingleByteTable(cvthdl);
#endif
}

#ifdef XP_MAC
#pragma cplusplus on
#include "uprefd.h"
#endif
#ifdef XP_UNIX
char* FE_GetAcceptLanguage();
#endif

/* INTL_GetAcceptLanguage()						*/
/* return the AcceptLanguage from FE Preference */
/* this should be a C style NULL terminated string */
char* INTL_GetAcceptLanguage()
{
#ifdef XP_MAC
	return (CPrefs::GetString( CPrefs::AcceptLanguage ));
#else
	return FE_GetAcceptLanguage();
#endif
}
#ifdef XP_MAC
#pragma cplusplus reset
#endif
PRIVATE 
XP_Bool onlyAsciiStr(const char *s)
{
	for(; *s; s++)
		if(*s & 0x80)
			return FALSE;
	return TRUE;
}

/*
 * this routine is needed to make sure parser and layout see whole
 * characters, not partial characters
 */
static unsigned char *
mz_euc2euc(CCCDataObject *obj, const unsigned char *eucbuf, int32 eucbufsz)
{
	unsigned char	b;
	int32			left_over;
	int32			len;
	unsigned char	*p;
	unsigned char	*q;
	unsigned char	*ret;
	int32			total;

	if ((!obj) || (!eucbuf) || (eucbufsz < 0))
	{
		return NULL;
	}

	total = strlen((char *)obj->uncvtbuf) + eucbufsz;
	ret = (unsigned char *) XP_ALLOC(total + 1);
	if (!ret)
	{
		obj->retval = MK_OUT_OF_MEMORY;
		return NULL;
	}

	p = ret;
	q = obj->uncvtbuf;
	while (*q)
	{
		*p++ = *q++;
	}

	q = (unsigned char *) eucbuf;
	while (eucbufsz)
	{
		*p++ = *q++;
		eucbufsz--;
	}

	p = ret;
	len = total;
	left_over = 0;
	while (len)
	{
		b = *p++;
		len--;
		if (b < SS2)
		{
			/* single byte */
		}
		else if (b == SS2)
		{
			if (len == 0)
			{
				left_over = 1;
				break;
			}
			p++;
			len--;
		}
		else if (b == SS3)
		{
			if (len == 0)
			{
				left_over = 1;
				break;
			}
			if (len == 1)
			{
				left_over = 2;
				break;
			}
			p += 2;
			len -= 2;
		}
		else if (b < 0xa1)
		{
			/* single byte */
		}
		else if (b < 0xff)
		{
			if (len == 0)
			{
				left_over = 1;
				break;
			}
			p++;
			len--;
		}
		else /* (b == 0xff) */
		{
			/* single byte */
		}
	}

	obj->len = total - left_over;

	q = --p;
	p = obj->uncvtbuf;
	while (left_over)
	{
		*p++ = *q++;
		left_over--;
	}
	*p = 0;

	ret[obj->len] = 0;

	return ret;
}

/*
 * this routine is needed to make sure parser and layout see whole
 * characters, not partial characters
 */
static unsigned char *
mz_sjis2sjis(CCCDataObject *obj, const unsigned char *sjisbuf, int32 sjisbufsz)
{
	unsigned char	b;
	int32			left_over;
	int32			len;
	unsigned char	*p;
	unsigned char	*q;
	unsigned char	*ret;
	int32			total;

	if ((!obj) || (!sjisbuf) || (sjisbufsz < 0))
	{
		return NULL;
	}

	total = strlen((char *)obj->uncvtbuf) + sjisbufsz;
	ret = (unsigned char *) XP_ALLOC(total + 1);
	if (!ret)
	{
		obj->retval = MK_OUT_OF_MEMORY;
		return NULL;
	}

	p = ret;
	q = obj->uncvtbuf;
	while (*q)
	{
		*p++ = *q++;
	}

	q = (unsigned char *) sjisbuf;
	while (sjisbufsz)
	{
		*p++ = *q++;
		sjisbufsz--;
	}

	p = ret;
	len = total;
	left_over = 0;
	while (len)
	{
		b = *p++;
		len--;
		if (b < 0x80)
		{
			/* single byte */
		}
		else if (b < 0xa0)
		{
			if (len == 0)
			{
				left_over = 1;
				break;
			}
			p++;
			len--;
		}
		else if (b < 0xe0)
		{
			/* single byte */
		}
		else /* (b <= 0xff) */
		{
			if (len == 0)
			{
				left_over = 1;
				break;
			}
			p++;
			len--;
		}
	}

	obj->len = total - left_over;

	q = --p;
	p = obj->uncvtbuf;
	while (left_over)
	{
		*p++ = *q++;
		left_over--;
	}
	*p = 0;

	ret[obj->len] = 0;

	return ret;
}

/*
 * this routine is needed to make sure parser and layout see whole
 * characters, not partial characters
 */
static unsigned char *
mz_ksc2ksc(CCCDataObject *obj, const unsigned char *kscbuf, int32 kscbufsz)
{
	unsigned char	b;
	int32			left_over;
	int32			len;
	unsigned char	*p;
	unsigned char	*q;
	unsigned char	*ret;
	int32			total;

	if ((!obj) || (!kscbuf) || (kscbufsz < 0))
	{
		return NULL;
	}

	total = strlen((char*)obj->uncvtbuf) + kscbufsz;
	ret = (unsigned char *) XP_ALLOC(total + 1);
	if (!ret)
	{
		obj->retval = MK_OUT_OF_MEMORY;
		return NULL;
	}

	p = ret;
	q = obj->uncvtbuf;
	while (*q)
	{
		*p++ = *q++;
	}

	q = (unsigned char *) kscbuf;
	while (kscbufsz)
	{
		*p++ = *q++;
		kscbufsz--;
	}

	p = ret;
	len = total;
	left_over = 0;
	while (len)
	{
		b = *p++;
		len--;
		if (b < 0xa1)
		{
			/* single byte */
		}
		else if (b < 0xff)
		{
			if (len == 0)
			{
				left_over = 1;
				break;
			}
			p++;
			len--;
		}
		else /* (b == 0xff) */
		{
			/* single byte */
		}
	}

	obj->len = total - left_over;

	q = --p;
	p = obj->uncvtbuf;
	while (left_over)
	{
		*p++ = *q++;
		left_over--;
	}
	*p = 0;

	ret[obj->len] = 0;

	return ret;
}

/*
 * this routine is needed to make sure parser and layout see whole
 * characters, not partial characters
 */
static unsigned char *
mz_gb2gb(CCCDataObject *obj, const unsigned char *gbbuf, int32 gbbufsz)
{
	unsigned char *start, *p, *q;
	unsigned char *output;
	int i, j, len;

	q = output = XP_ALLOC(strlen((char*)obj->uncvtbuf) + gbbufsz + 1);
	if (q == NULL)
		return NULL;

	start = NULL;

	for (j = 0; j < 2; j++)
	{
		if (j == 0 && (len = strlen((char *)obj->uncvtbuf)))
		{
			p = (unsigned char *) obj->uncvtbuf;
		}
		else
		{
			p = (unsigned char *) gbbuf ;
			len = gbbufsz;
			j = 100;  /* quit this loop next time */
		}
			
		for (i = 0; i < len;)
		{
			if (start)
			{
				if (*p == '~' && *(p+1) == '}')   /* switch back to ASCII mode */
				{
					for (; start < p; start++)
						*q++ = *start | 0x80;
					p += 2;
					i += 2;
					start = NULL;
				}
				else if (*p == 0x0D && *(p+1) == 0x0A)  /* Unix or Mac return */
				{
					for (; start < p; start++)
						*q++ = *start | 0x80;
					i += 2;
					*q++ = *p++;   /* 0x0D  */
					*q++ = *p++;   /* 0x0A  */
					start = NULL;   /* reset start if we see normal line return */
				}
				else if (*p == 0x0A)  /* Unix or Mac return */
				{
					for (; start < p; start++)
						*q++ = *start | 0x80;
					i ++;
					*q++ = *p++;   /* LF  */
					start = NULL;   /* reset start if we see normal line return */
				}
				else if (*p == 0x0D)  /* Unix or Mac return */
				{
					for (; start < p; start++)
						*q++ = *start | 0x80;
					i ++;
					*q++ = *p++;   /* LF  */
					start = NULL;   /* reset start if we see normal line return */
				}
				else
				{
					i ++ ;
					p ++ ;
				}
			}
			else
			{
				if (*p == '~' && *(p+1) == '{')    /* switch to GB mode */
				{
					start = p + 2;
					p += 2;
					i += 2;
				}
				else if (*p == '~' && *(p+1) == 0x0D && *(p+2) == 0x0A)  /* line-continuation marker */
				{
					i += 3;
					p += 3;
				}
				else if (*p == '~' && *(p+1) == 0x0A)  /* line-continuation marker */
				{
					i += 2;
					p += 2;
				}
				else if (*p == '~' && *(p+1) == 0x0D)  /* line-continuation marker */
				{
					i += 2;
					p += 2;
				}
				else if (*p == '~' && *(p+1) == '~')   /* ~~ means ~ */
				{
					*q++ = '~';
					p += 2;
					i += 2;
				}
				else
				{
					i ++;
					*q++ = *p++;
				}
			}
		}
	}
	*q = '\0';
	obj->len = q - output;
	if (start)
	{
#if 0
		if ((p - start) < sizeof(obj->uncvtbuf))
		{
			q = obj->uncvtbuf;
			for (; start < p; start++)
				*q++ = *start;
			*q = '\0';
		}
		else  /* if leftover is too big, we give up */
		{
			obj->len += p - start;
			for (; start < p; start++)
				*q++ = *start;
			*q = '\0';
		}
#else 
		/* Consider sizeof uncvtbuf is only 8 byte long, it's not enough 
		   for HZ anyway. Let's convert leftover to GB first and deal with
		   unfinished buffer in the coming block.
		*/
		obj->len += p - start;
		for (; start < p; start++)
			*q++ = *start | 0x80;
		*q = '\0';

		q = obj->uncvtbuf;
		XP_STRCPY((char *)q, "~{");
#endif
	}

    return output;
}


static unsigned char *
mz_b52b5(CCCDataObject *obj, const unsigned char *kscbuf, int32 kscbufsz)
{
    return(mz_ksc2ksc(obj, kscbuf, kscbufsz));
}

/*
 * this routine is needed to make sure parser and layout see whole
 * characters, not partial characters
 * XXX - obj->uncvtbuf needs to have atleast 4 bytes space.
 */
static unsigned char *
mz_cns2cns(CCCDataObject *obj, const unsigned char *cnsbuf, int32 cnsbufsz)
{
	unsigned char	b;
	int32			left_over;
	int32			len;
	unsigned char	*p;
	unsigned char	*q;
	unsigned char	*ret;
	int32			total;

	if ((!obj) || (!cnsbuf) || (cnsbufsz < 0))
	{
		return NULL;
	}

	total = strlen((char*)obj->uncvtbuf) + cnsbufsz;
	ret = (unsigned char *) XP_ALLOC(total + 1);
	if (!ret)
	{
		obj->retval = MK_OUT_OF_MEMORY;
		return NULL;
	}

	p = ret;
	q = obj->uncvtbuf;
	while (*q)
	{
		*p++ = *q++;
	}

	q = (unsigned char *) cnsbuf;
	while (cnsbufsz)
	{
		*p++ = *q++;
		cnsbufsz--;
	}

	p = ret;
	len = total;
	left_over = 0;
	while (len)
	{
		b = *p++;
		len--;
		if (b == 0x8E) {
			/* 4 bytes */
			if (len < 3) {
				left_over = len+1;
				break;
			}
			p+=3;
			len-=3;
		}
		else if (b < 0xa1)
		{
			/* single byte */
		}
		else if (b < 0xff)
		{
			/* 2 bytes */
			if (len == 0)
			{
				left_over = 1;
				break;
			}
			p++;
			len--;
		}
		else /* (b == 0xff) */
		{
			/* single byte */
		}
	}

	obj->len = total - left_over;

	q = --p;
	p = obj->uncvtbuf;
	while (left_over)
	{
		*p++ = *q++;
		left_over--;
	}
	*p = 0;

	ret[obj->len] = 0;

	return ret;
}


CCCDataObject *
INTL_CreateCharCodeConverter()
{
	return XP_NEW_ZAP(CCCDataObject);
}


void
INTL_DestroyCharCodeConverter(CCCDataObject *obj)
{
	XP_FREE(obj);
}


unsigned char *
INTL_CallCharCodeConverter(CCCDataObject *obj, const unsigned char *buf,
	int32 bufsz)
{
	return (obj->cvtfunc)(obj, buf, bufsz);
}


	/* INTL_GetCharCodeConverter:
	 * RETURN: 1 if converter found, else 0
	 * Also, sets:
	 *			obj->cvtfunc:	function handle for chararcter
	 *					code set streams converter
	 *			obj->cvtflag:	(Optional) flag to converter
	 *					function
	 *			obj->from_csid:	Code set converting from
	 *			obj->to_csid:	Code set converting to
	 * If the arg to_csid==0, then use the the conversion  for the
	 * first conversion entry that matches the from_csid.
	 */
int
INTL_GetCharCodeConverter(	register int16	from_csid,
				register int16	to_csid,
				CCCDataObject	*obj)
{
	register cscvt_t		*cscvtp;

	if (from_csid == CS_DEFAULT)
	{
		if (obj->current_stream == NULL)  /* Get Global if no current window */
			obj->from_csid = INTL_DefaultDocCharSetID(0);
		else
			obj->from_csid = INTL_DefaultDocCharSetID(obj->current_stream->window_id);
	}
	else
		obj->from_csid = from_csid;

		/* Look-up conversion method given FROM and TO char. code sets	*/
	cscvtp = cscvt_tbl;
	while (cscvtp->from_csid) {
		if (cscvtp->from_csid == from_csid) {
			if (to_csid == 0) {				/* unknown TO codeset	*/
/*
 * disgusting hack...
 */
#ifdef XP_UNIX
				if ((cscvtp->to_csid == CS_CNS_8BIT) && haveBig5) {
					cscvtp++;
					continue;
				}
#endif
				to_csid = cscvtp->to_csid;
				break;
			} else if (cscvtp->to_csid == to_csid)
				break;
		}
		cscvtp++;
	}
	obj->to_csid = to_csid;
	obj->cvtflag = cscvtp->cvtflag;
	obj->cvtfunc = cscvtp->cvtmethod;

	return (obj->cvtfunc) ? 1 : 0;
}

/*
 INTL_DefaultMailCharSetID,
   Based on DefaultDocCSID, it determines which CSID to use for mail and news.
   Right now, if it's Japanese code, we return JIS otherwise LATIN1.
*/
int16 INTL_DefaultMailCharSetID(int16 csid)
{
	int16 iRet ;
	if (csid == 0)
		csid = INTL_DefaultDocCharSetID(0);
	csid = csid & ~CS_AUTO;
	switch (csid) {
	  case CS_JIS:
	  case CS_SJIS:
	  case CS_EUCJP:
		iRet = CS_JIS;
		break ;
	  case CS_KSC_8BIT:
		iRet = CS_KSC_8BIT;
		break;
	  case CS_GB_8BIT:
		iRet = CS_GB_8BIT;
		break;
	  case CS_BIG5:
	  case CS_CNS_8BIT:
	    iRet = CS_BIG5;
	    break;
	  case CS_LATIN2:
	  case CS_CP_1250:
	  case CS_MAC_CE:
	    iRet = CS_LATIN2;
	    break;  	  	
	  case CS_8859_5:
	  case CS_MAC_CYRILLIC:
	  case CS_CP_1251:
	  case CS_KOI8_R:
	    iRet = CS_KOI8_R;
	    break;  	  	
	  case CS_MAC_GREEK:
	  case CS_8859_7:
	    iRet = CS_8859_7;
	    break;  	  	
	  case CS_MAC_TURKISH:
	  case CS_8859_9:
	    iRet = CS_8859_9;
	    break;  	  	
	  default:
	    iRet = CS_LATIN1;
		break ;
	}

	return iRet ;
}

/*
 INTL_DefaultWinCharSetID,
   Based on DefaultDocCSID, it determines which Win CSID to use for Display
*/
int16 INTL_DefaultWinCharSetID(MWContext *context)
{
	cscvt_t		*cscvtp;
	int16       from_csid = 0,  to_csid = 0;

	if (context && context->win_csid)
		return context->win_csid;
	from_csid = INTL_DefaultDocCharSetID(context) & ~CS_AUTO;	/* remove auto bit  */

	/* Look-up conversion method given FROM and TO char. code sets	*/
	cscvtp = cscvt_tbl;
	while (cscvtp->from_csid)
	{
		if (cscvtp->from_csid == from_csid)
		{
/*
 * disgusting hack...
 */
#ifdef XP_UNIX
			if ((cscvtp->to_csid == CS_CNS_8BIT) && haveBig5) {
				cscvtp++;
				continue;
			}
#endif
			to_csid = cscvtp->to_csid;
			break ;
		}
		cscvtp++;
	}
#ifndef XP_MAC
	return to_csid == 0 ? CS_LATIN1: to_csid ;
#else /* XP_UNIX */
	return to_csid == 0 ? CS_MAC_ROMAN: to_csid ;
#endif /* XP_UNIX */
}

/*
 INTL_DocToWinCharSetID,
   Based on DefaultDocCSID, it determines which Win CSID to use for Display
*/
int16 INTL_DocToWinCharSetID(int16 csid)
{
	cscvt_t		*cscvtp;
	int16       from_csid = 0,  to_csid = 0;

	from_csid = csid & ~CS_AUTO;	/* remove auto bit  */

	/* Look-up conversion method given FROM and TO char. code sets	*/
	cscvtp = cscvt_tbl;
	while (cscvtp->from_csid)
	{
		if (cscvtp->from_csid == from_csid)
		{
/*
 * disgusting hack...
 */
#ifdef XP_UNIX
			if ((cscvtp->to_csid == CS_CNS_8BIT) && haveBig5) {
				cscvtp++;
				continue;
			}
#endif
			to_csid = cscvtp->to_csid;
			break ;
		}
		cscvtp++;
	}
#ifndef XP_MAC
	return to_csid == 0 ? CS_LATIN1: to_csid ;
#else /* XP_UNIX */
	return to_csid == 0 ? CS_MAC_ROMAN: to_csid ;
#endif /* XP_UNIX */
}



int16
INTL_CharSetNameToID(char	*charset)
{
	csname2id_t	*csn2idp;
	int16			csid;

			/* Parse the URL charset string for the charset ID.
			 * If no MIME Content-Type charset pararm., default.
			 * HTML specifies ASCII, but let user override cuz
			 * of prior conventions (i.e. Japan).
			 */
	csn2idp = csname2id_tbl;
	csid = csn2idp->cs_id;		/* 1st entry is default codeset ID	*/

	if (charset != NULL) {		/* Linear search for charset string */
		while (*(csn2idp->cs_name) != '\0') {
 			if (strcasecomp(charset, (char *)csn2idp->cs_name) == 0) {
 				return(csn2idp->cs_id);
 			}
 			csn2idp++;
		}
 	}
	return(csn2idp->cs_id);		/* last entry is CS_UNKNOWN	*/
}
unsigned char *INTL_CsidToCharsetNamePt(int16 csid)
{
	csname2id_t	*csn2idp;

	if (csid & CS_AUTO)
		return (unsigned char *)"AUTO";
	csn2idp = &csname2id_tbl[1];	/* First one is reserved, skip it. */
	csid &= 0xff;

	/* Linear search for charset string */
	while (*(csn2idp->cs_name) != '\0') {
		if ((csn2idp->cs_id & 0xff) == csid)
			return csn2idp->cs_name;
 		csn2idp++;
	}
	return (unsigned char *)"";
}

void 
INTL_CharSetIDToName(int16 csid, char  *charset)
{
	if (charset) {	
		strcpy(charset,(char *)INTL_CsidToCharsetNamePt(csid));
	}
}

/***********************************************************
 Input:  int (int16) charsetid		Char Set ID
         char *pstr				   Buffer which always point to Multibyte char first byte
                      			   or normal single byte char
 Output: return next char position
***********************************************************/
char * INTL_NextChar(int charsetid, char *pstr)
{
#ifdef NOT
	/* Need to remove strlen later and pass in the length of the string */
	int len = mblen(pstr, strlen(pstr));
	return pstr+(len <= 0 ? 1 : len) ;
#else
	csinfo_t	*pFontTable ;
	unsigned char ch ;
	int i;

	if ((INTL_CharSetType(charsetid) == SINGLEBYTE) || (*pstr == 0)) /* If no csid, assume it's not multibyte */
		return pstr + 1;

	ch = *pstr ;
	pFontTable = &csinfo_tbl[0] ;
	for (;pFontTable->csid; pFontTable++)
	{
		if (pFontTable->csid == charsetid)
		{
			for (i=0; i<MAX_FIRSTBYTE_RANGE && pFontTable->enc[i].bytes > 0; i++)
			{
				if ((ch >= pFontTable->enc[i].range[0]) && (ch <= pFontTable->enc[i].range[1]))
				{	
					int j = 0;
					for (j=0; pstr[j] && j < pFontTable->enc[i].bytes; j++)
						;
					if (j < pFontTable->enc[i].bytes)
						return pstr+1;
					else
						return pstr+j;
				}
			}
			return pstr + 1;
		}
	}
	return pstr + 1;
#endif
}

/********************************************************
 Input:  MWContext context		Window Context
         unsigned char ch		Buffer which always point to Multibyte char
								first byte or normal single byte char
 Output: 1, if ch is under ShiftJIS type MultiByte first byte range
         2, if ch is under EUC type MultiByte first byte range
		 0, if it's not MultiByte firstbyte
*********************************************************/

int
INTL_IsLeadByte(int charsetid, unsigned char ch)
{
	csinfo_t	*pFontTable ;
	int i;

	if ((INTL_CharSetType(charsetid) == SINGLEBYTE) || (ch == 0)) /* If no csid, assume it's not multibyte */
		return 0;

	pFontTable = &csinfo_tbl[0] ;
	for (;pFontTable->csid; pFontTable++)
	{
		if (pFontTable->csid == charsetid)
		{
			for (i=0; i<MAX_FIRSTBYTE_RANGE && pFontTable->enc[i].bytes > 0; i++)
				if ((ch >= pFontTable->enc[i].range[0]) &&
					(ch <= pFontTable->enc[i].range[1]))
					return pFontTable->enc[i].bytes-1;
			return 0 ;
		}
	}
	return 0;
}

int 
INTL_CharLen(int charsetid, unsigned char *pstr)
{
	int i,l;
	if ((!pstr) || (!*pstr)) return 0;
	l = 1 + INTL_IsLeadByte(charsetid, *pstr);
	for(i=1, pstr++ ; (i<l) && (*pstr); i++, pstr++)
		;
	return i;
}

int
INTL_ColumnWidth(int charsetid, unsigned char *str)
{
	unsigned char	b;
	csinfo_t	*entry;
	int		i;

	if ((!str) || (!*str))
	{
		return 0;
	}

	if (INTL_CharSetType(charsetid) == SINGLEBYTE)
	{
		return 1;
	}

	for (entry = csinfo_tbl; entry->csid; entry++)
	{
		if (entry->csid == charsetid)
		{
			b = *str;
			for (i = 0; (i < MAX_FIRSTBYTE_RANGE) &&
				entry->enc[i].bytes; i++)
			{
				if ((b >= entry->enc[i].range[0]) &&
					(b <= entry->enc[i].range[1]))
				{
					return entry->enc[i].columns;
				}
			}
		}
	}

	return 1;
}

/********************************************************
 Input:  int (int16) charsetid	Char Set ID
         char *pstr				Buffer which always point to Multibyte char
								first byte or normal single byte char
		 int  pos				byte position
 Output: 0,   if pos is not on kanji char
 		 1,   if pos is on kanji 1st byte
	     2,   if pos is on kanji 2nd byte
		 3,   if pos is on kanji 3rd byte
 Note:   Current this one only works for ShiftJis type multibyte not for JIS or EUC
*********************************************************/
int
INTL_NthByteOfChar(int charsetid, char *pstr, int pos)
{
	int	i;
	int	prev;

	pos--;

	if
	(
		(INTL_CharSetType(charsetid) == SINGLEBYTE) ||
		(!pstr)  ||
		(!*pstr) ||
		(pos < 0)
	)
	{
		return 0;
	}

	i = 0;
	prev = 0;
	while (pstr[i] && (i <= pos))
	{
		prev = i;
		i += INTL_CharLen(charsetid, (unsigned char *) &pstr[i]);
	}
	if (i <= pos)
	{
		return 0;
	}
	if (INTL_CharLen(charsetid, (unsigned char *) &pstr[prev]) < 2)
	{
		return 0;
	}

	return pos - prev + 1;
}

int
INTL_IsHalfWidth(MWContext *context, unsigned char *pstr)
{
	int	c;

	c = *pstr;

	switch (context->win_csid)
	{
	case CS_SJIS:
		if ((0xa1 <= c) && (c <= 0xdf))
		{
			return 1;
		}
		break;
	case CS_EUCJP:
		if (c == 0x8e)
		{
			return 1;
		}
		break;
	default:
		break;
	}

	return 0;
}

int16
GetMimeCSID(int16	win_csid, char	**mime_charset)
{
	csmime_t	*csmimep = csmime_tbl;

	while(csmimep->win_csid != 0) {
		if (win_csid == csmimep->win_csid) {
			*mime_charset = csmimep->mime_charset;
			return(csmimep->mime_csid);
		}
		csmimep++;
	}
	*mime_charset = "iso-8859-1";
	return(win_csid);			/* causes no conversion */
}

char *
INTL_CharSetDocInfo(MWContext *context)
{
	register int16			doc_csid = context->doc_csid;
	register csname2id_t	*csn2idp;
	char					*s = NULL;
	int						detected = 0;

	if (doc_csid == CS_DEFAULT) {
		doc_csid = INTL_DefaultDocCharSetID(context) & ~CS_AUTO;	/* Get CSID from prefs	*/
	} else if (doc_csid & CS_AUTO) {
		doc_csid &= ~CS_AUTO;				/* mask off bit for name lookup */
		detected = 1;
	} else {
		StrAllocCopy(s, context->mime_charset);	/* string from MIME header */

		if (doc_csid == CS_UNKNOWN)
				StrAllocCat(s, XP_GetString(XP_DOCINFO_1));
		return(s);
	}
			/* Look up name for default & autodetected CSIDs		*/
#ifdef XP_WIN
	csn2idp = &csname2id_tbl[1] ;	/* skip first default one	*/
	for (; *(csn2idp->cs_name) != '\0'; csn2idp++)
#else
	for (csn2idp = csname2id_tbl; *(csn2idp->cs_name) != '\0'; csn2idp++)
#endif
	{
 		if (doc_csid == csn2idp->cs_id) {
			StrAllocCopy(s, (char *)csn2idp->cs_name);
			if (detected)
				StrAllocCat(s, XP_GetString(XP_DOCINFO_2));
			else
				StrAllocCat(s, XP_GetString(XP_DOCINFO_3));
			return(s);
 		}
	}
	StrAllocCopy(s, context->mime_charset);	/* string from MIME header */
	StrAllocCat(s, XP_GetString(XP_DOCINFO_4));
	return (s);
}

#ifdef XP_WIN

/*
 This routine will change the default URL charset to
 newCharset, BTW newCharset is passed from UI.
*/
void
FE_ChangeURLCharset(const char *charset)
{
	csname2id_t	*csn2idp;
	char			*cp;

	if (charset == NULL)
		return;

	csn2idp = csname2id_tbl;

	cp = (char *)charset;
	if (cp)
		while (*cp != '\0') {
			*cp = tolower(*cp);
			cp++;
    	}

	while (*(csn2idp->cs_name) != '\0') {
 		if (strcmp(charset, (char *)csn2idp->cs_name) == 0) {
				INTL_ChangeDefaultCharSetID(csn2idp->cs_id);
 				return;
 			}
 			csn2idp++;
		}
}

void
INTL_ChangeDefaultCharSetID(int16 csid)
{
	csname2id_tbl[0].cs_id = csid;
}

#endif /* XP_WIN */

XP_Bool
INTL_CanAutoSelect(int16 csid)
{
	register cscvt_t		*cscvtp;

	cscvtp = cscvt_tbl;
	while (cscvtp->from_csid) {
		if (cscvtp->from_csid == csid) {
			if (cscvtp->autoselect)
				return TRUE;
			else
				return FALSE;
		}
		cscvtp++;
	}
	return FALSE;
}



PRIVATE int DecodeBase64 (const char *in, char *out)
{
  /* reads 4, writes 3. */
  int j;
  unsigned long num = 0;

  for (j = 0; j < 4; j++)
	{
	  unsigned char c;
	  if (in[j] >= 'A' && in[j] <= 'Z')		 c = in[j] - 'A';
	  else if (in[j] >= 'a' && in[j] <= 'z') c = in[j] - ('a' - 26);
	  else if (in[j] >= '0' && in[j] <= '9') c = in[j] - ('0' - 52);
	  else if (in[j] == '+')				 c = 62;
	  else if (in[j] == '/')				 c = 63;
	  else if (in[j] == '=')				 c = 0;
	  else
	  {
		/*	abort ();	*/
		strcpy(out, in);	/* I hate abort */
		return 0;
	  }
	  num = (num << 6) | c;
	}

  *out++ = (unsigned char) (num >> 16);
  *out++ = (unsigned char) ((num >> 8) & 0xFF);
  *out++ = (unsigned char) (num & 0xFF);
  return 1;
}

PRIVATE char *DecodeQP(char *in)
{
	int i = 0, length;
	char token[3];
	char *out, *dest = 0;

	out = dest = (char *)XP_ALLOC(strlen(in)+1);
	if (dest == NULL)
		return NULL;
	memset(out, 0, strlen(in)+1);
	length = strlen(in);
  	while (length > 0 || i != 0)
	{
	  	while (i < 3 && length > 0)
		{
		  	token [i++] = *in;
		  	in++;
		  	length--;
		}

	  	if (i < 3)
		{
		  /* Didn't get enough for a complete token.
			 If it might be a token, unread it.
			 Otherwise, just dump it.
			 */
			strncpy (out, token, i);
		  	break;
		}
	  	i = 0;

	  	if (token [0] == '=')
		{
		  	unsigned char c = 0;
		  	if (token[1] >= '0' && token[1] <= '9')
				c = token[1] - '0';
		  	else if (token[1] >= 'A' && token[1] <= 'F')
				c = token[1] - ('A' - 10);
		  	else if (token[1] >= 'a' && token[1] <= 'f')
				c = token[1] - ('a' - 10);
		  	else if (token[1] == CR || token[1] == LF)
			{
			  	/* =\n means ignore the newline. */
			  	if (token[1] == CR && token[2] == LF)
					;		/* swallow all three chars */
			  	else
				{
				  	in--;	/* put the third char back */
				  	length++;
				}
			  	continue;
			}
		  	else
			{
			  	/* = followed by something other than hex or newline -
				 pass it through unaltered, I guess.  (But, if
				 this bogus token happened to occur over a buffer
				 boundary, we can't do this, since we don't have
				 space for it.  Oh well.  Screw it.)  */
			  	if (in > out) *out++ = token[0];
			  	if (in > out) *out++ = token[1];
			  	if (in > out) *out++ = token[2];
			  	continue;
			}

		  	/* Second hex digit */
		  	c = (c << 4);
		  	if (token[2] >= '0' && token[2] <= '9')
				c += token[2] - '0';
		  	else if (token[2] >= 'A' && token[2] <= 'F')
				c += token[2] - ('A' - 10);
		  	else if (token[2] >= 'a' && token[2] <= 'f')
				c += token[2] - ('a' - 10);
		  	else
			{
			  	/* We got =xy where "x" was hex and "y" was not, so
				 treat that as a literal "=", x, and y.  (But, if
				 this bogus token happened to occur over a buffer
				 boundary, we can't do this, since we don't have
				 space for it.  Oh well.  Screw it.) */
			  	if (in > out) *out++ = token[0];
			  	if (in > out) *out++ = token[1];
			  	if (in > out) *out++ = token[2];
			  	continue;
			}

		  	*out++ = (char) c;
		}
	  	else
		{
		  	*out++ = token [0];

		  	token[0] = token[1];
		  	token[1] = token[2];
		  	i = 2;
		}
	}
	/* take care of special underscore case */
	for (out = dest; *out; out++)
		if (*out == '_') 	*out = ' ';
	return dest;
	
}

PRIVATE char *DecodeBase64Buffer(char *subject)
{
	char *output = 0;
	char *pSrc, *pDest ;
	int i ;

	StrAllocCopy(output, subject); /* Assume converted text are always 
									  less than source text */

	pSrc = subject;
	pDest = output ;
	for (i = strlen(subject); i > 3; i -= 4)
	{
		if (DecodeBase64(pSrc, pDest) == 0)
		{
			pSrc += 4;
			pDest += 4;
		}
		else
		{
			pSrc += 4;
			pDest += 3;
		}
	}
	
	*pDest = '\0';
	return output;
}

/* 
 ConvSubject
  This functions converts mail charset to Window charset for subject
	Syntax:   =?MimeCharset?[B|Q]?text?=
		MimeCharset = ISO-2022-JP
		              ISO-8859-1
					  ISO-8859-?
					  ....
		?B? :  Base64 Encoding          (used for multibyte encoding)
		?Q? :  Quote Printable Encoding (used for single byte encoding)

  	eg. for Japanese mail, it looks like
    	 =?ISO-2022-JP?B?   ........   ?=
*/
PUBLIC
char *IntlDecodeMimePartIIStr(const char *header, int wincsid, XP_Bool plaindecode)
{
    CCCDataObject	*obj;
	char *buffer = NULL, *convbuf = NULL;
	char *subject = NULL;
	char *p, *q, *text;
	char *begin, *end, *retbuff;
	int16	 csid = 0;
	int  len;
	int  ret = 0;
	int16 mailcsid = INTL_DefaultMailCharSetID(wincsid);

	if (header == 0 || *header == '\0')
		return NULL;
	if (wincsid == 0) /* Use global if undefined */
		wincsid = INTL_DefaultWinCharSetID(0);

	if (plaindecode == FALSE && wincsid == CS_GB_8BIT)
	{  /* for subject list pane, if it's GB, we only do HZ conversion */
		if (XP_STRSTR(header, "~{") == NULL)  
			return NULL;

    	obj = XP_NEW_ZAP(CCCDataObject);
		if (obj == NULL)
			return NULL;
		INTL_GetCharCodeConverter((int16)wincsid, (int16)wincsid, obj);
		convbuf = NULL;
		if (obj->cvtfunc)
			convbuf = (char*)obj->cvtfunc(obj, (unsigned char *)header, (int32)XP_STRLEN((char*)header));
		XP_FREE(obj);
		return convbuf;
	}
	if((! onlyAsciiStr(header) ) ||								/* it has 8 bit data, or */
	   ((mailcsid & STATEFUL) && (XP_STRCHR(header, '\033'))))	/* it is statefule encoding with esc */
	{	/* then we assume it is not mime part 2  encoding, we convert from the internet encoding to wincsid */
		if (plaindecode == FALSE)
		{      
			char* tmpbuf = NULL;
			/* Copy buf to tmpbuf, this guarantee the convresion won't overwrite the origional buffer and  */
			/* It will always return something it any conversion occcur */
			StrAllocCopy(tmpbuf, header);
			
			if(tmpbuf == NULL)
				return NULL;
			
    		obj = XP_NEW_ZAP(CCCDataObject);
			if (obj == NULL)
				return NULL;
			INTL_GetCharCodeConverter(mailcsid, (int16)wincsid, obj);
			convbuf = NULL;
			if (obj->cvtfunc)
				convbuf = (char*)obj->cvtfunc(obj, (unsigned char*)tmpbuf, (int32)XP_STRLEN((char*)tmpbuf));
			XP_FREE(obj);
			
			if(convbuf != tmpbuf)
				XP_FREE(tmpbuf);
			return convbuf;
		}
		return NULL;
		/* IMPORTANT NOTE: */
		/* Return NULL in this interface only mean ther are no conversion */
		/* It does not mean the conversion is store in the origional buffer */
		/* and the length is not change. This is differ from other conversion routine */
	}

    obj = XP_NEW_ZAP(CCCDataObject);
	if (obj == NULL)
		return NULL;


	StrAllocCopy(buffer, header);  /* temporary buffer */
	StrAllocCopy(subject, header);

	if (buffer == NULL || subject == NULL)
		return NULL;
	retbuff = subject;
	begin = buffer;

	while (*begin != '\0')
	{
		/*		GetCharset();		*/
		p = strstr(begin, "=?");
		if (p == NULL)
			break;
		subject += p - begin; /* skip strings don't need conversion */
		p += 2;
		q = strchr(p, '?');  /* Get charset info */
		if (q == NULL)
			break;
		*q++ = '\0';
		csid = INTL_CharSetNameToID(p);
		if (csid == CS_UNKNOWN)
		{
			/*
			 * @@@ may want to use context's default doc_csid in the future
			 */
			break;
		}

		if (*(q+1) == '?' &&
		    (*q == 'Q' || *q == 'q'))
		{			/* Quote printable  */
			p = strstr(q+2, "?=");
			if (p == NULL)
				break;
			*p = '\0';
			text = DecodeQP(q+2);
		}
 		else if (*(q+1) == '?' &&
		    (*q == 'B' || *q == 'b'))
		{			/* Base 64  */
			p = strstr(q+2, "?=");
			if (p == NULL)
				break;
			*p = '\0';
			text = DecodeBase64Buffer(q+2);
		}
		else
			break;
		if (text == NULL)
			break ;

		end = p + 2;
		if (plaindecode)
		{
           	/* move converted data to original buffer */
			ret = 1;
	    	len = strlen(text);
			XP_MEMCPY(subject, (char *)text, len);
			XP_MEMMOVE(subject+len, end, strlen(end)+1); /* move '\0' also */
			subject += len;
			XP_FREE(text);
		}
		else	/*		Convert to window encoding	*/
		{
			INTL_GetCharCodeConverter(csid, (int16)wincsid, obj);

			convbuf = NULL;
			if (obj->cvtfunc)
				convbuf = (char*)obj->cvtfunc(obj, (unsigned char *)text, strlen((char*)text));
			else if (csid == wincsid)
			{    /* pass through if no conversion needed */
				StrAllocCopy(convbuf, (const char *)text);
			}

			if (convbuf)
			{
            	/* move converted data to original buffer */
				ret = 1;
		    	len = strlen(convbuf);
				XP_MEMCPY(subject, (char *)convbuf, len);
				XP_MEMMOVE(subject+len, end, strlen(end)+1); /* move '\0' also */
				if (convbuf != text)
				{
					XP_FREE(convbuf);
				}
				subject += len;
				if(convbuf != text)
					XP_FREE(text);
			}
			else  /* shouldn't come here */
			{
				XP_FREE(text);
				break;
			}
		}
		begin = end;
	}
	XP_FREE(obj);
	if (buffer)
		XP_FREE(buffer);

	if (ret)
		return retbuff;
	else
	{
		XP_FREE(retbuff);
		return NULL;  /* null means no conversion */
	}
}



static char basis_64[] =
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
PRIVATE int EncodeBase64 (const char *in, char *out)
{
	unsigned char c1, c2, c3;
	c1 = in[0];
	c2 = in[1];
	c3 = in[2];

    *out++ = basis_64[c1>>2];
    *out++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];

    *out++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
    *out++ = basis_64[c3 & 0x3F];
	return 1;
}



PRIVATE char *EncodeBase64Buffer(char *subject)
{
	char *output = 0;
	char *pSrc, *pDest ;
	int i ;

	output = (char *)XP_ALLOC(strlen(subject) * 4 / 3 + 4);
	if (output == NULL)
		return NULL;

	pSrc = subject;
	pDest = output ;
	for (i = strlen(subject); i >= 3; i -= 3)
	{
		if (EncodeBase64(pSrc, pDest) == 0) /* error */
		{
			pSrc += 3;
			pDest += 3;
		}
		else
		{
			pSrc += 3;
			pDest += 4;
		}
	}
	/* in case (i % 3 ) == 1 or 2 */
	if(i > 0)
	{
		char in[3];
		int j;
		in[0] = in[1] = in[2] ='\0';
		for(j=0;j<i;j++)
			in[j] = *pSrc++;
		EncodeBase64(in, pDest);
		for(j=i+1;j<4;j++)
			pDest[j] = '=';
		pDest += 4;
	}
	*pDest = '\0';
	return output;
}



PRIVATE char *EncodeQPBuffer(char *subject)
{
	char *output = 0;
	unsigned char *p, *pDest ;
	int i, n, len ;

	if (subject == NULL || *subject == '\0')
		return NULL;
	len = strlen(subject);
	output = XP_ALLOC(len * 3 + 1);
	if (output == NULL)
		return NULL;

	p = (unsigned char*)subject;
	pDest = (unsigned char*)output ;

	for (i = 0; i < len; i++)
	{
		/* XP_IS_ALPHA(*p) || XP_IS_DIGIT(*p)) */
		if ((*p < 0x80) &&
			(((*p >= 'a') && (*p <= 'z')) ||
			 ((*p >= 'A') && (*p <= 'Z')) ||
			 ((*p >= '0') && (*p <= '9')))
		   )
			*pDest = *p;
		else
		{
			*pDest++ = '=';
			n = (*p & 0xF0) >> 4; /* high byte */
			if (n < 10)
				*pDest = '0' + n;
			else
				*pDest = 'A' + n - 10;
			pDest ++ ;

			n = *p & 0x0F;			/* low byte */
			if (n < 10)
				*pDest = '0' + n;
			else
				*pDest = 'A' + n - 10;
		}

		p ++;
		pDest ++;
	}

	*pDest = '\0';
	return output;
}

#define MAXLINELEN 72
#define IS_MAIL_SEPARATOR(p) ((*(p) == ',' || *(p) == ' ' || *(p) == '\"' || *(p) == ':' || \
  *(p) == '(' || *(p) == ')' || *(p) == '\\' || (unsigned char)*p < 0x20))

char *encode_next8bitword(int wincsid, char *src)
{
	char *p;
	XP_Bool non_ascii = FALSE;
	if (src == NULL)
		return NULL;
	p = src;
	while (*p == ' ')
		p ++ ;
	while ( *p )
	{
		if ((unsigned char) *p > 0x7F)
			non_ascii = TRUE;
		if ( IS_MAIL_SEPARATOR(p) )
		{
			break;
		}
		p = INTL_NextChar(wincsid, p);
	}

	if (non_ascii)
		return p;
	else
		return NULL;
}


char * encode_mail_address(int wincsid, const char *src, CCCDataObject *obj)
{
	char *begin, *end;
	char *retbuf = NULL, *srcbuf = NULL;
	char sep;
	char *name;
	int  retbufsize;
	int line_len = 0;
	int srclen;

	if (src == NULL || *src == '\0')
		return NULL;
	/* make a copy, so don't need touch original buffer */
	StrAllocCopy(srcbuf, src);
	if (srcbuf == NULL)
		return NULL;
	begin = srcbuf;
	GetMimeCSID ((int16)wincsid, &name);

	/* allocate enough buffer for conversion, this way it can avoid
	   do another memory allocation which is expensive
	 */
	   
	retbufsize = XP_STRLEN(srcbuf) * 3 + MAX_CSNAME + 8;
	retbuf =  XP_ALLOC(retbufsize);
	if (retbuf == NULL)  /* Give up if not enough memory */
	{
		XP_FREE(srcbuf);
		return NULL;
	}

	*retbuf = '\0';

	srclen = XP_STRLEN(srcbuf);
	while (begin < (srcbuf + srclen))
	{	/* get block of data between commas */
		char *p, *q;
		char *buf1, *buf2;
		int len, newsize, convlen, retbuflen;
		XP_Bool non_ascii;

		retbuflen = XP_STRLEN(retbuf);
		end = NULL;
		/* scan for separator, conversion happens on 8bit
		   word between separators
		 */
		if (IS_MAIL_SEPARATOR(begin))
		{   /*  skip white spaces and separator */
			q = begin;
			while (	IS_MAIL_SEPARATOR(q) )
				q ++ ;
			sep = *(q - 1);
			*(q - 1) = '\0';
			end = q - 1;
		}
		else
		{
			sep = '\0';
			/* scan for next separator */
			non_ascii = FALSE;
			for (q = begin; *q;)
			{
				if ((unsigned char) *q > 0x7F)
					non_ascii = TRUE;
				if ( IS_MAIL_SEPARATOR(q) )
				{
					if ((*q == ' ') && (non_ascii == TRUE))
					{
						while ((p = encode_next8bitword(wincsid, q)))
						{
							if (p == NULL)
								break;
							q = p;
							if (*p != ' ')
								break;
						}
					}
					sep = *q;
					*q = '\0';
					end = q;
					break;
				}
				q = INTL_NextChar(wincsid, q);
			}
		}

		len = XP_STRLEN(begin);
		if (onlyAsciiStr(begin) == 0)
		{
			if (obj && obj->cvtfunc)
			{
				buf1 = (char *) obj->cvtfunc(obj, (unsigned char *)begin, len);
				if (!buf1)
				{
					XP_FREE(srcbuf);
					XP_FREE(retbuf);
					return NULL;
				}
			}
			else
			{
				buf1 = XP_ALLOC(len + 1);
				if (!buf1)
				{
					XP_FREE(srcbuf);
					XP_FREE(retbuf);
					return NULL;
				}
				XP_MEMCPY(buf1, begin, len);
				*(buf1 + len) = '\0';
			}

			if (wincsid & MULTIBYTE)
			{
				/* converts to Base64 Encoding */
				buf2 = (char *)EncodeBase64Buffer(buf1);
			}
			else
			{
				/* Converts to Quote Printable Encoding */
				buf2 = (char *)EncodeQPBuffer(buf1);
			}


			if (buf1 && (buf1 != begin))
				XP_FREE(buf1);

			if (buf2 == NULL) /* QUIT if memory allocation failed */
			{
				XP_FREE(srcbuf);
				XP_FREE(retbuf);
				return NULL;
			}

			/* realloc memory for retbuff if necessary, 
			   7: =?...?B?..?=, 3: CR LF TAB */
			convlen = XP_STRLEN(buf2) + XP_STRLEN(name) + 7;
			newsize = convlen + retbuflen + 3 + 2;  /* 2:SEP '\0', 3:CRLFTAB */

			if (newsize > retbufsize)
			{
				char *tempbuf;
				tempbuf = XP_REALLOC(retbuf, newsize);
				if (tempbuf == NULL)  /* QUIT, if not enough memory left */
				{
					XP_FREE(buf2);
					XP_FREE(srcbuf);
					XP_FREE(retbuf);
					return NULL;
				}
				retbuf = tempbuf;
				retbufsize = newsize;
			}
			/* buf1 points to end of current retbuf */
			buf1 = retbuf + retbuflen; 

			if ((line_len > 10) && 
			    ((line_len + convlen) > MAXLINELEN))
			{
		  		*buf1++ = CR;
		  		*buf1++ = LF;
		  		*buf1++ = '\t';
				line_len = 0;
			}
			*buf1 = '\0';

			/* Add encoding tag for base62 and QP */
			XP_STRCAT(buf1, "=?");
			XP_STRCAT(buf1, name );
			if(wincsid & MULTIBYTE)
				XP_STRCAT(buf1, "?B?");
			else
				XP_STRCAT(buf1, "?Q?");
			XP_STRCAT(buf1, buf2);
			XP_STRCAT(buf1, "?=");

			line_len += convlen + 1;  /* 1: SEP */
			XP_FREE(buf2);	/* free base64 buffer */
		}
		else  /* if no 8bit data in the block */
		{
			newsize = retbuflen + len + 2 + 3; /* 2: ',''\0', 3: CRLFTAB */
			if (newsize > retbufsize)
			{
				char *tempbuf;
				tempbuf = XP_REALLOC(retbuf, newsize);
				if (tempbuf == NULL)
				{
					XP_FREE(srcbuf);
					XP_FREE(retbuf);
					return NULL;
				}
				retbuf = tempbuf;
				retbufsize = newsize;
			}
			buf1 = retbuf + retbuflen;

			if ((line_len > 10) && 
			    ((line_len + len) > MAXLINELEN))
			{
		  		*buf1++ = CR;
		  		*buf1++ = LF;
		  		*buf1++ = '\t';
				line_len = 0;
			}
			/* copy buffer from begin to buf1 stripping CRLFTAB */
			for (p = begin; *p; p++)
			{
				if (*p == CR || *p == LF || *p == TAB)
					len --;
				else
					*buf1++ = *p;
			}
			*buf1 = '\0';
			line_len += len + 1;  /* 1: SEP */
		}

		buf1 = buf1 + XP_STRLEN(buf1);
		if (sep == CR || sep == LF || sep == TAB) /* strip CR,LF,TAB */
			*buf1 = '\0';
		else
		{
			*buf1 = sep;
			*(buf1+1) = '\0';
		}

		if (end == NULL)
			break;
		begin = end + 1;
	}
	if (srcbuf)
		XP_FREE(srcbuf);
	return retbuf;
}


/*
	Latin1, latin2:
	   Source --> Quote Printable --> Encoding Info
	Japanese:
	   EUC,JIS,SJIS --> JIS --> Base64 --> Encoding Info
	Others:
	   No conversion  
    flag:   0:   8bit on
	        1:   mime_use_quoted_printable_p
	return:  NULL  if no conversion occured

*/
PUBLIC
char *IntlEncodeMimePartIIStr(char *subject, int wincsid, XP_Bool bUseMime)
{
	int iSrcLen;
	unsigned char *buf  = NULL;	/* Initial to NULL */
	int16 mail_csid;
   	CCCDataObject	*obj = NULL;
	char  *name;

	if (subject == NULL || *subject == '\0')
		return NULL;

	iSrcLen = XP_STRLEN(subject);
	if (wincsid == 0)
		wincsid = INTL_DefaultWinCharSetID(0) ;

	mail_csid = GetMimeCSID ((int16)wincsid, &name);
	
	/* check to see if subject are all ascii or not */
	if(onlyAsciiStr(subject))
		return NULL;
		
	if (mail_csid != wincsid)
	{
   		obj = XP_NEW_ZAP(CCCDataObject);
		if (obj == NULL)
			return 0;
		/* setup converter from wincsid --> mail_csid */
		INTL_GetCharCodeConverter((int16)wincsid, mail_csid, obj) ;
	}
	/* Erik said in the case of STATEFUL mail encoding, we should FORCE it to use */
	/* MIME Part2 to get ride of ESC in To: and CC: field, which may introduce more trouble */
	if((bUseMime) || (mail_csid & STATEFUL))/* call encode_mail_address */
	{
		buf = (unsigned char *)encode_mail_address(wincsid, subject, obj);
		if(buf == (unsigned char*)subject)	/* no encoding, set return value to NULL */
			buf =  NULL;
	}
	else
	{	/* 8bit, just do conversion if necessary */
		/* In this case, since the conversion routine may reuse the origional buffer */
		/* We better allocate one first- We don't want to reuse the origional buffer */
		
		if ((mail_csid != wincsid) && (obj->cvtfunc))
		{
			char* newbuf = NULL;
			/* Copy buf to newbuf */
			StrAllocCopy(newbuf, subject);
			if(newbuf != NULL)
			{
				buf = (unsigned char *)obj->cvtfunc(obj, (unsigned char*)newbuf, iSrcLen);
				if(buf != (unsigned char*)newbuf)
					XP_FREE(newbuf);
			}
		}
	}
	if (obj)   
		XP_FREE(obj);
	return (char*)buf;
	
	/* IMPORTANT NOTE: */
	/* Return NULL in this interface only mean ther are no conversion */
	/* It does not mean the conversion is store in the origional buffer */
	/* and the length is not change. This is differ from other conversion routine */
}


int16
INTL_DefaultTextAttributeCharSetID(MWContext *context)
{
	if (context && (context->win_csid))
	{
		return context->win_csid;
	}

	return INTL_DefaultWinCharSetID(context);
}


void
INTL_NumericCharacterReference(unsigned char *in, uint32 inlen, uint32 *inread,
	unsigned char *out, uint16 outbuflen, uint16 *outlen, Bool force)
{
	unsigned char	b;
#ifdef XP_MAC
	char		**cvthdl;
#endif  /* 'cuz it made Jamie unhappy */
	int		i;
	uint32		ncr;
	unsigned char	val;

	XP_ASSERT(outbuflen >= 10);

	for (i = 0; i < inlen; i++)
	{
		b = in[i];
		if ((b < '0') || (b > '9'))
		{
			break;
		}
	}
	if (i == 0)
	{
		*inread = 0;
		out[0] = 0;
		*outlen = 0;
		return;
	}
	if ((i >= inlen) && (!force))
	{
		*inread = (inlen + 1);
		out[0] = 0;
		*outlen = 0;
		return;
	}
	inlen = i;

	ncr = 0;
	for (i = 0; i < inlen; i++)
	{
		b = in[i];
		if ((b < '0') || ('9' < b))
		{
			break;
		}
		if (ncr < 256)
		{
			ncr = ((10 * ncr) + (b - '0'));
		}
	}
	*inread = i;

	if (ncr > 255)
	{
		val = (unsigned char) '?';
	}
	else
	{
		val = (unsigned char) ncr;
	}


#ifdef XP_MAC

#define xlat_LATIN1_TO_MAC_ROMAN	 128

	cvthdl = INTL_GetSingleByteTable(CS_LATIN1, CS_MAC_ROMAN,
		xlat_LATIN1_TO_MAC_ROMAN);
	if (cvthdl)
	{
		val = ((unsigned char) ((*cvthdl)[val]));
		INTL_FreeSingleByteTable(cvthdl);
	}

#endif /*XP_MAC*/


#ifdef USE_NPC

	out[0] = CSIDToNPC(CS_LATIN1);
	out[1] = val;
	*outlen = 2;

#else /* USE_NPC */

	out[0] = val;
	*outlen = 1;

#endif /* USE_NPC */

}


void
INTL_EntityReference(unsigned char val, unsigned char *out, uint16 outbuflen,
	uint16 *outlen)
{
	XP_ASSERT(outbuflen >= 10);

#ifdef USE_NPC

	out[0] = CSIDToNPC(CS_LATIN1);
	out[1] = val;
	*outlen = 2;

#else /* USE_NPC */

	out[0] = val;
	*outlen = 1;

#endif /* USE_NPC */

}


#ifndef USE_NPC

void
INTL_FreeFontEncodingList(INTL_FontEncodingList *list)
{
	if (list)
	{
		XP_FREE(list);
	}
}


INTL_FontEncodingList *
INTL_InternalToFontEncoding(int16 charset, unsigned char *text)
{
	INTL_FontEncodingList	*ret;

	ret = XP_NEW_ZAP(INTL_FontEncodingList);
	if (!ret)
	{
		return NULL;
	}

	ret->next = NULL;
	ret->charset = charset;
	ret->text = text;

	return ret;
}


#else /* USE_NPC */


void
INTL_FreeFontEncodingList(INTL_FontEncodingList *list)
{
	INTL_FontEncodingList	*next;

	while (list)
	{
		next = list->next;
		if (list->text)
		{
			XP_FREE(list->text);
		}
		XP_FREE(list);
		list = next;
	}
}


INTL_FontEncodingList *
INTL_InternalToFontEncoding(int16 charset, unsigned char *text)
{
	INTL_FontEncodingList	*current;
	unsigned char		*in;
	uint16			inlen;
	uint16			inread;
	unsigned char		*out;
	uint16			outbuflen;
	int16			outcsid;
	uint16			outlen;
	INTL_FontEncodingList	**prev;
	INTL_FontEncodingList	*ret;

	if (!text)
	{
		return NULL;
	}

	in = text;
	while (*in++)
	{
		;
	}
	inlen = in - text;

	ret = NULL;
	prev = &ret;

	in = text;
	while (*in)
	{
		current = XP_NEW_ZAP(INTL_FontEncodingList);
		if (!current)
		{
			INTL_FreeFontEncodingList(ret);
			return NULL;
		}

		/*
		 * @@@ allocating too much? -- erik
		 */
		outbuflen = inlen + 1;
		out = XP_ALLOC(outbuflen);
		if (!out)
		{
			XP_FREE(current);
			INTL_FreeFontEncodingList(ret);
			return NULL;
		}

		if (INTL_ConvertNPC(in, inlen, &inread, out, outbuflen,
			&outlen, &outcsid))
		{
			in += inread;
			inlen -= inread;

			out[outlen] = 0;

			current->next = NULL;
			current->charset = outcsid;
			current->text = out;

			*prev = current;
			prev = &current->next;
		}
		else
		{
			break;
		}
	}

	return ret;
}

#endif /* USE_NPC */


void
INTL_ReportFontCharSets(int16 *charsets)
{
	uint16	len;

	if (!charsets)
	{
		return;
	}

	if (availableFontCharSets)
	{
		free(availableFontCharSets);
	}

	availableFontCharSets = charsets;

	while (*charsets)
	{
		if (*charsets == CS_X_BIG5)
		{
			haveBig5 = 1;
		}
		charsets++;
	}
	len = (charsets - availableFontCharSets);

#ifdef XP_UNIX
	INTL_SetUnicodeCSIDList(len, availableFontCharSets);

#ifdef UNICODE_INIT_TEST
	{
		extern void npctest(void);

		npctest();
	}
#endif /* UNICODE_INIT_TEST */

#endif

}
/*	
	INTL_NextCharIdxInText 
		Input: 	csid - window csid	
				text - point to a text buffer
				pos  - origional index position
		output: index of the position of next character
		Called by lo_next_character in layfind.c
*/
int INTL_NextCharIdxInText(int16 csid, unsigned char *text, int pos)
{
	return pos + INTL_CharLen(csid ,text+pos);
}
/*	
	INTL_PrevCharIdxInText 
		Input: 	csid - window csid	
				text - point to a text buffer
				pos  - origional index position
		output: index of the position of previous character
		Called by lo_next_character in layfind.c
*/
int INTL_PrevCharIdxInText(int16 csid, unsigned char *text, int pos)
{
	int rev, ff , thislen;
	if((INTL_CharSetType(csid) == SINGLEBYTE) ) {
		return pos - 1;
	}
	else 
	{
		/*	First, backward to character in ASCII range */
		for(rev=pos - 1; rev > 0 ; rev--)
		{
			if(((text[rev] & 0x80 ) == 0) &&
			   ((rev + INTL_CharLen(csid ,text+rev)) < pos))
				break;
		}
			
		/*	Then forward till we cross the position. */
		for(ff = rev ; ff < pos ; ff += thislen)
		{
			thislen = INTL_CharLen(csid ,text+ff);
			if((ff + thislen) >= pos)
				break;
		}
		return ff;
	}
}

/*	
	INTL_NextCharIdx
		Input: 	csid - window csid	
				text - point to a text buffer
				pos  - 0 based position
		output: 0 based next char position
		Note: this one works for any position no matter it's legal or not
*/

int INTL_NextCharIdx(int16 csid, unsigned char *str, int pos)
{
	int n;
	unsigned char *p;

	if((INTL_CharSetType(csid) == SINGLEBYTE) || (pos < 0))
		return pos + 1;

	n = INTL_NthByteOfChar(csid, (char *) str, pos+1);
	if (n == 0)
		return pos + 1;

	p = str + pos - n + 1;
	return pos + INTL_CharLen(csid, p) - n + 1;
}
/*	
	INTL_PrevCharIdx
		Input: 	csid - window csid	
				text - point to a text buffer
				pos  - 0 based position
		output: 0 based prev char position
		Note: this one works for any position no matter it's legal or not
*/
int INTL_PrevCharIdx(int16 csid, unsigned char *str, int pos)
{
	int n;
	if((INTL_CharSetType(csid) == SINGLEBYTE) || (pos <= 0))
		return pos - 1;
#ifdef DEBUG
	n = INTL_NthByteOfChar(csid, (char *) str, pos+1);
	if (n > 1)
	{
		XP_TRACE(("Wrong position passed to INTL_PrevCharIdx"));
		pos -= (n - 1); 
	}
#endif

	pos --;
	if ((n = INTL_NthByteOfChar(csid, (char *) str, pos+1)) > 1)
		return pos - n + 1;
	else
		return pos;
}

#define INTL_SingleByteToLower(lower, ch)	((ch & 0x80) ? (lower[(ch & 0x7f)]) : (lower_lookup_ascii[ch]))
/*
static unsigned char lower_lookup_no_change[256]={
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
*/
/*	
	lower_lookup_ascii  map 
		0x41-0x5a to 0x61-0x7a
*/
static unsigned char lower_lookup_ascii[128]={
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
};
#ifndef XP_MAC
/*	
	lower_lookup_latin1 map 
	(2) 0xc0-0xd6 to 0xe0-0xf6
	(3) 0xd8-0xde to 0xf8-0xfe
*/
static unsigned char lower_lookup_latin1[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
/*	
	lower_lookup_latin2  map 
	(2) 0xa1 to 0xb1
	(3) 0xa3 to 0xb3
	(4) 0xa5-0xa6 to 0xb5-0xb6
	(5) 0xa9-0xac to 0xb9-0xbc
	(6) 0xae-0xaf to 0xbe-0xbf
	(7) 0xc0-0xd6 to 0xe0-0xf6
	(8) 0xd8-0xde to 0xf8-0xfe
*/
static unsigned char lower_lookup_latin2[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xb1, 0xa2, 0xb3, 0xa4, 0xb5, 0xb6, 0xa7, 0xa8, 0xb9, 0xba, 0xbb, 0xbc, 0xad, 0xbe, 0xbf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
/*	
	lower_lookup_macicelandic map 
		0x80 to 0x8a
		0x81-0x83 to 0x8c-0x8e
		0x84 to 0x96
		0x85 to 0x9a
		0x86 to 0x9f
		0xa0 to 0xe0
		0xae-0xaf to 0xbe-0xbf
		0xcb to 0x88
		0xcc to 0x8b
		0xcd to 0x9b
		0xce to 0xcf
		0xd9 to 0xd8
		0xdc to 0xdd
		0xde to 0xdf
		0xe5 to 0x89
		0xe6 to 0x90
		0xe7 to 0x87
		0xe8 to 0x91
		0xe9 to 0x8f
		0xea to 0x92
		0xeb to 0x94
		0xec to 0x95
		0xed to 0x93
		0xee to 0x97
		0xef to 0x99
		0xf1 to 0x98
		0xf2 to 0x9c
		0xf3 to 0x9e
		0xf4 to 0x9d
*/
#else /* ifndef XP_MAC */
static unsigned char lower_lookup_macicelandic[128]={
	0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xe0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xbe, 0xbf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0x88, 0x8b, 0x9b, 0xcf, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xda, 0xdb, 0xdd, 0xdd, 0xdf, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x89, 0x90, 0x87, 0x91, 0x8f, 0x92, 0x94, 0x95, 0x93, 0x97, 0x99,
	0xf0, 0x98, 0x9c, 0x9e, 0x9d, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
/*	
	lower_lookup_macce  map 
			0x80 to 0x8a
			0x81 to 0x82
			0x83 to 0x8e
			0x84 to 0x88
			0x85 to 0x9a
			0x86 to 0x9f
			0x89 to 0x8b
			0x8c to 0x8d
			0x8f to 0x90
			0x91 to 0x93
			0x94 to 0x95
			0x96 to 0x98
			0x9d to 0x9e
			0xa2 to 0xab
			0xaf to 0xb0
			0xb1 to 0xb4
			0xb5 to 0xfa
			0xb9 to 0xba
			0xbb to 0xbc
			0xbd to 0xbe
			0xbf to 0xc0
			0xc1 to 0xc4
			0xc5 to 0xcb
			0xcc to 0xce
			0xcd to 0x9b
			0xcf to 0xd8
			0xd9 to 0xda
			0xdb to 0xde
			0xdf to 0xe0
			0xe1 to 0xe4
			0xe5 to 0xe6
			0xe7 to 0x87
			0xe8 to 0xe9
			0xea to 0x92
			0xeb to 0xec
			0xed to 0xf0
			0xee to 0x97
			0xef to 0x99
			0xf1 to 0xf3
			0xf2 to 0x9c
			0xf4 to 0xf5
			0xf6 to 0xf7
			0xf8 to 0xf9
			0xfb to 0xfd
			0xfc to 0xb8
			0xfe to 0xae
*/
static unsigned char lower_lookup_macce[128]={
	0x8a, 0x82, 0x82, 0x8e, 0x88, 0x9a, 0x9f, 0x87, 0x88, 0x8b, 0x8a, 0x8b, 0x8d, 0x8d, 0x8e, 0x90,
	0x90, 0x93, 0x92, 0x93, 0x95, 0x95, 0x98, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xab, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xae, 0xae, 0xb0,
	0xb0, 0xb4, 0xb2, 0xb3, 0xb4, 0xfa, 0xb6, 0xb7, 0xb8, 0xba, 0xba, 0xbc, 0xbc, 0xbe, 0xbe, 0xc0,
	0xc0, 0xc4, 0xc2, 0xc3, 0xc4, 0xcb, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xce, 0x9b, 0xce, 0xd8,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xda, 0xda, 0xde, 0xdc, 0xdd, 0xde, 0xe0,
	0xe0, 0xe4, 0xe2, 0xe3, 0xe4, 0xe6, 0xe6, 0x87, 0xe9, 0xe9, 0x92, 0xec, 0xec, 0xf0, 0x97, 0x99,
	0xf0, 0xf3, 0x9c, 0xf3, 0xf5, 0xf5, 0xf7, 0xf7, 0xf9, 0xf9, 0xfa, 0xfd, 0xb8, 0xfd, 0xae, 0xff
};
#endif /* ifndef XP_MAC */

#ifndef XP_UNIX
/*	
	lower_lookup_jis0201  map 
		0xa7-0xab to 0xb1-0xb5
		0xac-0xae to 0xd4-0xd6
		0xaf to 0xc2
*/
static unsigned char lower_lookup_jis0201[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xd4, 0xd5, 0xd6, 0xc2,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif

#ifdef XP_MAC
/*
	lower_lookup_mac_cyrillic
		0x80-0x9e to 0xe0-0xfe		A - YU
		0x9F	  to 0xDF			YA
		0xA7	  to 0xb4			BYELORUSSIAN-UKRAINIAN I
		0xAb	  to 0xAC			DJE
		0xae	  to 0xaf			gje
		0xb7	  to 0xc0			je
		0xb8	  to 0xb9			ie
		0xba	  to 0xbb			yi
		0xbc	  to 0xbc			lje
		0xbd	  to 0xbd			nje
		0xc1	  to 0xcf			dze
		0xcb	  to 0xcc			tshe
		0xcd	  to 0xce			kje
		0xd8	  to 0xd9			short u
		0xda	  to 0xdb			dzhe
		0xdd	  to 0xde			dzhe
*/
static unsigned char lower_lookup_mac_cyrillic[128]={
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xb4, 0xa8, 0xa9, 0xaa, 0xac, 0xac, 0xad, 0xaf, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xc0, 0xb9, 0xb9, 0xbb, 0xbb, 0xbd, 0xbd, 0xbf, 0xbf,
	0xc0, 0xcf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcc, 0xcc, 0xce, 0xce, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd9, 0xd9, 0xdb, 0xdb, 0xdc, 0xde, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
#ifdef XP_UNIX
/*	
	lower_lookup_8859_5  map 
		0xa1-0xac to 0xf1-0xfc
		0xae-0xaf to 0xfe-0xff
		0xb0-0xcf to 0xd0-0xef
*/
static unsigned char lower_lookup_8859_5[128]={
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xad, 0xfe, 0xff,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
#ifdef XP_WIN
/*	
	lower_lookup_cp1251  map 
		0x80		 0x90
		0x81		 0x83
		0x8a		 0x9a
		0x8c-0x8f	 0x9c-0x9f
		0xa1		 0xa2
		0xa3		 0xbc
		0xa5		 0xb4
		0xa8		 0xb8
		0xaa		 0xba
		0xaf		 0xbf
		0xb2		 0xb3
		0xbd		 0xbe
*/
static unsigned char lower_lookup_cp1251[128]={
	0x90, 0x83, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa2, 0xa2, 0xbc, 0xa4, 0xb4, 0xa6, 0xa7, 0xb8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf,
	0xb0, 0xb1, 0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbe, 0xbe, 0xbf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
#ifdef XP_MAC
/*	
	lower_lookup_mac_greek  map 
		0x80		to	0x8a
		0x8e		to 	0x8e
		0x85		to 	0x9a
		0x86		to 	0x9f
		0xa1		to 	0xe7
		0xa2		to 	0xe4
		0xa3		to 	0xf5
		0xa4		to 	0xec
		0xa5		to 	0xea
		0xa6		to 	0xf0
		0xaa		to 	0xf3
		0xab		to 	0xfb
		0xb0		to 	0xe1		
		0xb5		to 	0xe2
		0xb6		to 	0xe5
		0xb7		to 	0xfa
		0xb8		to 	0xe8
		0xb9		to 	0xe9
		0xba		to 	0xeb
		0xbb		to 	0xed
		0xbc		to 	0xe6
		0xbd		to 	0xfc
		0xbe		to 	0xe3
		0xbf		to 	0xf6		
		0xc1		to	0xee
		0xc3		to	0xef
		0xc4		to	0xf2
		0xc6		to	0xf4		
		0xcb		to	0xf9
		0xcc		to	0xf8
		0xcd		to	0xc0
		0xce		to	0xdb

		0xd7-0xd9	to	0xdc-0xde
		0xda		to	0xe0
		0xdf		to	0xf1
		
		
*/
static unsigned char lower_lookup_mac_greek[128]={
	0x8a, 0x81, 0x82, 0x8e, 0x84, 0x9a, 0x9f, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xe7, 0xe4, 0xf5, 0xec, 0xea, 0xf0, 0xa7, 0xa8, 0xa9, 0xf3, 0xfb, 0xac, 0xad, 0xae, 0xaf,
	0xe1, 0xb1, 0xb2, 0xb3, 0xb4, 0xe2, 0xe5, 0xfa, 0xe8, 0xe9, 0xeb, 0xed, 0xe6, 0xfc, 0xe3, 0xf6,
	0xc0, 0xee, 0xc2, 0xef, 0xf2, 0xc5, 0xf4, 0xc7, 0xc8, 0xc9, 0xca, 0xf9, 0xf8, 0xc0, 0xdb, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xdc, 0xdd, 0xde, 0xe0, 0xdb, 0xdc, 0xdd, 0xde, 0xf1,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
#ifdef XP_UNIX
/*	
	lower_lookup_8859_7  map 
		0xb6	  to 0xdc
		0xb8-0xba to 0xdd-0xdf
		0xbc	  to 0xfc
		0xbe-0xbf to 0xfd-0xfe
		0xc1-0xdb to 0xe1-0xfb
*/
static unsigned char lower_lookup_8859_7[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xdc, 0xb7, 0xdd, 0xde, 0xdf, 0xbb, 0xfc, 0xbd, 0xfd, 0xfe,
	0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
#ifdef XP_WIN
/*	
	The only differences between these two lower_lookup_8859_7
	( The differences in these two table. I am not saying the difference between these two codeset)
		is 0xb6 and 0xa2
	lower_lookup_8859_7  map 
		0xa2	  to 0xdc
		0xb8-0xba to 0xdd-0xdf
		0xbc	  to 0xfc
		0xbe-0xbf to 0xfd-0xfe
		0xc1-0xdb to 0xe1-0xfb
*/
static unsigned char lower_lookup_8859_7[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xdc, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xdd, 0xde, 0xdf, 0xbb, 0xfc, 0xbd, 0xfd, 0xfe,
	0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xdc, 0xdd, 0xde, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif

#ifdef XP_WIN
/*
	lower_lookup_cp1250  map 
	
*/
static unsigned char lower_lookup_cp1250[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xb3, 0xa4, 0xb9, 0xa6, 0xa7, 0xa8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbe, 0xbd, 0xbe, 0xbf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
#ifndef XP_MAC
/*
	lower_lookup_8859_9  map 
	
	PROBLEM!!!!! Need more information !!!!
	Currently I map 0xdd to 0xfd for tolower
	0xDD is LATIN CAPITAL LETTER I WITH DOT ABOVE
	0xFD is LATIN SMALL LETTER DOTLESS I
	
	Should I do that ?
	
*/
static unsigned char lower_lookup_8859_9[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x9a, 0x8b, 0x9c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0xff,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#else
/*
	lower_lookup_mac_turkish  map 
	PROBLEM!!!!! Need more information !!!!
	Currently I map 0xdc to 0xdd for tolower
	0xDC is LATIN CAPITAL LETTER I WITH DOT ABOVE
	0xDD is LATIN SMALL LETTER DOTLESS I
	
	Should I do that ?
*/
static unsigned char lower_lookup_mac_turkish[128]={
	0x8a, 0x8c, 0x8d, 0x8e, 0x96, 0x9a, 0x9f, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xbe, 0xbf,
	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0x88, 0xcb, 0x9b, 0xcf, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xdb, 0xdb, 0xdd, 0xdd, 0xdf, 0xdf,
	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x89, 0x90, 0x87, 0x91, 0x8f, 0x92, 0x94, 0x95, 0x93, 0x97, 0x99,
	0xf0, 0x98, 0x9c, 0x9e, 0x9d, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
#endif
/*
	lower_lookup_koi8_r  map 
*/
static unsigned char lower_lookup_koi8_r[128]={
	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
	0xb0, 0xb1, 0xb1, 0xa3, 0xa4, 0xb5, 0xa6, 0xa7, 0xb8, 0xb9, 0xba, 0xbb, 0xbd, 0xbd, 0xbe, 0xbf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf
};

unsigned char *INTL_GetSingleByteToLowerMap(int16 csid)
{
	switch(csid)
	{
#ifdef XP_MAC
		case CS_MAC_ROMAN:
			return lower_lookup_macicelandic;
		case CS_MAC_CE:
			return lower_lookup_macce;
		case CS_MAC_CYRILLIC:
			return lower_lookup_mac_cyrillic;
		case CS_MAC_GREEK:
			return lower_lookup_mac_greek;
		case CS_MAC_TURKISH:	
			return lower_lookup_mac_turkish;
		case CS_SJIS:
			return lower_lookup_jis0201;
#endif
#ifdef XP_WIN
		case CS_LATIN1:
			return lower_lookup_latin1;
		case CS_CP_1250:	
			return lower_lookup_cp1250;
		case CS_CP_1251:
			return lower_lookup_cp1251;
		case CS_8859_7:
			return lower_lookup_8859_7;
		case CS_8859_9:	
			return lower_lookup_8859_9;
		case CS_SJIS:
			return lower_lookup_jis0201;
#endif
#ifdef XP_UNIX
		case CS_LATIN1:
			return lower_lookup_latin1;
		case CS_LATIN2:
			return lower_lookup_latin2;
		case CS_8859_5:
			return lower_lookup_8859_5;
		case CS_8859_7:
			return lower_lookup_8859_7;
		case CS_8859_9:	
			return lower_lookup_8859_9;
#endif	
		case CS_KOI8_R:
			return lower_lookup_koi8_r;
		/* currently, return the ascii table. We should supply table for this csid later */
		
		case CS_8859_3:	
		case CS_8859_4:		
		case CS_8859_6:
		case CS_8859_8:
		case CS_SYMBOL:
		case CS_DINGBATS:
		case CS_TIS620:
		case CS_JISX0201:
		
		/* use the ascii table */
		case CS_DEFAULT:
		case CS_ASCII:
		case CS_BIG5:		
		case CS_CNS_8BIT:		
		case CS_GB_8BIT:	
		case CS_KSC_8BIT:	
		default:
			return lower_lookup_ascii;
	}
}
	/*	ShiftJIS	*/	
typedef struct {
	unsigned char src_b1;
	unsigned char src_b2_start;
	unsigned char src_b2_end;
	unsigned char dest_b1;
	unsigned char dest_b2_start;
} DoubleByteToLowerMap;

static DoubleByteToLowerMap lower_lookup_none[]=
{	
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }	/* Terminator */
};

#ifndef XP_UNIX
static DoubleByteToLowerMap lower_lookup_sjis[]=
{	
	/*	Full-width Latin */
	{ 0x82, 0x60, 0x7a, 0x82, 0x81 },	
	
	/*	Map Full-width Hiragana to  Full-width Katakana */
	{ 0x82, 0x9f, 0x9f, 0x83, 0x41 },	/*	A	*/
	{ 0x82, 0xa0, 0xa0, 0x83, 0x41 },

	{ 0x82, 0xa1, 0xa1, 0x83, 0x43 },	/*	I	*/
	{ 0x82, 0xa2, 0xa2, 0x83, 0x43 },

	{ 0x82, 0xa3, 0xa3, 0x83, 0x45 },	/*	U	*/
	{ 0x82, 0xa4, 0xa4, 0x83, 0x45 },

	{ 0x82, 0xa5, 0xa5, 0x83, 0x47 },	/*	E	*/
	{ 0x82, 0xa6, 0xa6, 0x83, 0x47 },

	{ 0x82, 0xa7, 0xa7, 0x83, 0x49 },	/*	O	*/
	{ 0x82, 0xa8, 0xa8, 0x83, 0x49 },
	
	{ 0x82, 0xa9, 0xc0, 0x83, 0x4a },	/* KA - DI */

	{ 0x82, 0xc1, 0xc1, 0x83, 0x63 },	/* TU */
	{ 0x82, 0xc2, 0xc2, 0x83, 0x63 },

	{ 0x82, 0xc3, 0xdd, 0x83, 0x64 },	/* DU - MI */
	{ 0x82, 0xde, 0xe0, 0x83, 0x80 },	/* MU - MO */

	{ 0x82, 0xe1, 0xe1, 0x83, 0x84 },	/* YA	*/
	{ 0x82, 0xe2, 0xe2, 0x83, 0x84 },

	{ 0x82, 0xe3, 0xe3, 0x83, 0x86 },	/* YU	*/
	{ 0x82, 0xe4, 0xe4, 0x83, 0x86 },

	{ 0x82, 0xe5, 0xe5, 0x83, 0x88 },	/* YO	*/
	{ 0x82, 0xe6, 0xe6, 0x83, 0x88 },

	{ 0x82, 0xe7, 0xeb, 0x83, 0x89 },	/* RA - RO */

	{ 0x82, 0xec, 0xec, 0x83, 0x8f },	/* WA	*/
	{ 0x82, 0xed, 0xed, 0x83, 0x8f },

	{ 0x82, 0xee, 0xf1, 0x83, 0x90 },	/* WI - N */

	/*	Map SMALL Full-width Katakana to Full-width Katakana */
	{ 0x83, 0x40, 0x40, 0x83, 0x41 },	/*	A	*/
	{ 0x83, 0x42, 0x42, 0x83, 0x43 },	/*	I	*/
	{ 0x83, 0x43, 0x44, 0x83, 0x45 },	/*	U	*/
	{ 0x83, 0x46, 0x46, 0x83, 0x47 },	/*	E	*/
	{ 0x83, 0x48, 0x47, 0x83, 0x49 },	/*	O	*/
	{ 0x83, 0x62, 0x62, 0x83, 0x63 },	/* TU	*/
	{ 0x83, 0x83, 0x83, 0x83, 0x84 },	/* YA	*/
	{ 0x83, 0x85, 0x85, 0x83, 0x86 },	/* YU	*/
	{ 0x83, 0x87, 0x87, 0x83, 0x88 },	/* YO	*/
	{ 0x83, 0x8e, 0x8e, 0x83, 0x8f },	/* WA	*/

	/*	Full-width Greek */
	{ 0x83, 0x9f, 0xb6, 0x83, 0xbf },	
	
	/*	Full-width Cyrillic*/
	{ 0x84, 0x40, 0x4e, 0x84, 0x70 },	/* Part 1 */
	{ 0x84, 0x4f, 0x61, 0x84, 0x80 },	/* Part 2 */
	
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }	/* Terminator */
};
#endif
/* Don't #ifdef XP_UNIX for lower_lookup_eucjp. It is also used by GB2312 */
static DoubleByteToLowerMap lower_lookup_eucjp[]=
{	
	/*	Half-width Katakana */
	{ SS2,  0xa6, 0xa6, 0xa5, 0xf2 },	/*	WO */
	
	{ SS2,  0xa7, 0xa7, 0xa5, 0xa2 },	/*	A */
	{ SS2,  0xa8, 0xa8, 0xa5, 0xa4 },	/*	I */
	{ SS2,  0xa9, 0xa9, 0xa5, 0xa6 },	/*	U */
	{ SS2,  0xaa, 0xaa, 0xa5, 0xa8 },	/*	E */
	{ SS2,  0xab, 0xab, 0xa5, 0xaa },	/*	O */
	
	{ SS2,  0xac, 0xac, 0xa5, 0xe4 },	/*	YA */
	{ SS2,  0xad, 0xad, 0xa5, 0xe6 },	/*	YU */
	{ SS2,  0xae, 0xae, 0xa5, 0xe8 },	/*	YO */
	{ SS2,  0xaf, 0xaf, 0xa5, 0xc4 },	/*	TU */
	
	{ SS2,  0xb1, 0xb1, 0xa5, 0xa2 },	/*	A */
	{ SS2,  0xb2, 0xb2, 0xa5, 0xa4 },	/*	I */
	{ SS2,  0xb3, 0xb3, 0xa5, 0xa6 },	/*	U */
	{ SS2,  0xb4, 0xb4, 0xa5, 0xa8 },	/*	E */
	{ SS2,  0xb5, 0xb5, 0xa5, 0xaa },	/*	O */
	
	{ SS2,  0xb6, 0xb6, 0xa5, 0xab },	/*	KA */
	{ SS2,  0xb7, 0xb7, 0xa5, 0xad },	/*	KI */
	{ SS2,  0xb8, 0xb8, 0xa5, 0xaf },	/*	KU */
	{ SS2,  0xb9, 0xb9, 0xa5, 0xb1 },	/*	KE */
	{ SS2,  0xba, 0xba, 0xa5, 0xb3 },	/*	KO */
	
	{ SS2,  0xbb, 0xbb, 0xa5, 0xb5 },	/*	SA */
	{ SS2,  0xbc, 0xbc, 0xa5, 0xb7 },	/*	SI */
	{ SS2,  0xbd, 0xbd, 0xa5, 0xb9 },	/*	SU */
	{ SS2,  0xbe, 0xbe, 0xa5, 0xbb },	/*	SE */
	{ SS2,  0xbf, 0xbf, 0xa5, 0xbd },	/*	SO */
	
	{ SS2,  0xc0, 0xc0, 0xa5, 0xbf },	/*	TA */
	{ SS2,  0xc1, 0xc1, 0xa5, 0xc1 },	/*	TI */
	{ SS2,  0xc2, 0xc2, 0xa5, 0xc4 },	/*	TU */
	{ SS2,  0xc3, 0xc3, 0xa5, 0xc6 },	/*	TE */
	{ SS2,  0xc4, 0xc4, 0xa5, 0xc8 },	/*	TO */
	
	{ SS2,  0xc5, 0xc9, 0xa5, 0xca },	/*	NA - NO */
	
	{ SS2,  0xca, 0xca, 0xa5, 0xcf },	/*	HA */
	{ SS2,  0xcb, 0xcb, 0xa5, 0xd2 },	/*	HI */
	{ SS2,  0xcc, 0xcc, 0xa5, 0xd5 },	/*	HU */
	{ SS2,  0xcd, 0xcd, 0xa5, 0xd8 },	/*	HE */
	{ SS2,  0xce, 0xce, 0xa5, 0xdb },	/*	HO */
	
	{ SS2,  0xcf, 0xd3, 0xa5, 0xde },	/*	MA - MO */
	
	{ SS2,  0xd4, 0xd4, 0xa5, 0xe4 },	/*	YA */
	{ SS2,  0xd5, 0xd5, 0xa5, 0xe6 },	/*	YU */
	{ SS2,  0xd6, 0xd6, 0xa5, 0xe8 },	/*	YO */

	{ SS2,  0xd7, 0xdb, 0xa5, 0xe9 },	/*	RA - RO */

	{ SS2,  0xdc, 0xdc, 0xa5, 0xef },	/*	WA */

	{ SS2,  0xdd, 0xdd, 0xa5, 0xf3 },	/*	N */
	
	/*	Full-width Latin */
	{ 0xa3, 0xc1, 0xda, 0xa3, 0xe1 },	
	
	/*	Map Full-width Hiragana to  Full-width Katakana */
	{ 0xa4, 0xa1, 0xa1, 0xa5, 0xa2 },	/*	A	*/
	{ 0xa4, 0xa2, 0xa2, 0xa5, 0xa2 },

	{ 0xa4, 0xa3, 0xa3, 0xa5, 0xa4 },	/*	I	*/
	{ 0xa4, 0xa4, 0xa4, 0xa5, 0xa4 },

	{ 0xa4, 0xa5, 0xa5, 0xa5, 0xa6 },	/*	U	*/
	{ 0xa4, 0xa6, 0xa6, 0xa5, 0xa6 },

	{ 0xa4, 0xa7, 0xa7, 0xa5, 0xa8 },	/*	E	*/
	{ 0xa4, 0xa8, 0xa8, 0xa5, 0xa8 },

	{ 0xa4, 0xa9, 0xa9, 0xa5, 0xaa },	/*	O	*/
	{ 0xa4, 0xaa, 0xaa, 0xa5, 0xaa },	
	
	{ 0xa4, 0xab, 0xc2, 0xa5, 0xab},	/* KA - DI */

	{ 0xa4, 0xc3, 0xc3, 0xa5, 0xc4 },	/* TU */
	{ 0xa4, 0xc4, 0xc4, 0xa5, 0xc4 },

	{ 0xa4, 0xc5, 0xe2, 0xa5, 0xc5 },	/* DU - MO */

	{ 0xa4, 0xe3, 0xe3, 0xa5, 0xe4 },	/* YA	*/
	{ 0xa4, 0xe4, 0xe4, 0xa5, 0xe4 },

	{ 0xa4, 0xe5, 0xe5, 0xa5, 0xe6 },	/* YU	*/
	{ 0xa4, 0xe6, 0xe6, 0xa5, 0xe6 },

	{ 0xa4, 0xe7, 0xe7, 0xa5, 0xe8 },	/* YO	*/
	{ 0xa4, 0xe8, 0xe8, 0xa5, 0xe8 },

	{ 0xa4, 0xe9, 0xed, 0xa5, 0xe9},	/* RA - RO */

	{ 0xa4, 0xee, 0xee, 0xa5, 0xef },	/* WA	*/
	{ 0xa4, 0xef, 0xef, 0xa5, 0xef },

	{ 0xa4, 0xf0, 0xf3, 0xa5, 0xf0 },	/* WI - N */
	
	/*	Map SMALL Full-width Katakana to Full-width Katakana */
	{ 0xa5, 0xa1, 0xa1, 0xa5, 0xa2 },	/*	A	*/
	{ 0xa5, 0xa3, 0xa3, 0xa5, 0xa4 },	/*	I	*/
	{ 0xa5, 0xa5, 0xa5, 0xa5, 0xa6 },	/*	U	*/
	{ 0xa5, 0xa7, 0xa7, 0xa5, 0xa8 },	/*	E	*/
	{ 0xa5, 0xa9, 0xa9, 0xa5, 0xaa },	/*	O	*/
	{ 0xa5, 0xc3, 0xc3, 0xa5, 0xc4 },	/* TU	*/
	{ 0xa5, 0xe3, 0xe3, 0xa5, 0xe4 },	/* YA	*/
	{ 0xa5, 0xe5, 0xe5, 0xa5, 0xe6 },	/* YU	*/
	{ 0xa5, 0xe7, 0xe7, 0xa5, 0xe8 },	/* YO	*/
	{ 0xa5, 0xee, 0xee, 0xa5, 0xef },	/* WA	*/
	
	/*	Full-width Greek */
	{ 0xa6, 0xa1, 0xb8, 0xa6, 0xc1 },	
	/*	Full-width Cyrillic*/
	{ 0xa7, 0xa1, 0xc1, 0xa7, 0xd1 },	

	{ 0x00, 0x00, 0x00, 0x00, 0x00 }	/* Terminator */
};	
static DoubleByteToLowerMap lower_lookup_big5[]=
{	
	/*	Full-width Latin */
	{ 0xa2, 0xcf, 0xe4, 0xa2, 0xe9 },	/* Part 1 A-V */
	{ 0xa2, 0xe5, 0xe8, 0xa3, 0x40 },	/* Part 2 W-Z */
	
	/*	Full-width Greek */
	{ 0xa3, 0x44, 0x5b, 0xa3, 0x5c },

	{ 0x00, 0x00, 0x00, 0x00, 0x00 }	/* Terminator */
};	
static DoubleByteToLowerMap lower_lookup_cns11643_1[]=
{	
	/*	Roman Number  */
	{ 0xa4, 0xab, 0xb4, 0xa6, 0xb5 },	
	
	/*	Full-width Latin */
	{ 0xa4, 0xc1, 0xda, 0xa4, 0xdb },	
	
	/*	Full-width Greek */
	{ 0xa4, 0xf5, 0xfe, 0xa5, 0xaf },	/* Part 1 Alpha - kappa */
	{ 0xa5, 0xa1, 0xae, 0xa5, 0xb9 },	/* Part 2 Lamda - Omega */

	{ 0x00, 0x00, 0x00, 0x00, 0x00 }	/* Terminator */
};	
static DoubleByteToLowerMap lower_lookup_ksc5601[]=
{	
	/*	Full-width Latin */
	{ 0xa3, 0xc1, 0xda, 0xa3, 0xe1 },	

	/*	Full-width Roman Number */
	{ 0xa5, 0xb0, 0xb9, 0xa5, 0xa1 },	

	/*	Full-width Greek */
	{ 0xa5, 0xc1, 0xd8, 0xa5, 0xe1 },	

	/*	Map Full-width Hiragana to  Full-width Katakana */
	{ 0xaa, 0xa1, 0xa1, 0xab, 0xa2 },	/*	A	*/
	{ 0xaa, 0xa2, 0xa2, 0xab, 0xa2 },

	{ 0xaa, 0xa3, 0xa3, 0xab, 0xa4 },	/*	I	*/
	{ 0xaa, 0xa4, 0xa4, 0xab, 0xa4 },

	{ 0xaa, 0xa5, 0xa5, 0xab, 0xa6 },	/*	U	*/
	{ 0xaa, 0xa6, 0xa6, 0xab, 0xa6 },

	{ 0xaa, 0xa7, 0xa7, 0xab, 0xa8 },	/*	E	*/
	{ 0xaa, 0xa8, 0xa8, 0xab, 0xa8 },

	{ 0xaa, 0xa9, 0xa9, 0xab, 0xaa },	/*	O	*/
	{ 0xaa, 0xaa, 0xaa, 0xab, 0xaa },	
	
	{ 0xaa, 0xab, 0xc2, 0xab, 0xab},	/* KA - DI */

	{ 0xaa, 0xc3, 0xc3, 0xab, 0xc4 },	/* TU */
	{ 0xaa, 0xc4, 0xc4, 0xab, 0xc4 },

	{ 0xaa, 0xc5, 0xe2, 0xab, 0xc5 },	/* DU - MO */

	{ 0xaa, 0xe3, 0xe3, 0xab, 0xe4 },	/* YA	*/
	{ 0xaa, 0xe4, 0xe4, 0xab, 0xe4 },

	{ 0xaa, 0xe5, 0xe5, 0xab, 0xe6 },	/* YU	*/
	{ 0xaa, 0xe6, 0xe6, 0xab, 0xe6 },

	{ 0xaa, 0xe7, 0xe7, 0xab, 0xe8 },	/* YO	*/
	{ 0xaa, 0xe8, 0xe8, 0xab, 0xe8 },

	{ 0xaa, 0xe9, 0xed, 0xab, 0xe9},	/* RA - RO */

	{ 0xaa, 0xee, 0xee, 0xab, 0xef },	/* WA	*/
	{ 0xaa, 0xef, 0xef, 0xab, 0xef },

	{ 0xaa, 0xf0, 0xf3, 0xab, 0xf0 },	/* WI - N */
	
	/*	Map SMALL Full-width Katakana to Full-width Katakana */
	{ 0xab, 0xa1, 0xa1, 0xab, 0xa2 },	/*	A	*/
	{ 0xab, 0xa3, 0xa3, 0xab, 0xa4 },	/*	I	*/
	{ 0xab, 0xa5, 0xa5, 0xab, 0xa6 },	/*	U	*/
	{ 0xab, 0xa7, 0xa7, 0xab, 0xa8 },	/*	E	*/
	{ 0xab, 0xa9, 0xa9, 0xab, 0xaa },	/*	O	*/
	{ 0xab, 0xc3, 0xc3, 0xab, 0xc4 },	/* TU	*/
	{ 0xab, 0xe3, 0xe3, 0xab, 0xe4 },	/* YA	*/
	{ 0xab, 0xe5, 0xe5, 0xab, 0xe6 },	/* YU	*/
	{ 0xab, 0xe7, 0xe7, 0xab, 0xe8 },	/* YO	*/
	{ 0xab, 0xee, 0xee, 0xab, 0xef },	/* WA	*/

	/*	Full-width Cyrillic*/
	{ 0xac, 0xa1, 0xc1, 0xac, 0xd1 },	
	
	{ 0x00, 0x00, 0x00, 0x00, 0x00 }	/* Terminator */
};

DoubleByteToLowerMap *INTL_GetDoubleByteToLowerMap(int16 csid)
{
	switch(csid)
	{
#ifndef XP_UNIX
		case CS_SJIS:
			return lower_lookup_sjis;
#else
		case CS_EUCJP:
			return lower_lookup_eucjp;
#endif
		case CS_BIG5:		
			return lower_lookup_big5;
		case CS_CNS_8BIT:		
			return lower_lookup_cns11643_1;
		case CS_GB_8BIT:	
			return lower_lookup_eucjp;	/*	The to_lower mapping for GB 2312 and JIS0208 are exactly the same */
										/*  We just use the same table here.								  */
		case CS_KSC_8BIT:	
			return lower_lookup_ksc5601;
		default:
			return lower_lookup_none;
	}
}
void INTL_DoubleByteToLower(DoubleByteToLowerMap *db_tolowermap, unsigned char* lowertext, unsigned char* text)
{
	DoubleByteToLowerMap *p;
	for(p = db_tolowermap; !((p->src_b1 == 0) && (p->src_b2_start == 0)); p++)
	{
		if( (p->src_b1       == text[0]) &&
			(p->src_b2_start <= text[1] ) &&
			(p->src_b2_end   >= text[1]) )
		{
			lowertext[0] = p->dest_b1;
			lowertext[1] = text[1] - p->src_b2_start + p->dest_b2_start;
			return;
		}
		else 
		{	/*	The map have to be sorted order to implement a fast search */
			if(p->src_b1 > text[0])
				break;
			else {
				if((p->src_b1 == text[0]) && (p->src_b2_start > text[1]))
					break;
			}
		}
	}
	lowertext[0] = text[0];
	lowertext[1] = text[1];
	return;
}

XP_Bool INTL_MatchOneChar(int16 csid, unsigned char *text1,unsigned char *text2,int *charlen)
{
	if((INTL_CharSetType(csid) == SINGLEBYTE) ) {
		unsigned char *sb_tolowermap;
		*charlen = 1;
		sb_tolowermap = INTL_GetSingleByteToLowerMap(csid);
		return( INTL_SingleByteToLower(sb_tolowermap,text1[0]) == INTL_SingleByteToLower(sb_tolowermap, text2[0]));
	}
	else
	{
		int l1, l2;
		l1 = INTL_CharLen(csid ,text1);
		l2 = INTL_CharLen(csid ,text2);
		if(l1 != l2)
			return FALSE;
		if(l1 == 1)
		{
			unsigned char *sb_tolowermap;
			*charlen = 1;
			sb_tolowermap = INTL_GetSingleByteToLowerMap(csid);
			return( INTL_SingleByteToLower(sb_tolowermap,text1[0]) == INTL_SingleByteToLower(sb_tolowermap, text2[0]));
		}
		else
		{
			if(l1 == 2)
			{
				DoubleByteToLowerMap *db_tolowermap;
				unsigned char lowertext1[2], lowertext2[2];
				*charlen = 2;
				db_tolowermap = INTL_GetDoubleByteToLowerMap(csid);
				INTL_DoubleByteToLower(db_tolowermap, lowertext1, text1);
				INTL_DoubleByteToLower(db_tolowermap, lowertext2, text2);
				return( ( lowertext1[0] ==  lowertext2[0] ) &&
						( lowertext1[1] ==  lowertext2[1] ) );
			}
			else
			{
				/* for character which is neither one byte nor two byte, we cannot ignore case for them */
				int i;
				*charlen = l1;
				for(i=0;i<l1;i++)
				{
					if(text1[i] != text2[i])
						return FALSE;
				}
				return TRUE;
			}
		}
	}
}
XP_Bool INTL_MatchOneCaseChar(int16 csid, unsigned char *text1,unsigned char *text2,int *charlen)
{
	if((INTL_CharSetType(csid) == SINGLEBYTE) ) {
		*charlen = 1;
		return( text1[0]== text2[0]);
	}
	else
	{
		int i,len;
		*charlen = len  = INTL_CharLen(csid, (unsigned char *) text1);
		for(i=0 ; i < len; i++)
		{
			if(text1[i] != text2[i]) 
				return FALSE;
		}
		return TRUE;
	}
}

PUBLIC
char *INTL_Strstr(int16 csid, const char *s1,const char *s2)
{
	int len;
	char *p1, *pp1, *p2;
	if((s2==NULL) || (*s2 == '\0'))
		return (char *)s1;
	if((s1==NULL) || (*s1 == '\0'))
		return NULL;
	
	for(p1=(char*)s1; *p1  ;p1 = INTL_NextChar(csid ,p1))
	{
		for(p2=(char*)s2, pp1=p1 ;  
			((*pp1) && (*p2) && INTL_MatchOneCaseChar(csid, (unsigned char*)pp1, (unsigned char*)p2, &len)); 
			pp1 += len, p2 += len)
				;	/* do nothing in the loop */
		if(*p2 == '\0')
			return p1;
	}
	return NULL;
}

PUBLIC
char *INTL_Strcasestr(int16 csid, const char *s1, const char *s2)
{
	int len;
	char *p1, *pp1, *p2;
	if((s2==NULL) || (*s2 == '\0'))
		return (char *)s1;
	if((s1==NULL) || (*s1 == '\0'))
		return NULL;

	for(p1=(char*)s1; *p1  ;p1 = INTL_NextChar(csid , p1))
	{
		for(p2=(char*)s2, pp1=p1 ;  
			((*pp1) && (*p2) && INTL_MatchOneChar(csid, (unsigned char*)pp1, (unsigned char*)p2, &len)); 
			pp1 += len, p2 += len)
				;	/* do nothing in the loop */
		if(*p2 == '\0')
			return p1;
	}
	return NULL;
}


PUBLIC
XP_Bool INTL_FindMimePartIIStr(int16 csid, XP_Bool searchcasesensitive, const char *mimepart2str,const char *s2)
{
	XP_Bool onlyAscii;
	char *ret = NULL;
	char *s1 = (char*)mimepart2str;
	char *conv;
	if((s2 == NULL) || (*s2 == '\0'))	/* if search for NULL string, return TRUE */
		return TRUE;
	if((s1 == NULL) || (*s1 == '\0'))	/* if string is NULL, return FALSE */
		return FALSE;
	
	conv= IntlDecodeMimePartIIStr(mimepart2str, csid, FALSE);
	if(conv)
		s1 = conv;
	onlyAscii = onlyAsciiStr(s1) && onlyAsciiStr(s2);
	if(onlyAscii)	/* for performance reason, let's call the ANSI C routine for ascii only case */
	{
		if(searchcasesensitive)
			ret= strstr( s1, s2);
		else
			ret= strcasestr(s1, s2);
	}
	else
	{
		if(searchcasesensitive)
			ret= INTL_Strstr(csid, s1, s2);
		else
			ret= INTL_Strcasestr(csid, s1, s2);
	}
	if(conv != mimepart2str)
		XP_FREE(conv);
	return (ret != NULL);		/* return TRUE if it find something */
}

PUBLIC
int32  INTL_TextByteCountToCharLen(int16 csid, unsigned char* text, uint32 byteCount)
{
	/* quickly return if it is zero */
	if(byteCount == 0 )
		return 0;
	if(INTL_CharSetType(csid) == SINGLEBYTE)
	{
		/* for single byte csid, byteCount equal to charLen */
		return byteCount;
	}
	else
	{
		csinfo_t	*info ;
		info = &csinfo_tbl[0] ;
		for (;info->csid; info++)			/* looking for an entry for this csid */
		{
			if (info->csid == csid)	/* find the entry for this csid */
			{
				uint32 curByte, curChar;
				int thislen;
				for(curByte=curChar=0; curByte < byteCount ;curChar++,curByte += thislen)
				{
					int i;
					unsigned char ch = text[curByte];
					/* preset thislen to 1 and looking for the entry for this char */
					for (i=0, thislen = 1; i<MAX_FIRSTBYTE_RANGE && info->enc[i].bytes > 0; i++)
					{
						if ((ch >= info->enc[i].range[0]) && (ch <= info->enc[i].range[1]))
							thislen = info->enc[i].bytes;
					}
				}
				return curChar;		
			}
		}
	}
	/* it should not come to here */
	XP_ASSERT(byteCount);
	return byteCount;		
}



PUBLIC
int32  INTL_TextCharLenToByteCount(int16 csid, unsigned char* text, uint32 charLen)
{
	/* quickly return if it is zero */
	if(charLen == 0 )
		return 0;
	if(INTL_CharSetType(csid) == SINGLEBYTE)
	{
		/* for single byte csid, byteCount equal to charLen */
		return charLen;
	}
	else
	{
		csinfo_t	*info ;
		info = &csinfo_tbl[0] ;
		for (;info->csid; info++)			/* looking for an entry for this csid */
		{
			if (info->csid == csid)	/* find the entry for this csid */
			{
				uint32 curByte, curChar;
				int thislen;
				for(curByte=curChar=0; curChar < charLen ;curChar++,curByte += thislen)
				{
					int i;
					unsigned char ch = text[curByte];
					/* preset thislen to 1 and looking for the entry for this char */
					for (i=0, thislen = 1; i<MAX_FIRSTBYTE_RANGE && info->enc[i].bytes > 0; i++)
					{
						if ((ch >= info->enc[i].range[0]) && (ch <= info->enc[i].range[1]))
							thislen = info->enc[i].bytes;
					}
				}
				return curByte;		
			}
		}
	}
	/* it should not come to here */
	XP_ASSERT(charLen);
	return charLen;
}

const char *INTL_NonBreakingSpace(MWContext *pContext)
{
    int csid = pContext->win_csid;

    switch (csid)
    {
    case CS_LATIN1:  
    case CS_LATIN2:
        return "\240";      /* 0xA0 */
    case CS_MAC_ROMAN:
    case CS_MAC_CE:
        return "\312";      /* 0xCA */
    case CS_SJIS:
        return "\201\100";  /* 0x8140 */
    case CS_BIG5:
        return "\241\100";   /* 0xA140 */
    case CS_KSC_8BIT:       /* korean */
        return "\241\241";   /* 0xA1A1 */
    case CS_EUCJP:
        return "\241\241";   /* 0xA1A1 */
    case CS_GB_8BIT:        /* chinese */
        return "\241\241";   /* 0xA1A1 */
    default:
        return "\240";
    }
}

/*
    INTL_CharClass is used for multibyte to divide character to different type
*/
int
INTL_CharClass(int charset, unsigned char *pstr)
{
	int	c1, c2;

	c1 = *pstr;

	switch (charset)
	{
	case CS_SJIS:
        if (c1 < 0x80)
            return  SEVEN_BIT_CHAR;
        if ((c1 >= 0xA0) && (c1 < 0xE0))
            return HALFWIDTH_PRONOUNCE_CHAR;

        c2 = *(pstr + 1);
        if (c1 == 0x82 && (c2 >= 0x60 && c2 <= 0x9A))
        {       /*   0x8260 -- 0x929A  */
            return FULLWIDTH_ASCII_CHAR;

        }
        if ((c1 == 0x82 && (c2 >= 0x9F && c2 <= 0xF1)) || 
            (c1 == 0x83 && (c2 >= 0x40 && c2 <= 0x96)) ||
            (c1 == 0x81 && (c2 == 0x5B || c2 == 0x5C || c2 == 0x5D)))
        {        /* 829F -- 82F1 
                    8340 -- 8396 */
            return FULLWIDTH_PRONOUNCE_CHAR;

        }
        if (c1 >= 0x88  &&  c1 <= 0xFC)
        {
            return KANJI_CHAR;

        }
        return UNCLASSIFIED_CHAR;
    case CS_KSC_8BIT:
        if (c1 < 0x80)
            return  SEVEN_BIT_CHAR;

        c2 = *(pstr + 1);
        if (c1 == 0xC1 && ((c2 >= 0xC1 && c2 <= 0xDA) ||
                           (c2 >= 0xE1 && c2 <= 0xFA)))
        {       /*   0xA3C1 -- 0xA3DA, 0xA3E1 -- A3FA  */
            return FULLWIDTH_ASCII_CHAR;

        }
        if ((c1 == 0xA4 && (c2 >= 0xA1 && c2 <= 0xFE)) || 
            (c1 >= 0xB0 && c1 < 0xCA))
        {        /* A4A1 -- A4FE, B0A0 -- C8FF */
            return FULLWIDTH_PRONOUNCE_CHAR;

        }
        if (c1 >= 0xCA  &&  c1 <= 0xFD)
        {       /* CAA0 -- FDFF */
            return KANJI_CHAR;

        }
        return UNCLASSIFIED_CHAR;
    case CS_GB_8BIT:
        if (c1 < 0x80)
            return  SEVEN_BIT_CHAR;

        c2 = *(pstr + 1);
        if (c1 == 0xA3 && ((c2 >= 0xC1 && c2 <= 0xDA) ||
                           (c2 >= 0xE1 && c2 <= 0xFA)))
        {       /*   0xA3C1 -- 0xA3DA, 0xA3E1 -- A3FA  */
            return FULLWIDTH_ASCII_CHAR;

        }
        if (c1 >= 0xB0 && c1 <= 0xF7) 
        {        /* B0A1 -- F7FE */
            return KANJI_CHAR;

        }
        return UNCLASSIFIED_CHAR;
    case CS_BIG5:
        if (c1 < 0x80)
            return  SEVEN_BIT_CHAR;

        c2 = *(pstr + 1);
        if ((c1 == 0xA2 && (c2 >= 0xCF && c2 <= 0xFF)) || 
            (c1 == 0xA3 && c2 <= 0x43))
        {       /*   0xA2CF -- 0xA343  */
            return FULLWIDTH_ASCII_CHAR;

        }
        if (((c1 == 0xA3 && ((c2 >= 0x74 && c2 <= 0x7E))) || 
			 (c2 >= 0xA1 && c2 <= 0xBF)))
        {        /* A374 -- A37E, A3A1 -- A3BF */
            return FULLWIDTH_PRONOUNCE_CHAR;

        }
        if ((c1 == 0xA4 && c2 != 0x40) || c1 > 0xA4)
        {       /* over A441 */
            return KANJI_CHAR;

        }
        return UNCLASSIFIED_CHAR;
#if 0
	case CS_EUCJP:
		if (c == 0x8e)
		{
			return 1;
		}
		break;
    case CS_GB_8BIT:
#endif
	default:
		break;
	}

	return UNCLASSIFIED_CHAR;
}

/*
  Japanese Kinsoku table:
  Characters are not allowed in the beginning of line 
*/
const char *ProhibitBegin_SJIS[] = 
{
"\x21",  "\x25",  "\x29",  "\x2C",  "\x2E",  "\x3A",  "\x3B",  "\x3F",  "\x5D", "\x7D", 
"\xA1",   "\xA3",   "\xA4",   "\xA5",   "\xDE",   "\xDF",   "\x81\x41", "\x81\x42", "\x81\x43", "\x81\x44", 	
"\x81\x45", "\x81\x46", "\x81\x47", "\x81\x48", "\x81\x49", "\x81\x4A", "\x81\x4B", "\x81\x52",	"\x81\x53", "\x81\x54", 
"\x81\x55", "\x81\x58", "\x81\x66", "\x81\x68", "\x81\x6A", "\x81\x6C", "\x81\x6E", "\x81\x70", "\x81\x72", "\x81\x74", 	
"\x81\x76", "\x81\x78", "\x81\x7A", "\x81\x8B", "\x81\x8C", "\x81\x8D", "\x81\x8E", "\x81\x91", "\x81\x93", "\x81\xF1", 
"\0"
};
const char *ProhibitBegin_EUCJP[] = 
{
"\x21",	 "\x25",	  "\x29",   "\x2C",   "\x2E",   "\x3A",   "\x3B",   "\x3F",   "\x5D",   "\x7D",            
"\x8E\xA1", "\x8E\xA3", "\x8E\xA4", "\x8E\xA5", "\x8E\xDE", "\x8E\xDF", "\xA1\xA2", "\xA1\xA3", "\xA1\xA4", "\xA1\xA5", 
"\xA1\xA6", "\xA1\xA7", "\xA1\xA8", "\xA1\xA9", "\xA1\xAA", "\xA1\xAB", "\xA1\xAC", "\xA1\xB3", "\xA1\xB4", "\xA1\xB5",
"\xA1\xB6", "\xA1\xB9", "\xA1\xC7", "\xA1\xC9",	"\xA1\xCB", "\xA1\xCD", "\xA1\xCF", "\xA1\xD1", "\xA1\xD3", "\xA1\xD5",
"\xA1\xD7", "\xA1\xD9", "\xA1\xDB", "\xA1\xEB", "\xA1\xEC", "\xA1\xED", "\xA1\xEE", "\xA1\xF1", "\xA1\xF3", "\xA2\xF3",
"\0"
};

/*
 * The datas are from Nadine Kano's book - Developing International Software -
 *   Page 239 - 245 
 */
const char *ProhibitBegin_BIG5[] = 
{
"\x21",     "\x29",     "\x2C", 	"\x2E",     "\x3A",     "\x3B",     "\x3F",     "\x5D",     "\x7D",     "\xA1\x41", 
"\xA1\x43", "\xA1\x44", "\xA1\x45", "\xA1\x46", "\xA1\x47", "\xA1\x48", "\xA1\x49", "\xA1\x4A", "\xA1\x4B", "\xA1\x4C", 
"\xA1\x4D", "\xA1\x4E", "\xA1\x50", "\xA1\x51", "\xA1\x52", "\xA1\x53", "\xA1\x54", "\xA1\x55", "\xA1\x56", "\xA1\x57", 
"\xA1\x58", "\xA1\x59", "\xA1\x5A", "\xA1\x5B", "\xA1\x5C", "\xA1\x5E", "\xA1\x60", "\xA1\x62", "\xA1\x64", "\xA1\x66", 
"\xA1\x68", "\xA1\x6A", "\xA1\x6C", "\xA1\x6E", "\xA1\x70", "\xA1\x72", "\xA1\x74", "\xA1\x76", "\xA1\x78", "\xA1\x7A", 
"\xA1\x7C", "\xA1\x7E", "\xA1\xA2", "\xA1\xA4", "\xA1\xA6", "\xA1\xA8", "\xA1\xAA", "\xA1\xAC", "\0"
};

const char *ProhibitBegin_GB[] = 
{
"\x21",     "\x29",     "\x2C",     "\x2E",     "\x3A",     "\x3B",     "\x3F",     "\x5D",     "\x7D",     "\xA1\xA2", 
"\xA1\xA3", "\xA1\xA4", "\xA1\xA5", "\xA1\xA6", "\xA1\xA7", "\xA1\xA8", "\xA1\xA9", "\xA1\xAA", "\xA1\xAB", "\xA1\xAC", 
"\xA1\xAD", "\xA1\xAF", "\xA1\xB1", "\xA1\xB3", "\xA1\xB5", "\xA1\xB7", "\xA1\xB9", "\xA1\xBB", "\xA1\xBD", "\xA1\xBF", 
"\xA1\xC3", "\xA3\xA1", "\xA3\xA2", "\xA3\xA7", "\xA3\xA9", "\xA3\xAC", "\xA3\xAE", "\xA3\xBA", "\xA3\xBB", "\xA3\xBF", 
"\xA3\xDD", "\xA3\xE0", "\xA3\xFC", "\xA3\xFD", "\0"
};

const char *ProhibitBegin_KSC[] = 
{
"\x21",     "\x25",     "\x29",     "\x2C",     "\x2E",     "\x3A",     "\x3B",     "\x3F",     "\x5D",     "\x7D", 
"\xA1\xA2", "\xA1\xAF", "\xA1\xB1", "\xA1\xB3", "\xA1\xB5", "\xA1\xB7", "\xA1\xB9", "\xA1\xBB", "\xA1\xBD", "\xA1\xC6", 
"\xA1\xC7", "\xA1\xC8", "\xA1\xC9", "\xA1\xCB", "\xA3\xA1", "\xA3\xA5", "\xA3\xA9", "\xA3\xAC", "\xA3\xAE", "\xA3\xBA", 
"\xA3\xBB", "\xA3\xBF", "\xA3\xDC", "\xA3\xDD", "\xA3\xFD", "\0"
};




/*
  Japanese Kinsoku table:
  Characters are not allowed in the end of line 
*/

const char *ProhibitEnd_SJIS[] =
{
"\x24",     "\x28",     "\x5B",     "\x5C",     "\x7B",     "\xA2",     "\x81\x65", "\x81\x67", "\x81\x69", "\x81\x6B",
"\x81\x6D", "\x81\x6F", "\x81\x71", "\x81\x73", "\x81\x75", "\x81\x77", "\x81\x79", "\x81\x8F", "\x81\x90", "\x81\x92",
"\0"
};
const char *ProhibitEnd_EUCJP[] =
{
"\x24",     "\x28",     "\x5B",     "\x5C",     "\x7B",     "\x8E\xA2", "\xA1\xC6", "\xA1\xC8", "\xA1\xCA", "\xA1\xCC",
"\xA1\xCE", "\xA1\xD0", "\xA1\xD2", "\xA1\xD4", "\xA1\xD6", "\xA1\xD8", "\xA1\xDA", "\xA1\xEF", "\xA1\xF0", "\xA1\xF2",
"\0"
};

const char *ProhibitEnd_BIG5[] = 
{
"\x28",    "\x5B",    "\x7B",    "\xA1\x5D", "\xA1\x5F", "\xA1\x61", "\xA1\x63", "\xA1\x65", "\xA1\x67", "\xA1\x69", 
"\xA1\x6D","\xA1\x6F","\xA1\x71","\xA1\x73", "\xA1\x75", "\xA1\x77", "\xA1\x79", "\xA1\x7B", "\xA1\x7D", 
"\xA1\xA1","\xA1\xA3","\xA1\xA5","\xA1\xA7", "\xA1\xA9", "\xA1\xAB", "\0"
};

const char *ProhibitEnd_GB[] = 
{
"\x28",    "\x5B",    "\x7B",    "\xA1\xAE", "\xA1\xB0", "\xA1\xB2", "\xA1\xB4", "\xA1\xB6", "\xA1\xB8", "\xA1\xBA", 
"\xA1\xBC","\xA1\xBE","\xA3\xA8","\xA3\xAE", "\xA3\xDB", "\xA3\xFB", "\0"
};

const char *ProhibitEnd_KSC[] = 
{
"\x28",    "\x5B",    "\x5C",    "\x7B",    "\xA1\xAE", "\xA1\xB0", "\xA1\xB2", "\xA1\xB4", "\xA1\xB6", "\xA1\xB8", 
"\xA1\xBA","\xA1\xBC","\xA3\xA4","\xA3\xA8","\xA3\xDB", "\xA3\xDC", "\xA3\xFB", "\0"
};


int INTL_KinsokuClass(int16 win_csid, unsigned char *pstr)
{
    int i;
	switch (win_csid)
	{
	  case CS_SJIS:
        for (i = 0; ProhibitBegin_SJIS[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitBegin_SJIS[i], XP_STRLEN(ProhibitBegin_SJIS[i])) == 0)
                return  PROHIBIT_BEGIN_OF_LINE;
        for (i = 0; ProhibitEnd_SJIS[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitEnd_SJIS[i], XP_STRLEN(ProhibitEnd_SJIS[i])) == 0)
                return PROHIBIT_END_OF_LINE;
		break;
	case CS_EUCJP:
        for (i = 0; i < ProhibitBegin_EUCJP[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitBegin_EUCJP[i], XP_STRLEN(ProhibitBegin_EUCJP[i])) == 0)
                return  PROHIBIT_BEGIN_OF_LINE;
        for (i = 0; i < ProhibitEnd_EUCJP[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitEnd_EUCJP[i], XP_STRLEN(ProhibitEnd_EUCJP[i])) == 0)
                return PROHIBIT_END_OF_LINE;
		break;
	case CS_GB_8BIT:
        for (i = 0; ProhibitBegin_GB[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitBegin_GB[i], XP_STRLEN(ProhibitBegin_GB[i])) == 0)
                return  PROHIBIT_BEGIN_OF_LINE;
        for (i = 0; ProhibitEnd_GB[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitEnd_GB[i], XP_STRLEN(ProhibitEnd_GB[i])) == 0)
                return PROHIBIT_END_OF_LINE;
		break;
	case CS_BIG5:
        for (i = 0; ProhibitBegin_BIG5[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitBegin_BIG5[i], XP_STRLEN(ProhibitBegin_BIG5[i])) == 0)
                return  PROHIBIT_BEGIN_OF_LINE;
        for (i = 0; ProhibitEnd_BIG5[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitEnd_BIG5[i], XP_STRLEN(ProhibitEnd_BIG5[i])) == 0)
                return PROHIBIT_END_OF_LINE;
		break;
	case CS_KSC_8BIT:
        for (i = 0; ProhibitBegin_KSC[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitBegin_KSC[i], XP_STRLEN(ProhibitBegin_KSC[i])) == 0)
                return  PROHIBIT_BEGIN_OF_LINE;
        for (i = 0; ProhibitEnd_KSC[i][0]; i++)
            if (XP_STRNCMP((char *)pstr, ProhibitEnd_KSC[i], XP_STRLEN(ProhibitEnd_KSC[i])) == 0)
                return PROHIBIT_END_OF_LINE;
		break;
	}

    return  PROHIBIT_NOWHERE;
}


#ifdef XP_UNIX
/* We need this linkerdummy to keep INTL_CompoundStrFromUnicode */
void* linkerdummy = (void*)INTL_CompoundStrFromUnicode;
#endif