﻿// Utf8_16.cxx
// Copyright (C) 2002 Scott Kirkwood
//
// Permission to use, copy, modify, distribute and sell this code
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies or
// any derived copies.  Scott Kirkwood makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#include "Utf8_16.h"
#include <windows.h>
#include <mbstring.h>
#include <fstream>      // std::ifstream

//#include "SString.h"
#include "Code.h"

#include <stdio.h>

//const int blockSize = 131072;
//const int blockSize = 11;
//

// ==================================================================
// ==================================================================

const Utf8_16::utf8 Utf8_16::k_Boms[][3] = {
	{0x00, 0x00, 0x00},  // Unknown
	{0xFE, 0xFF, 0x00},  // Big endian
	{0xFF, 0xFE, 0x00},  // Little endian
	{0xEF, 0xBB, 0xBF}, // UTF8
};

enum { SURROGATE_LEAD_FIRST = 0xD800 };
enum { SURROGATE_LEAD_LAST = 0xDBFF };
enum { SURROGATE_TRAIL_FIRST = 0xDC00 };
enum { SURROGATE_TRAIL_LAST = 0xDFFF };
enum { SURROGATE_FIRST_VALUE = 0x10000 };

UniMode SpecifiedEncoding=uni8Bit;
// ==================================================================
// ==================================================================

Euc_Iter::Euc_Iter() {
	iFstOnTwo = 0;
    m_pRead=NULL;
	m_eState=eStart;
	m_nCur=0;
	// for euc to utf8 
	iFstOnTwo = 0;
	ihbyte = 0;
}
Euc_Iter::~Euc_Iter() {
	iFstOnTwo = 0;
    m_pRead=NULL;
	m_eState=eStart;
	m_nCur=0;
	// for euc to utf8 
	iFstOnTwo = 0;
	ihbyte = 0;
}
int Euc_Iter::CheckOnEUC(unsigned char  *pcPos, size_t uiLen)
{

	size_t i=0;
	int iPoint;

	if( langId == 0x0804)
	{
		return 0;
	}

	iPoint = 100;
	while((iPoint > (int)0) && (i< uiLen))    // && (*pcPos != '\n')
	{
		if(iFstOnTwo == 1)
		{
			if((*pcPos < 0xA1) || (*pcPos > 0xFE))	/* 2バイト目は 0xA1～0xFE */
			{
				iPoint = 0;
				break;
			}
			iFstOnTwo = 0;
		}
		else if(iFstOnTwo == 2)		/* 皝E钎?*/
		{
			if((*pcPos < 0xA0) || (*pcPos > 0xDF))	/* 2バイト目は 0xA0～0xDF */
			{
				iPoint = 0;
				break;
			}
			iFstOnTwo = 0;
		}
		else
		{
			if(*pcPos == 0x8E)		/* 0x8E??は皝E钎?*/
				iFstOnTwo = 2;
			else if((*pcPos >= 0xA1) && (*pcPos <= 0xFE))
				iFstOnTwo = 1;
			else if( *pcPos > 0x80 ){
				iPoint = 0;
				break;
			}
		}
		pcPos++;
		i++;
	}
	//if(iFstOnTwo != 0)		/* １バイト目で終E盲皮い丒韦悉筏? */
	//	iPoint = 0;
	iFstOnTwo=0;

	return(iPoint);
}

size_t Euc_Iter::EucJpToUtf8(unsigned char  *pcEucChar,size_t iEucLen, unsigned char  *pcUtf8Char, int *ipLeftChar)
{

	unsigned char  *pcChar=pcUtf8Char;

	size_t i=0;

	int iCode;

	//iFstOnTwo = 0;  //※※※※※※※※※※※E

	while(i< iEucLen)
	{
		if(iFstOnTwo == 0)
		{
			if(*pcEucChar == 0x8E)		/* 0x8E??は皝E钎?*/
				iFstOnTwo = 2;
			else if((*pcEucChar > 0xA0) && (*pcEucChar < 0xFF))
			{
				ihbyte=*pcEucChar-0xA1;
				iFstOnTwo = 1;
			}
			else if((*pcEucChar > 0x0) && (*pcEucChar < 0x80))
			{

				iCode=*pcEucChar;
				iFstOnTwo = 0;
			}

		}
		else if(iFstOnTwo == 2)		/* 皝E钎?*/
		{
			if((*pcEucChar > 0xA0) || (*pcEucChar < 0xE0))	/* 2バイト目は 0xA0～0xDF */
			{
				iCode=0xFF00|(*pcEucChar-0x40);
			}
			iFstOnTwo = 0;
		}
		else
		{
			if((*pcEucChar > 0xA0) || (*pcEucChar < 0xFF))	/* 2バイト目は 0xA1～0xFE */
			{
				iCode=euc_unicode_tbl[ihbyte][*pcEucChar-0xA1];
			}

			iFstOnTwo = 0;
		}

		m_eState=eStart;
		if (iFstOnTwo==0)
		{
			do{
				switch (m_eState) {
					case eStart:
						if (iCode < 0x80) {
							*pcUtf8Char++ = static_cast<ubyte>(iCode & 0xFF);
							m_eState = eStart;
						} else if (iCode < 0x800) {
							*pcUtf8Char++ = static_cast<ubyte>(0xC0 | iCode >> 6);
							m_eState = eFinal;
						} else if (iCode < SURROGATE_FIRST_VALUE) {
							*pcUtf8Char++ = static_cast<ubyte>(0xE0 | iCode >> 12);
							m_eState = ePenultimate;
						} else {
							*pcUtf8Char++ = static_cast<ubyte>(0xF0 | iCode >> 18);
							m_eState = eSecondOf4Bytes;
						}
						break;
					case eSecondOf4Bytes:
						*pcUtf8Char++ = static_cast<ubyte>(0x80 | ((iCode >> 12) & 0x3F));
						m_eState = ePenultimate;
						break;
					case ePenultimate:
						*pcUtf8Char++ = static_cast<ubyte>(0x80 | ((iCode >> 6) & 0x3F));
						m_eState = eFinal;
						break;
					case eFinal:
						*pcUtf8Char++ = static_cast<ubyte>(0x80 | (iCode & 0x3F));
						m_eState = eStart;
						break;
				}
			}while ( m_eState != eStart);
		}



		pcEucChar++;
		i++;
	}
	*pcUtf8Char=0x0;
	if(iFstOnTwo != 0)		/* １バイト目で終E盲皮い丒韦悉筏? */
		*ipLeftChar = 1;

	return(pcUtf8Char-pcChar);

}

size_t Euc_Iter::Utf8ToEucJp(unsigned char  *pcUtf8Char,size_t iUtf8Len, unsigned char  *pcEucChar)
{

	size_t i,n,m,k;
	int cmp_flg;
	unsigned short  usTmp;
	unsigned char  *pcChar=pcEucChar;

	m_pRead=pcUtf8Char;
	i=0;

	//m_eState = eStart;   //※※※※※※※※※※※E
	while(i< iUtf8Len)
	{
		switch (m_eState) {
		case eStart:
			if ((0xF0 & *m_pRead) == 0xF0) {
				m_nCur = (0x7 & *m_pRead) << 18;
				m_eState = eSecondOf4Bytes;
			} else if ((0xE0 & *m_pRead) == 0xE0) {
				m_nCur = (~0xE0 & *m_pRead) << 12;
				m_eState = ePenultimate;
			} else if ((0xC0 & *m_pRead) == 0xC0) {
				m_nCur = (~0xC0 & *m_pRead) << 6;
				m_eState = eFinal;
			} else {
				m_nCur = *m_pRead;
				m_eState = eStart;
			}
			break;
		case eSecondOf4Bytes:
			m_nCur |= (0x3F & *m_pRead) << 12;
			m_eState = ePenultimate;
			break;
		case ePenultimate:
			m_nCur |= (0x3F & *m_pRead) << 6;
			m_eState = eFinal;
			break;
		case eFinal:
			m_nCur |= static_cast<utf8>(0x3F & *m_pRead);
			m_eState = eStart;
			break;
		}

		++m_pRead;

		if(m_eState == eStart)
		{
			if((m_nCur> 0x0 )&& (m_nCur < 0x80))		/* 0x8E??は皝E钎?*/
			{
				*pcEucChar++=(char)m_nCur;

			}
			else if((m_nCur > 0xFF60) && (m_nCur < 0xFFA0))
			{
				*(wchar_t *)pcEucChar=(0x8E00|((m_nCur & 0xFF)+0x40));
			}
			else if ( m_nCur < SURROGATE_FIRST_VALUE)
			{
				m=UNICODE_EUC_LEN-1;
				n=0;
				for(k=(n+m)/2; m>n;k=(n+m)/2)
				{
					cmp_flg=unicode_euc[k].unicode-(unsigned short)m_nCur;
					if(cmp_flg==0)
					{
						m=n;
						if( (unicode_euc[k].euc & 0xFF00) ==0){
							*pcEucChar++=(char)unicode_euc[k].euc;
						}else
						{
							usTmp=unicode_euc[k].euc;
							*pcEucChar++=(char)(usTmp & 0xFF);
							*pcEucChar++=(char)((usTmp>>8)&0xFF);
						}
					}
					else if(cmp_flg>0)
					{
						m=k;
					}
					else
					{
						if(n==k)
						{
							m=n;
							cmp_flg=unicode_euc[k+1].unicode-(unsigned short)m_nCur;
							if(0==cmp_flg)
							{

								if( (unicode_euc[k].euc & 0xFF00) ==0){
									*pcEucChar++=(char)unicode_euc[k].euc;
								}else
								{
									usTmp=unicode_euc[k].euc;
									*pcEucChar++=(char)(usTmp&0xFF);
									*pcEucChar++=(char)((usTmp>>8)&0xFF);
								}
							}

						}else
						{
							n=k;
						}
					}

				}

			}
		} // if(m_eState == eStart)
		i++;
	} //while(i< iUtf8Len)
	
	return(pcEucChar-pcChar);

}

//---------for MyRegEditor--Euc_Iter------------------start
size_t Euc_Iter::EucJpToUnicode(unsigned char  *pcEucChar,size_t iEucLen, wchar_t *pcUnicodeChar, int *ipLeftChar)
{

	size_t i=0;
	size_t iUniLen=0;
	int iFstOnTwo;
	int ihbyte;

	iFstOnTwo = 0;

	if (pcUnicodeChar == NULL)
	{
		while(i< iEucLen)
		{
			if(iFstOnTwo == 0)
			{
				if(*pcEucChar == 0x8E)		/* 0x8E??は半角カナ */
					iFstOnTwo = 2;
				else if((*pcEucChar > 0xA0) && (*pcEucChar < 0xFF))
				{
					iFstOnTwo = 1;
				}
				//else if((*pcEucChar > 0x0) && (*pcEucChar < 0x7F))
				else if((*pcEucChar > 0x0) && (*pcEucChar < 0x80))
				{
					iUniLen++;
					iFstOnTwo = 0;
				}

			}
			else if(iFstOnTwo == 2)		/* 半角カナ */
			{
				if((*pcEucChar > 0xA0) || (*pcEucChar < 0xE0))	/* 2バイト目は 0xA0～0xDF */
				{
					iUniLen++;

				}
				iFstOnTwo = 0;
			}
			else
			{
				if((*pcEucChar > 0xA0) || (*pcEucChar < 0xFF))	/* 2バイト目は 0xA1～0xFE */
				{
					iUniLen++;
				}

				iFstOnTwo = 0;
			}
			pcEucChar++;
			i++;
		}
		iUniLen++;
		if(iFstOnTwo != 0)		/* １バイト目で終わっているのはおかしい  */
			*ipLeftChar = 1;
	}else
	{
		while(i< iEucLen)
		{
			if(iFstOnTwo == 0)
			{

				if(*pcEucChar == 0x8E)		/* 0x8E??は半角カナ */
					iFstOnTwo = 2;
				else if((*pcEucChar > 0xA0) && (*pcEucChar < 0xFF))
				{
					ihbyte=*pcEucChar-0xA1;
					iFstOnTwo = 1;
				}
				//else if((*pcEucChar > 0x0) && (*pcEucChar < 0x7E))
				else if((*pcEucChar > 0x0) && (*pcEucChar < 0x80))
				{
					/*
					if ( *pcEucChar== 0x5C)
					{
						*pcUnicodeChar++=0xA5;
					}else{

						*pcUnicodeChar++=(wchar_t)*pcEucChar;
					}
					*/
					*pcUnicodeChar++=(wchar_t)*pcEucChar;
					iUniLen++;
					iFstOnTwo = 0;
				}
				/*
				else if(*pcEucChar == 0x7E){
					*pcUnicodeChar++=0x203E;
					iUniLen++;
					iFstOnTwo = 0;
				}
				*/

			}
			else if(iFstOnTwo == 2)		/* 半角カナ */
			{
				if((*pcEucChar > 0xA0) || (*pcEucChar < 0xE0))	/* 2バイト目は 0xA0～0xDF */
				{
					*pcUnicodeChar++=0xFF00|(*pcEucChar-0x40);
					iUniLen++;

				}
				iFstOnTwo = 0;
			}
			else
			{
				if((*pcEucChar > 0xA0) || (*pcEucChar < 0xFF))	/* 2バイト目は 0xA1～0xFE */
				{
					*pcUnicodeChar++=euc_unicode_tbl[ihbyte][*pcEucChar-0xA1];
					iUniLen++;
				}

				iFstOnTwo = 0;
			}
			pcEucChar++;
			i++;
		}
		*pcUnicodeChar=0x0;
		iUniLen++;
		if(iFstOnTwo != 0)		/* １バイト目で終わっているのはおかしい  */
			*ipLeftChar = 1;
	}

	return(iUniLen);

}

size_t Euc_Iter::UnicodeToEucJp(wchar_t *pcUnicodeChar, size_t iUnicodeLen, char *pcEucChar)
{

	size_t i=0;
	size_t n,m,k;
	int	cmp_flg;
	size_t iEucLen=0;
	//int iFstOnTwo;
	//int ihbyte;
	unsigned short  usTmp;

	if (pcEucChar == NULL)
	{
		while(i< iUnicodeLen)
		{
			//if((*pcUnicodeChar > 0x0) && (*pcUnicodeChar < 0x7E))		/* 0x8E??は半角カナ */
			if((*pcUnicodeChar > 0x0) && (*pcUnicodeChar < 0x80))	
			{
				/*
				if ( *pcUnicodeChar== 0x5C)
				{
					iEucLen++;
				}else{
					;
				}
				*/
				iEucLen++;

			}
			else if((*pcUnicodeChar > 0xFF60) && (*pcUnicodeChar < 0xFFA0))
			{
				iEucLen+=2;
			}
			else
			{
				m=UNICODE_EUC_LEN-1;
				n=0;
				for(k=(n+m)/2; m>n;k=(n+m)/2)
				{
					cmp_flg=unicode_euc[k].unicode-(unsigned short)*pcUnicodeChar;
					if(cmp_flg==0)
					{
						m=n;
						if( (unicode_euc[k].euc & 0xFF00) ==0){
							iEucLen++;
						}else
						{
							iEucLen+=2;
						}
					}else if(cmp_flg>0)
					{
						m=k;
					}else{
						if(n==k)
						{
							m=n;
							cmp_flg=unicode_euc[k+1].unicode-(unsigned short)*pcUnicodeChar;
							if(0==cmp_flg)
							{
								if( (unicode_euc[k].euc & 0xFF00 ) ==0){
									iEucLen++;
								}else
								{
									iEucLen+=2;
								}
							}

						}else
						{
							n=k;
						}
					}

				}

			}
		
			pcUnicodeChar++;
			i++;
		}
		iEucLen++;
	}else
	{
		while(i< iUnicodeLen)
		{
			//if((*pcUnicodeChar > 0x0 )&& (*pcUnicodeChar < 0x7E))		/* 0x8E??は半角カナ */
			if((*pcUnicodeChar > 0x0 )&& (*pcUnicodeChar < 0x80))		/* 0x8E??は半角カナ */
			{
				/*
				if ( *pcUnicodeChar== 0x5C)
				{
					*(wchar_t *)pcEucChar=0xA1C0;
					pcEucChar+=2;
					iEucLen++;
				}else{

					*pcEucChar++=(char)*pcUnicodeChar;
				}
				*/
				*pcEucChar++=(char)*pcUnicodeChar;
				iEucLen++;

			}
			else if((*pcUnicodeChar > 0xFF60) && (*pcUnicodeChar < 0xFFA0))
			{
				*(wchar_t *)pcEucChar=(0x8E00|((*pcUnicodeChar & 0xFF)+0x40));
				pcEucChar+=2;
				iEucLen+=2;
			}
			else
			{
				m=UNICODE_EUC_LEN-1;
				n=0;
				for(k=(n+m)/2; m>n;k=(n+m)/2)
				{
					cmp_flg=unicode_euc[k].unicode-(unsigned short)*pcUnicodeChar;
					if(cmp_flg==0)
					{
						m=n;
						if( (unicode_euc[k].euc & 0xFF00) ==0){
							*pcEucChar++=(char)unicode_euc[k].euc;
							iEucLen++;
						}else
						{
							usTmp=unicode_euc[k].euc;
							*pcEucChar++=(char)(usTmp & 0xFF);
							*pcEucChar++=(char)((usTmp>>8)&0xFF);

							iEucLen+=2;
						}
					}else if(cmp_flg>0)
					{
						m=k;
					}else{
						if(n==k)
						{
							m=n;
							cmp_flg=unicode_euc[k+1].unicode-(unsigned short)*pcUnicodeChar;
							if(0==cmp_flg)
							{

								if( (unicode_euc[k].euc & 0xFF00) ==0){
									*pcEucChar++=(char)unicode_euc[k].euc;
									iEucLen++;
								}else
								{
									usTmp=unicode_euc[k].euc;
									*pcEucChar++=(char)(usTmp&0xFF);
									*pcEucChar++=(char)((usTmp>>8)&0xFF);
									iEucLen+=2;
								}
							}

						}else
						{
							n=k;
						}
					}

				}

			}

		
			pcUnicodeChar++;
			i++;
		}
		*pcEucChar=0x0;
		iEucLen++;
	}

	return (iEucLen);
}
//---------for MyRegEditor--Euc_Iter------------------end

#define CONV_ASCII		0		/* ASCII文字処历蛐 */
#define CONV_KANJI		1		/* 漢字処历蛐 */
#define CONV_KANA		2		/* 皝E钎骏蕜I历蛐 */
#define CODE_ESC		0x1B		/* ESC */

#define LOW8(x)			((x) & 0xFF)
#define HIGH8(x)		(((x) >> 8) & 0xFF)

typedef unsigned char uchar; // 8 bits

/*----- JIS漢字コードをSHIFT-JIS漢字コードに変換 ------------------------------
*
*	Parameter
*		CODECONVINFO *cInfo : 漢字コード変換情垇E
*
*	Return Value
*		int くE丹伐榨楗?(YES/NO)
*
*	Note
*		くE丹伐榨楗挨琘ESの時は、cInfoの内容を変えずにもう一度呼ぶこと
*
*		エスケープコードは、次のものに対応していE
*			漢字開始		<ESC>$B		<ESC>$@
*			皝E钎书_始	<ESC>(I
*			漢字終了		<ESC>(B		<ESC>(J		<ESC>(H
*----------------------------------------------------------------------------*/
int ConvJIStoSJIS(CODECONVINFO *cInfo)
{
	int Kcode;
	const char *Str;
	char *Put;
	char *Limit;
	size_t StrLen=cInfo->StrLen;
	int Continue;

	//cInfo->KanaProc = &ConvJIStoSJISkanaProc;

	Continue = 0;
	Str = cInfo->Str;
	Put = cInfo->Buf;
	Limit = cInfo->Buf + cInfo->BufSize - 3;

	for(; StrLen > 0; StrLen--)
	{
		if(Put >= Limit)
		{
			Continue = 1;
			break;
		}

		if(cInfo->EscProc == 0)
		{
			if(*Str == CODE_ESC)
			{
				if(cInfo->KanjiFst != 0)
				{
					*Put++ = cInfo->KanjiFst;
					cInfo->KanjiFst = 0;
				}
				cInfo->EscCode[cInfo->EscProc] = *Str++;
				cInfo->EscProc++;
			}
			else
			{
				if(cInfo->KanjiMode == CONV_KANA)
				{
					if(cInfo->KanjiFst != 0)
					{
						*Put++ = cInfo->KanjiFst;
						cInfo->KanjiFst = 0;
					}

					if((*Str >= 0x21) && (*Str <= 0x5F))
					{
						*Put++ = *Str++| 0x80;
					}
					else
					{
						*Put++ = *Str++;
					}
				}
				else if(cInfo->KanjiMode == CONV_KANJI)
				{
					if((*Str >= 0x21) && (*Str <= 0x7E))
					{
						if(cInfo->KanjiFst == 0)
							cInfo->KanjiFst = *Str++;
						else
						{
							Kcode = _mbcjistojms((cInfo->KanjiFst * 0x100) + *Str++);
							*Put++ = HIGH8(Kcode);
							*Put++ = LOW8(Kcode);
							cInfo->KanjiFst = 0;
						}
					}
					else
					{
						if(cInfo->KanjiFst == 0)
							*Put++ = *Str++;
						else
						{
							*Put++ = cInfo->KanjiFst;
							*Put++ = *Str++;
							cInfo->KanjiFst = 0;
						}
					}
				}
				else
				{
					*Put++ = *Str++;
				}
			}
		}
		else if(cInfo->EscProc == 1)
		{
			if((*Str == '$') || (*Str == '('))
			{
				cInfo->EscCode[cInfo->EscProc] = *Str++;
				cInfo->EscProc++;
			}
			else
			{
				*Put++ = cInfo->EscCode[0];
				*Put++ = *Str++;
				cInfo->EscProc = 0;
			}
		}
		else if(cInfo->EscProc == 2)
		{
			if((cInfo->EscCode[1] == '$') && ((*Str == 'B') || (*Str == '@')))
				cInfo->KanjiMode = CONV_KANJI;
			else if((cInfo->EscCode[1] == '(') && (*Str == 'I'))
				cInfo->KanjiMode = CONV_KANA;
			else if((cInfo->EscCode[1] == '(') && ((*Str == 'B') || (*Str == 'J') || (*Str == 'H')))
				cInfo->KanjiMode = CONV_ASCII;
			else
			{
				*Put++ = cInfo->EscCode[0];
				*Put++ = cInfo->EscCode[1];
				if((cInfo->KanjiMode == CONV_KANJI) && ((*Str >= 0x21) && (*Str <= 0x7E)))
					cInfo->KanjiFst = *Str;
				else
					*Put++ = *Str;
			}
			Str++;
			cInfo->EscProc = 0;
		}
	}

	*Put= 0x0;
	//cInfo->Str = Str;
	cInfo->OutLen = Put - cInfo->Buf;

	return(Continue);
}

/*----- SHIFT-JIS漢字コードをJIS漢字コードに変換 ------------------------------
*
*	Parameter
*		CODECONVINFO *cInfo : 漢字コード変換情垇E
*
*	Return Value
*		int くE丹伐榨楗?(YES/NO)
*
*	Note
*		くE丹伐榨楗挨琘ESの時は、cInfoの内容を変えずにもう一度呼ぶこと
*
*		エスケープコードは、次のものを使用すE
*			漢字開始		<ESC>$B
*			皝E钎书_始	<ESC>(I
*			漢字終了		<ESC>(B
*----------------------------------------------------------------------------*/
int ConvSJIStoJIS(CODECONVINFO *cInfo)
{
	int Kcode;
	const char *Str;
	char *Put;
	char *Limit;
	size_t StrLen=cInfo->StrLen;
	int len=0;
	//int Continue;

	//cInfo->KanaProc = &ConvSJIStoJISkanaProc;

	//Continue = NO;
	Str = cInfo->Str;
	Put = cInfo->Buf;
	Limit = cInfo->Buf + cInfo->BufSize - 5;

	for(; StrLen > 0; StrLen--)
	{
		/*
		if(Put >= Limit)
		{
			Continue = YES;
			break;
		}
		*/

		if(cInfo->KanjiFst == 0)
		{
			if((((uchar)*Str >= (uchar)0x81) && ((uchar)*Str <= (uchar)0x9F)) ||
			   ((uchar)*Str >= (uchar)0xE0))
			{
				//Put = ConvSJIStoJISkanaProc(cInfo, 0, Put);
				cInfo->KanjiFst = *Str++;
			}
			else if(((uchar)*Str >= (uchar)0xA0) && ((uchar)*Str <= (uchar)0xDF))
			{
				//Put = ConvSJIStoJISkanaProc(cInfo, *Str++, Put);
				if(cInfo->KanjiMode != CONV_KANA)
				{
					if( Put )
					{
						*Put++ = CODE_ESC;
						*Put++ = '(';
						*Put++ = 'I';
					}
					else
					{
						len+=3;
					}
					cInfo->KanjiMode = CONV_KANA;
				}
				if( Put )
				{
					*Put++ = *Str  - 0x80;
				}
				else
				{
					len++;
				}
				Str++;
			}
			else
			{
				//Put = ConvSJIStoJISkanaProc(cInfo, 0, Put);
				if(cInfo->KanjiMode != CONV_ASCII)
				{
					if( Put )
					{
						*Put++ = CODE_ESC;
						*Put++ = '(';
						*Put++ = 'B';
					}
					else
					{
						len+=3;
					}
					cInfo->KanjiMode = CONV_ASCII;
				}
				if( Put )
				{
					*Put++ = *Str++;
				}
				else
				{
					len++;
					Str++;
				}
			}
		}
		else
		{
			//Put = ConvSJIStoJISkanaProc(cInfo, 0, Put);
			if((uchar)*Str >= (uchar)0x40)
			{
				if(cInfo->KanjiMode != CONV_KANJI)
				{
					if( Put )
					{
						*Put++ = CODE_ESC;
						*Put++ = '$';
						*Put++ = 'B';
					}
					else
					{
						len+=3;
					}
					cInfo->KanjiMode = CONV_KANJI;
				}

				//Kcode = ConvertIBMExtendedChar(((uchar)cInfo->KanjiFst * 0x100) + (uchar)*Str++);
				Kcode =((uchar)cInfo->KanjiFst * 0x100) + (uchar)*Str++;
				Kcode = _mbcjmstojis(Kcode);
				if( Put )
				{
					*Put++ = HIGH8(Kcode);
					*Put++ = LOW8(Kcode);
				}
				else
				{
					len+=2;
				}
			}
			else
			{
				if(cInfo->KanjiMode != CONV_ASCII)
				{
					if( Put )
					{
						*Put++ = 0x1B;
						*Put++ = '(';
						*Put++ = 'B';
					}
					else
					{
						len+=3;
					}
					cInfo->KanjiMode = CONV_ASCII;
				}
				if( Put )
				{
					*Put++ = cInfo->KanjiFst;
					*Put++ = *Str++;
				}
				else
				{
					len+=2;
					Str++;
				}
			}
			cInfo->KanjiFst = 0;
		}
	}

	//cInfo->Str = Str;
	cInfo->OutLen = Put - cInfo->Buf;

	return(len);
}

//---------for MyRegEditor--Utf16_Read------------------start
void Utf16_Read::init() 
{
	ansi[0]=0;
	ansi_bk=0;
	m_eEncoding = eUnknown;
	m_nBufSize = 0;
	m_pNewBuf = NULL;
	m_bFirstRead = true;
	m_pFileContent = NULL;
	m_LineNum = 0;
	
	memset( &m_ConvInfo , 0x0, sizeof(m_ConvInfo));
}
void Utf16_Read::free() 
{
	if ((m_pNewBuf != NULL) && (m_eEncoding != eUtf16LittleEndian)) {
		delete [] m_pNewBuf;
		m_pNewBuf = NULL;
	}
	if ( m_pFileContent ){
		delete  m_pFileContent;
	}
	m_LineInfo.clear();
}
Utf16_Read::Utf16_Read() 
{
	init();

}
Utf16_Read::Utf16_Read(const wchar_t *file) 
{
	init();
	readFile( file );

}
bool Utf16_Read::readFile(const wchar_t *file) 
{
	ifstream infile(file,ios::in);
	if(!infile)
		return FALSE;
	infile.seekg (0, infile.end);
	int l_iLen = infile.tellg();
	infile.seekg (0, infile.beg);

	m_pFileContent=new char[l_iLen+2];
	infile.read (m_pFileContent,l_iLen);
	infile.close();

	m_nFileSize =convert(m_pFileContent,l_iLen)/2;
	
	size_t  i,line_start,line_end;
	i=0;
	line_start=0;
	while(i<m_nFileSize)
	{
		if( reinterpret_cast<const wchar_t*>(m_pNewBuf)[i]==L'\n')
		{
			if(i>0&&reinterpret_cast<const wchar_t*>(m_pNewBuf)[i-1]==L'\r')
			{
				line_end=i-1;
			}else
			{
				line_end=i;
			}
			size_t length = line_end - line_start;
			Utf16_Line_Info ifno={line_start,length};
			m_LineInfo.push_back(ifno);
			line_start=i+1;
		}
		i++;
	}
	if (line_start <= m_nFileSize ){
		Utf16_Line_Info ifno={line_start,m_nFileSize-line_start};
		m_LineInfo.push_back(ifno);
	}
	m_LineNum = 0;
	return TRUE;
}
int Utf16_Read::getline(wchar_t *line, size_t _len)
{
	size_t sz= m_LineInfo.size();
	if (  m_LineNum <  sz  ){
		size_t  len= m_LineInfo[m_LineNum].len>_len-1 ?  _len-1: m_LineInfo[m_LineNum].len;
		wcsncpy(line, reinterpret_cast<const wchar_t*>(m_pNewBuf)+m_LineInfo[m_LineNum].idx, len );
		line[len] = L'\0';
		m_LineNum++;
		return 1;
	}
	else{
		return 0;
	}
}

Utf16_Read::~Utf16_Read() 
{
	free();

}

void Utf16_Read::reset()
{
	free();
	init();
}

void  Utf16_Read::CheckKanjiCode(char *Text, size_t Size) 
{
	char *Pos;
	char *Btm;
	//int PointSJIS;
	//int PointEUC;

	m_eEncoding = eUnknown;
	if(Size >= 2)
	{
		Btm = Text + Size;

		/* JIS漢字コードのチェック */
		Pos = Text;
		while((Pos = (char *)memchr(Pos, CODE_ESC, Btm-Pos-2)) != NULL)
		{
			Pos++;
			if((memcmp(Pos, "$B", 2) == 0) ||	/* <ESC>$B */
			   (memcmp(Pos, "$@", 2) == 0) ||	/* <ESC>$@ */
			   (memcmp(Pos, "(I", 2) == 0))		/* <ESC>(I */
			{
				m_eEncoding = eJis;
				break;
			}
		}

	}
	if ( m_eEncoding == eUnknown )
	{
		if(m_Ieuc.CheckOnEUC((unsigned char *)m_pBuf,m_nLen))
		{
			m_eEncoding = eEuc;
		}
		else
		{
			m_eEncoding = eAnsi;
		}

	}

}

// return byte size
size_t Utf16_Read::convert(const char* buf, size_t byteSize, bool Continue) {
	m_pBuf = reinterpret_cast<const ubyte*>(buf);
	m_nLen = byteSize;
	int nSkip = 0;
	if (m_bFirstRead) {
		nSkip = determineEncoding();
		m_bFirstRead = false;
	}

	if (m_eEncoding == eUtf16LittleEndian ) {
		// Pass through after BOM
		m_nBufSize = 0;
		m_pNewBuf = const_cast <ubyte*>(m_pBuf + nSkip);
		return byteSize - nSkip;
	}

	size_t newSize = (byteSize+1)*2;
	if (m_nBufSize != newSize) {
		if( m_pNewBuf )
		{
			delete [] m_pNewBuf;
		}
		m_pNewBuf = NULL;
		m_pNewBuf = new ubyte[newSize];
		m_nBufSize = newSize;
	}

	if (m_eEncoding == eUtf16BigEndian) {

		ubyte* pCur = m_pNewBuf;

		m_Iter16_16.set(m_pBuf + nSkip, byteSize - nSkip);

		for (; m_Iter16_16; ++m_Iter16_16) {
			for (;m_Iter16_16.canGet();) {
				*pCur++ = m_Iter16_16.get();
			}
		}

		*pCur=0;
		*(pCur+1)=0;

		// Return number of bytes writen out
		return pCur - m_pNewBuf;

	}

	if (m_eEncoding == eUtf8 || m_eEncoding == eUtf8_bom ) {
		m_Iter8.set(reinterpret_cast<const ubyte*>(m_pBuf + nSkip), byteSize - nSkip, eUtf16LittleEndian);

		utf16* pCur = reinterpret_cast<utf16*>(m_pNewBuf);
		for (; m_Iter8; ++m_Iter8) {
			if (m_Iter8.canGet()) {
				int codePoint = m_Iter8.get();
				if (codePoint >= SURROGATE_FIRST_VALUE) {
					codePoint -= SURROGATE_FIRST_VALUE;
					int lead = (codePoint >> 10) + SURROGATE_LEAD_FIRST;
					*pCur++ = static_cast<utf16>(lead);
					int trail = (codePoint & 0x3ff) + SURROGATE_TRAIL_FIRST;
					*pCur++ = static_cast<utf16>(trail);
				} else {
					*pCur++ = static_cast<utf16>(codePoint);
				}
			}
		}
		*pCur=0;
		return (reinterpret_cast<ubyte*>(pCur) - m_pNewBuf);
	}



	/////////////////////////////////////
	size_t    needLength;
	int     ret;
	size_t 	lenth=byteSize;
	/////////////////////////////////////
	if (m_eEncoding == eEuc) {
		needLength=m_Ieuc.EucJpToUnicode((unsigned char *)buf,byteSize,(wchar_t *)m_pNewBuf,&ret);
		lenth=2*(needLength-1);
	}
	else 
	{
		if ( m_eEncoding == eJis)
		{
			ansi[0]=0;

			m_ConvInfo.Str=buf;
			m_ConvInfo.StrLen=byteSize;

			char *ansi_buf = new char[byteSize+3];
			m_ConvInfo.Buf = ansi_buf;
			m_ConvInfo.BufSize = byteSize+3;

			ConvJIStoSJIS( &m_ConvInfo);

			buf=ansi_buf;
			lenth=m_ConvInfo.OutLen;
		}
		else
		{
			if (ansi_bk)
			{
				// have trail char
				--lenth; // 上一次转换时候剩了一个字节。所以这次开头第一个字符排除。
				// 派出的字符跟上一次字符一起组成一个字母。
			}

			ansi[0]=ansi_bk;
			if ( Continue ) 
			{
				size_t i;
				unsigned char judgeCh;
				for(i=1;i<=lenth;i++)
				{
					judgeCh= *(buf+byteSize-i);
					//if((judgeCh > 0x7F && judgeCh < 0xA1) || (judgeCh > 0xDF))
					if(judgeCh > 0x7F )
					{
						;
					}
					else //(judgeCh2<0x80 || (judgeCh2>0xA0 && judgeCh2< 0xE0 ))
					{
						break;
					}
				}
				if( 1==(i & 1))
				{
					ansi_bk=0;// code ended;
					//*(buf+byteSize)=0;
				}
				else
				{
					--lenth;
					ansi_bk=*(buf+byteSize-1);//code not end 
					//*(buf+byteSize-1)=0;
				}
			}
			else
			{
				ansi[0]=0;
				//*(buf+byteSize)=0;
			}
		}
		
		utf16 *wcharBuf;
		if(ansi[0])
		{
			// 上一次转换时候剩了一个字节
			ansi[1]=*buf;
			needLength=MultiByteToWideChar(CP_ACP, 0, buf+1, lenth, NULL, 0)+1+1;
			wcharBuf =new utf16[needLength];
			MultiByteToWideChar(CP_ACP, 0, ansi, -1, (LPWSTR)wcharBuf,1);
			MultiByteToWideChar(CP_ACP, 0, buf+1, lenth, (LPWSTR)wcharBuf+1, static_cast<int>(needLength-1));
		}
		else
		{
			needLength=MultiByteToWideChar(CP_ACP, 0, buf, lenth, NULL, 0)+1;
			wcharBuf =new utf16[needLength];
			MultiByteToWideChar(CP_ACP, 0, buf, lenth, (LPWSTR)wcharBuf, static_cast<int>(needLength));

			if ( m_eEncoding == eJis)
				delete [] buf;
		}

		lenth=2*(needLength-1);
		size_t iSize=(lenth<m_nBufSize-2) ? lenth : (m_nBufSize-2);

		wcharBuf[iSize/2]=L'\0';
		wcsncpy( reinterpret_cast<wchar_t *>(m_pNewBuf), reinterpret_cast<wchar_t *> (wcharBuf), iSize/2+1 );

		delete [] wcharBuf;
		// Return number of bytes writen out
		return iSize;

	}

	return lenth;
}

int Utf16_Read::determineEncoding() {
	m_eEncoding = eUnknown;

	int nRet = 0;

	if (m_nLen > 1) {
		switch ( SpecifiedEncoding ) 
		{
			case uni16BE:
				m_eEncoding = eUtf16BigEndian;
				nRet = 2;
				break;
			case uni16LE:
				m_eEncoding = eUtf16LittleEndian;
				nRet = 2;
				break;
			case uniUTF8_bom:
				m_eEncoding = eUtf8_bom;
				nRet = 3;
				break;
			case uniUTF8:
				m_eEncoding = eUtf8;
				nRet = 0;
				break;
			case uniAnsi:
				m_eEncoding = eAnsi;
				nRet = 0;
				break;
			case uniEuc:
				m_eEncoding = eEuc;
				nRet = 0;
				break;
			case uniJis:
				m_eEncoding = eJis;
				nRet = 0;
				break;
		}

		if ( SpecifiedEncoding != uni8Bit ) //not Auto Determine
		{
			return nRet;
		}

		if (m_pBuf[0] == k_Boms[eUtf16BigEndian][0] && m_pBuf[1] == k_Boms[eUtf16BigEndian][1]) {
			m_eEncoding = eUtf16BigEndian;
			nRet = 2;
		} else if (m_pBuf[0] == k_Boms[eUtf16LittleEndian][0] && m_pBuf[1] == k_Boms[eUtf16LittleEndian][1]) {
			m_eEncoding = eUtf16LittleEndian;
			nRet = 2;
		} else if (m_nLen > 2 && m_pBuf[0] == k_Boms[eUtf8_bom][0] && m_pBuf[1] == k_Boms[eUtf8_bom][1] && m_pBuf[2] == k_Boms[eUtf8_bom][2]) {
			m_eEncoding = eUtf8_bom;
			nRet = 3;
		}else if(m_Iter8.CheckOnUTF8((unsigned char *)m_pBuf,m_nLen))
		{
			m_eEncoding = eUtf8;
		}
		else 
		{
			CheckKanjiCode(( char *)m_pBuf, m_nLen);
		}
	}
	return nRet;
}
//---------for MyRegEditor--Utf16_Read------------------end



void Utf8_Read::init() 
{
	ansi[0]=0;
	ansi_bk=0;
	m_eEncoding = eUnknown;
	m_nBufSize = 0;
	m_pNewBuf = NULL;
	m_bFirstRead = true;
	
	memset( &m_ConvInfo , 0x0, sizeof(m_ConvInfo));
}
void Utf8_Read::free() 
{
	if ((m_pNewBuf != NULL) && (m_eEncoding != eUnknown) 
		&& (m_eEncoding != eUtf8)
		&& (m_eEncoding != eUtf8_bom)) {
		delete [] m_pNewBuf;
		m_pNewBuf = NULL;
	}
}
Utf8_Read::Utf8_Read() 
{
	init();

}

Utf8_Read::~Utf8_Read() 
{
	free();

}

void Utf8_Read::reset()
{
	free();
	init();
}

void  Utf8_Read::CheckKanjiCode(char *Text, size_t Size) 
{
	char *Pos;
	char *Btm;
	//int PointSJIS;
	//int PointEUC;

	m_eEncoding = eUnknown;
	if(Size >= 2)
	{
		Btm = Text + Size;

		/* JIS漢字コードのチェック */
		Pos = Text;
		while((Pos = (char *)memchr(Pos, CODE_ESC, Btm-Pos-2)) != NULL)
		{
			Pos++;
			if((memcmp(Pos, "$B", 2) == 0) ||	/* <ESC>$B */
			   (memcmp(Pos, "$@", 2) == 0) ||	/* <ESC>$@ */
			   (memcmp(Pos, "(I", 2) == 0))		/* <ESC>(I */
			{
				m_eEncoding = eJis;
				break;
			}
		}

	}
	if ( m_eEncoding == eUnknown )
	{
		if(m_Ieuc.CheckOnEUC((unsigned char *)m_pBuf,m_nLen))
		{
			m_eEncoding = eEuc;
		}
		else
		{
			m_eEncoding = eAnsi;
		}

	}

}

size_t Utf8_Read::convert(char* buf, size_t len, bool Continue) {
	m_pBuf = reinterpret_cast<ubyte*>(buf);
	m_nLen = len;
	int nSkip = 0;
	if (m_bFirstRead) {
		nSkip = determineEncoding();
		m_bFirstRead = false;
	}

	if (m_eEncoding == eUtf8 || m_eEncoding == eUtf8_bom ) {
		// Pass through after BOM
		m_nBufSize = 0;
		m_pNewBuf = m_pBuf + nSkip;
		return len - nSkip;
	}


	size_t newSize = len + len / 2 + 2;
	if (m_nBufSize != newSize) {
		if( m_pNewBuf )
		{
			delete [] m_pNewBuf;
		}
		m_pNewBuf = NULL;
		m_pNewBuf = new ubyte[newSize];
		m_nBufSize = newSize;
	}

	// Else...
	if (m_eEncoding == eUtf16BigEndian ||
		m_eEncoding == eUtf16LittleEndian
		) {

		ubyte* pCur = m_pNewBuf;

		m_Iter16.set(m_pBuf + nSkip, len - nSkip, m_eEncoding);

		for (; m_Iter16; ++m_Iter16) {
			for (; m_Iter16.canGet();) {
				*pCur++ = m_Iter16.get();
			}
		}
		*pCur=0;

		// Return number of bytes writen out
		return pCur - m_pNewBuf;

	}


		/////////////////////////////////////
		size_t    needLength;
		int     ret;
		size_t 	lenth=len;
		/////////////////////////////////////
		if (m_eEncoding == eEuc) {
			needLength=m_Ieuc.EucJpToUtf8((unsigned char *)buf,len,(unsigned char *)m_pNewBuf,&ret);
		}
		else 
		{
			unsigned char judgeCh;

			if ( m_eEncoding == eJis)
			{
				ansi[0]=0;

				m_ConvInfo.Str=buf;
				m_ConvInfo.StrLen=len;

				char *ansi_buf = new char[len+3];
				m_ConvInfo.Buf = ansi_buf;
				m_ConvInfo.BufSize = len+3;

				ConvJIStoSJIS( &m_ConvInfo);

				buf=ansi_buf;
			}
			else
			{
				if (ansi_bk)
				{
					// have trail char
					--lenth;
				}

				ansi[0]=ansi_bk;
				if ( Continue ) 
				{
					size_t i;
					for(i=1;i<=lenth;i++)
					{
						judgeCh= *(buf+len-i);
						//if((judgeCh > 0x7F && judgeCh < 0xA1) || (judgeCh > 0xDF))
						if(judgeCh > 0x7F )
						{
							;
						}
						else //(judgeCh2<0x80 || (judgeCh2>0xA0 && judgeCh2< 0xE0 ))
						{
							break;
						}
					}
					if( 1==(i & 1))
					{
						ansi_bk=0;// code ended;
						*(buf+len)=0;
					}
					else
					{
						ansi_bk=*(buf+len-1);//code not end 
						*(buf+len-1)=0;
					}
				}
				else
				{
					ansi[0]=0;
					*(buf+len)=0;
				}
			}
			
			utf16 *wcharBuf;
			if(ansi[0])
			{
				ansi[1]=*buf;
				needLength=MultiByteToWideChar(CP_ACP, 0, buf+1, -1, NULL, 0)+1;
				wcharBuf =new utf16[needLength];
				MultiByteToWideChar(CP_ACP, 0, ansi, -1, (LPWSTR)wcharBuf,1);
				MultiByteToWideChar(CP_ACP, 0, buf+1, -1, (LPWSTR)wcharBuf+1, static_cast<int>(needLength-1));
			}
			else
			{
				needLength=MultiByteToWideChar(CP_ACP, 0, buf, -1, NULL, 0);
				wcharBuf =new utf16[needLength];
				MultiByteToWideChar(CP_ACP, 0, buf, -1, (LPWSTR)wcharBuf, static_cast<int>(needLength));

				if ( m_eEncoding == eJis)
					delete [] buf;
			}
			ubyte* pCur = m_pNewBuf;
			ubyte* pEndCur = m_pNewBuf+m_nBufSize-1;

			m_Iter16.set( (ubyte *)wcharBuf, 2*(needLength-1), eUtf16LittleEndian);

			for (; pCur<pEndCur && m_Iter16; ++m_Iter16) {
				for (; m_Iter16.canGet();) {
					*pCur++ = m_Iter16.get();
				}
			}

			*pCur=0;
			size_t iSize=pCur - m_pNewBuf;

			delete [] wcharBuf;
			// Return number of bytes writen out
			return iSize;

		}

		return needLength;
}

int Utf8_Read::determineEncoding() {
	m_eEncoding = eUnknown;

	int nRet = 0;

	if (m_nLen > 1) {
		switch ( SpecifiedEncoding ) 
		{
			case uni16BE:
				m_eEncoding = eUtf16BigEndian;
				nRet = 2;
				break;
			case uni16LE:
				m_eEncoding = eUtf16LittleEndian;
				nRet = 2;
				break;
			case uniUTF8_bom:
				m_eEncoding = eUtf8_bom;
				nRet = 3;
				break;
			case uniUTF8:
				m_eEncoding = eUtf8;
				nRet = 0;
				break;
			case uniAnsi:
				m_eEncoding = eAnsi;
				nRet = 0;
				break;
			case uniEuc:
				m_eEncoding = eEuc;
				nRet = 0;
				break;
			case uniJis:
				m_eEncoding = eJis;
				nRet = 0;
				break;
		}

		if ( SpecifiedEncoding != uni8Bit ) //not Auto Determine
		{
			return nRet;
		}

		if (m_pBuf[0] == k_Boms[eUtf16BigEndian][0] && m_pBuf[1] == k_Boms[eUtf16BigEndian][1]) {
			m_eEncoding = eUtf16BigEndian;
			nRet = 2;
		} else if (m_pBuf[0] == k_Boms[eUtf16LittleEndian][0] && m_pBuf[1] == k_Boms[eUtf16LittleEndian][1]) {
			m_eEncoding = eUtf16LittleEndian;
			nRet = 2;
		} else if (m_nLen > 2 && m_pBuf[0] == k_Boms[eUtf8_bom][0] && m_pBuf[1] == k_Boms[eUtf8_bom][1] && m_pBuf[2] == k_Boms[eUtf8_bom][2]) {
			m_eEncoding = eUtf8_bom;
			nRet = 3;
		}else if(m_Iter8.CheckOnUTF8((unsigned char *)m_pBuf,m_nLen))
		{
			m_eEncoding = eUtf8;
		}
		else 
		{
			CheckKanjiCode(( char *)m_pBuf, m_nLen);
		}
	}

	


	return nRet;
}

//---------for MyRegEditor--Utf8_Write------------------start
Utf16_Write::Utf16_Write() {
	m_eEncoding = eUnknown;
	m_pFile = NULL;
	m_pBuf = NULL;
	m_bFirstWrite = true;
	m_nBufSize = 0;

	memset( &m_ConvInfo , 0x0, sizeof(m_ConvInfo));
}

Utf16_Write::~Utf16_Write() {
	if (m_pFile) {
		fclose();
	}
}

void Utf16_Write::setfile(FILE *pFile) {
	m_pFile = pFile;
	fseek(pFile, 0, SEEK_SET);
	m_bFirstWrite = true;
}

// Swap the two low order bytes of an integer value
static int swapped(int v) {
	return ((v & 0xFF) << 8) + (v >> 8);
}

size_t Utf16_Write::fwrite(const void* p, size_t _wordSize) {

	if (!m_pFile) {
		return 0; // fail
	}

	if (m_bFirstWrite) {
		if (m_eEncoding == eUtf16BigEndian || m_eEncoding == eUtf16LittleEndian) {
			// Write the BOM
			::fwrite(k_Boms[m_eEncoding], 2, 1, m_pFile);
		}else if (m_eEncoding == eUtf8_bom|| m_eEncoding == eUnknown){
			m_eEncoding=eUtf8_bom;
			::fwrite(k_Boms[m_eEncoding], 3, 1, m_pFile);
		}
		m_bFirstWrite = false;
	}

	if (m_eEncoding == eUtf16LittleEndian) {
		// Normal write
		return ::fwrite(p, _wordSize*2, 1, m_pFile);
	}

	if (_wordSize > m_nBufSize) {
		m_nBufSize = _wordSize;
		delete [] m_pBuf;
		m_pBuf = new utf16[_wordSize + 1];
	}

	if (m_eEncoding == eUtf16BigEndian) {

		ubyte* pCur = reinterpret_cast<ubyte*>(m_pBuf);

		m_Iter16_16.set(reinterpret_cast<const ubyte*>(p) , _wordSize*2);

		for (; m_Iter16_16; ++m_Iter16_16) {
			for (;m_Iter16_16.canGet();) {
				*pCur++ = m_Iter16_16.get();
			}
		}

		*pCur=0;
		// Return number of bytes writen out
		return ::fwrite(m_pBuf, pCur - (reinterpret_cast<const ubyte*>(m_pBuf)), 1, m_pFile);

	}

	if (m_eEncoding == eEuc) {
		size_t i_size =m_Ieuc.UnicodeToEucJp((wchar_t *)p,_wordSize,(char *)m_pBuf);
		return ::fwrite(m_pBuf, i_size, 1, m_pFile);
	}

	if (m_eEncoding == eAnsi || m_eEncoding == eJis) {
		int strLength = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)p, static_cast<int>(_wordSize), NULL, 0, NULL, NULL);
		char *ansi_buf=new char[strLength+1];
		memset(ansi_buf, 0x00, strLength + 1);
		WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)p, static_cast<int>(_wordSize), ansi_buf, strLength, NULL, NULL);

		size_t ch_ret;
		if (m_eEncoding == eJis)
		{
				m_ConvInfo.Str=ansi_buf;
				m_ConvInfo.StrLen=strLength;

				m_ConvInfo.Buf = NULL;
				m_ConvInfo.BufSize = 0;

				int jis_len = ConvSJIStoJIS( &m_ConvInfo);

				char *jis_buf=new char[jis_len+1];

				m_ConvInfo.Buf = jis_buf;
				m_ConvInfo.BufSize = jis_len+1;

				jis_len = ConvSJIStoJIS( &m_ConvInfo);
				ch_ret =::fwrite(jis_buf, m_ConvInfo.OutLen, 1, m_pFile);

				delete [] jis_buf;

		}else
		{
			ch_ret =::fwrite(ansi_buf, strLength, 1, m_pFile);
		}
		delete [] ansi_buf;

		return ch_ret;
	}
	
	ubyte* pCur = reinterpret_cast<ubyte*>(m_pBuf);

	m_Iter16.set(reinterpret_cast<const ubyte*>(p), _wordSize*2, eUtf16LittleEndian);

	for (; m_Iter16;) {
		++m_Iter16;
		for (; m_Iter16.canGet();) {
			*pCur++ = m_Iter16.get();
		}
	}
	size_t 	lenth=pCur - reinterpret_cast<ubyte*>(m_pBuf);

	// for eUtf8_bom,   eUtf8_bom,   eUtf8_bom
	return ::fwrite(m_pBuf, lenth, 1, m_pFile);

}

void Utf16_Write::fclose() {
	delete [] m_pBuf;
	m_pBuf = NULL;

	::fclose(m_pFile);
	m_pFile = NULL;
}

void Utf16_Write::setEncoding(Utf8_16::encodingType eType) {
	m_eEncoding = eType;
}

//---------for MyRegEditor--Utf8_Write------------------end

Utf8_Write::Utf8_Write() {
	m_eEncoding = eUnknown;
	m_pFile = NULL;
	m_pBuf = NULL;
	m_bFirstWrite = true;
	m_nBufSize = 0;

	memset( &m_ConvInfo , 0x0, sizeof(m_ConvInfo));
}

Utf8_Write::~Utf8_Write() {
	if (m_pFile) {
		fclose();
	}
}

void Utf8_Write::setfile(FILE *pFile) {
	m_pFile = pFile;
	fseek(m_pFile, 0, SEEK_SET);
	m_bFirstWrite = true;
}


size_t Utf8_Write::fwrite(const void* p, size_t _byteSize) {

	if (!m_pFile) {
		return 0; // fail
	}

	if (m_eEncoding == eUtf8) {
		// Normal write
		return ::fwrite(p, _byteSize, 1, m_pFile);
	}

	if (m_eEncoding == eUtf8_bom|| m_eEncoding == eUnknown) {
		m_eEncoding=eUtf8_bom;
		if (m_bFirstWrite)
			::fwrite(k_Boms[m_eEncoding], 3, 1, m_pFile);
		m_bFirstWrite = false;
		return ::fwrite(p, _byteSize, 1, m_pFile);
	}

	if (_byteSize > m_nBufSize) {
		m_nBufSize = _byteSize;
		delete [] m_pBuf;
		m_pBuf = new utf16[_byteSize + 1];
	}

	if (m_eEncoding == eEuc) {
		size_t i_size =m_Ieuc.Utf8ToEucJp((unsigned char *)p,_byteSize,(unsigned char *)m_pBuf);
		return ::fwrite(m_pBuf, i_size, 1, m_pFile);
	}

	if (m_bFirstWrite) {
		if (m_eEncoding == eUtf16BigEndian || m_eEncoding == eUtf16LittleEndian) {
			// Write the BOM
			::fwrite(k_Boms[m_eEncoding], 2, 1, m_pFile);
		}

		m_bFirstWrite = false;
	}

	Utf8_Iter iter8;

	iter8.set(reinterpret_cast<const ubyte*>(p), _byteSize, m_eEncoding);

	utf16* pCur = m_pBuf;

	for (; iter8; ++iter8) {
		if (iter8.canGet()) {
			int codePoint = iter8.get();
			if (codePoint >= SURROGATE_FIRST_VALUE) {
				codePoint -= SURROGATE_FIRST_VALUE;
				int lead = (codePoint >> 10) + SURROGATE_LEAD_FIRST;
				*pCur++ = static_cast<utf16>((m_eEncoding == eUtf16BigEndian) ?
					swapped(lead) : lead);
				int trail = (codePoint & 0x3ff) + SURROGATE_TRAIL_FIRST;
				*pCur++ = static_cast<utf16>((m_eEncoding == eUtf16BigEndian) ?
					swapped(trail) : trail);
			} else {
				*pCur++ = static_cast<utf16>((m_eEncoding == eUtf16BigEndian) ?
					swapped(codePoint) : codePoint);
			}
		}
	}

	if (m_eEncoding == eAnsi || m_eEncoding == eJis) {
		*pCur=0;
		int strLength = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)m_pBuf, -1, NULL, 0, NULL, NULL);
		char *ansi_buf=new char[strLength+1];
		memset(ansi_buf, 0x00, strLength + 1);
		WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)m_pBuf, -1, ansi_buf, strLength, NULL, NULL);

		size_t ch_ret;
		if (m_eEncoding == eJis)
		{
				m_ConvInfo.Str=ansi_buf;
				m_ConvInfo.StrLen=strLength;

				m_ConvInfo.Buf = NULL;
				m_ConvInfo.BufSize = 0;

				int jis_len = ConvSJIStoJIS( &m_ConvInfo);

				char *jis_buf=new char[jis_len+1];

				m_ConvInfo.Buf = jis_buf;
				m_ConvInfo.BufSize = jis_len+1;

				jis_len = ConvSJIStoJIS( &m_ConvInfo);
				ch_ret =::fwrite(jis_buf, m_ConvInfo.OutLen, 1, m_pFile);

				delete [] jis_buf;

		}else
		{
			ch_ret =::fwrite(ansi_buf, strLength, 1, m_pFile);
		}
		delete [] ansi_buf;

		return ch_ret;
	}

	size_t ret = ::fwrite(m_pBuf, (const char*)pCur - (const char*)m_pBuf, 1, m_pFile);

	return ret;
}

void Utf8_Write::fclose() {
	delete [] m_pBuf;
	m_pBuf = NULL;

	::fclose(m_pFile);
	m_pFile = NULL;
}

void Utf8_Write::setEncoding(Utf8_16::encodingType eType) {
	m_eEncoding = eType;
}

// ==================================================================

// ==================================================================

Utf8_16_Read::Utf8_16_Read() {
	m_eEncoding = eUnknown;
	m_nBufSize = 0;
	m_pBuf = NULL;
	m_pNewBuf = NULL;
	m_bFirstRead = true;
	m_nLen = 0;
}

Utf8_16_Read::~Utf8_16_Read() {
	if ((m_eEncoding != eUnknown) && (m_eEncoding != eUtf8)) {
		delete [] m_pNewBuf;
		m_pNewBuf = NULL;
	}
}

size_t Utf8_16_Read::convert(char* buf, size_t len) {
	m_pBuf = reinterpret_cast<ubyte*>(buf);
	m_nLen = len;

	int nSkip = 0;
	if (m_bFirstRead) {
		nSkip = determineEncoding();
		m_bFirstRead = false;
	}

	if (m_eEncoding == eUnknown) {
		// Do nothing, pass through
		m_nBufSize = 0;
		m_pNewBuf = m_pBuf;
		return len;
	}

	if (m_eEncoding == eUtf8) {
		// Pass through after BOM
		m_nBufSize = 0;
		m_pNewBuf = m_pBuf + nSkip;
		return len - nSkip;
	}

	// Else...
	size_t newSize = len + len / 2 + 1;
	if (m_nBufSize != newSize) {
		delete [] m_pNewBuf;
		m_pNewBuf = new ubyte[newSize];
		m_nBufSize = newSize;
	}

	ubyte* pCur = m_pNewBuf;

	m_Iter16.set(m_pBuf + nSkip, len - nSkip, m_eEncoding);

	for (; m_Iter16; ++m_Iter16) {
		for (; m_Iter16.canGet();) {
			*pCur++ = m_Iter16.get();
		}
	}

	// Return number of bytes written out
	return pCur - m_pNewBuf;
}

int Utf8_16_Read::determineEncoding() {
	m_eEncoding = eUnknown;

	int nRet = 0;

	if (m_nLen > 1) {
		if (m_pBuf[0] == k_Boms[eUtf16BigEndian][0] && m_pBuf[1] == k_Boms[eUtf16BigEndian][1]) {
			m_eEncoding = eUtf16BigEndian;
			nRet = 2;
		} else if (m_pBuf[0] == k_Boms[eUtf16LittleEndian][0] && m_pBuf[1] == k_Boms[eUtf16LittleEndian][1]) {
			m_eEncoding = eUtf16LittleEndian;
			nRet = 2;
		} else if (m_nLen > 2 && m_pBuf[0] == k_Boms[eUtf8][0] && m_pBuf[1] == k_Boms[eUtf8][1] && m_pBuf[2] == k_Boms[eUtf8][2]) {
			m_eEncoding = eUtf8;
			nRet = 3;
		}
	}

	return nRet;
}

// ==================================================================

Utf8_16_Write::Utf8_16_Write() {
	m_eEncoding = eUnknown;
	m_pFile = NULL;
	m_pBuf = NULL;
	m_bFirstWrite = true;
	m_nBufSize = 0;
}

Utf8_16_Write::~Utf8_16_Write() {
	if (m_pFile) {
		fclose();
	}
}

void Utf8_16_Write::setfile(FILE *pFile) {
	m_pFile = pFile;

	m_bFirstWrite = true;
}

// Swap the two low order bytes of an integer value
size_t Utf8_16_Write::fwrite(const void* p, size_t _size) {
	if (!m_pFile) {
		return 0; // fail
	}

	if (m_eEncoding == eUnknown) {
		// Normal write
		return ::fwrite(p, _size, 1, m_pFile);
	}

	if (m_eEncoding == eUtf8) {
		if (m_bFirstWrite)
			::fwrite(k_Boms[m_eEncoding], 3, 1, m_pFile);
		m_bFirstWrite = false;
		return ::fwrite(p, _size, 1, m_pFile);
	}

	if (_size > m_nBufSize) {
		m_nBufSize = _size;
		delete [] m_pBuf;
		m_pBuf = new utf16[_size + 1];
	}

	if (m_bFirstWrite) {
		if (m_eEncoding == eUtf16BigEndian || m_eEncoding == eUtf16LittleEndian) {
			// Write the BOM
			::fwrite(k_Boms[m_eEncoding], 2, 1, m_pFile);
		}

		m_bFirstWrite = false;
	}

	Utf8_Iter iter8;
	iter8.set(reinterpret_cast<const ubyte*>(p), _size, m_eEncoding);

	utf16* pCur = m_pBuf;

	for (; iter8; ++iter8) {
		if (iter8.canGet()) {
			int codePoint = iter8.get();
			if (codePoint >= SURROGATE_FIRST_VALUE) {
				codePoint -= SURROGATE_FIRST_VALUE;
				int lead = (codePoint >> 10) + SURROGATE_LEAD_FIRST;
				*pCur++ = static_cast<utf16>((m_eEncoding == eUtf16BigEndian) ?
					swapped(lead) : lead);
				int trail = (codePoint & 0x3ff) + SURROGATE_TRAIL_FIRST;
				*pCur++ = static_cast<utf16>((m_eEncoding == eUtf16BigEndian) ?
					swapped(trail) : trail);
			} else {
				*pCur++ = static_cast<utf16>((m_eEncoding == eUtf16BigEndian) ?
					swapped(codePoint) : codePoint);
			}
		}
	}

	size_t ret = ::fwrite(m_pBuf, (const char*)pCur - (const char*)m_pBuf, 1, m_pFile);

	return ret;
}

void Utf8_16_Write::fclose() {
	delete [] m_pBuf;
	m_pBuf = NULL;

	::fclose(m_pFile);
	m_pFile = NULL;
}

void Utf8_16_Write::setEncoding(Utf8_16::encodingType eType) {
	m_eEncoding = eType;
}

//=================================================================
Utf8_Iter::Utf8_Iter() {
	reset();
}

void Utf8_Iter::reset() {
	m_pBuf = NULL;
	m_pRead = NULL;
	m_pEnd = NULL;
	m_eState = eStart;
	m_nCur = 0;
	m_eEncoding = eUnknown;
}

void Utf8_Iter::set
	(const ubyte* pBuf, size_t nLen, Utf8_16::encodingType eEncoding) {
	m_pBuf = pBuf;
	m_pRead = pBuf;
	m_pEnd = pBuf + nLen;
	m_eEncoding = eEncoding;
	operator++();
	// Note: m_eState, m_nCur not reset
}
// Go to the next byte.
void Utf8_Iter::operator++() {
	switch (m_eState) {
	case eStart:
		if ((0xF0 & *m_pRead) == 0xF0) {
			m_nCur = (0x7 & *m_pRead) << 18;
			m_eState = eSecondOf4Bytes;
		} else if ((0xE0 & *m_pRead) == 0xE0) {
			m_nCur = (~0xE0 & *m_pRead) << 12;
			m_eState = ePenultimate;
		} else if ((0xC0 & *m_pRead) == 0xC0) {
			m_nCur = (~0xC0 & *m_pRead) << 6;
			m_eState = eFinal;
		} else {
			m_nCur = *m_pRead;
			toStart();
		}
		break;
	case eSecondOf4Bytes:
		m_nCur |= (0x3F & *m_pRead) << 12;
		m_eState = ePenultimate;
		break;
	case ePenultimate:
		m_nCur |= (0x3F & *m_pRead) << 6;
		m_eState = eFinal;
		break;
	case eFinal:
		m_nCur |= static_cast<utf8>(0x3F & *m_pRead);
		toStart();
		break;
	}
	++m_pRead;
}

void Utf8_Iter::toStart() {
	m_eState = eStart;
}

int Utf8_Iter::CheckOnUTF8(unsigned char  * pcPos, size_t uiLen)
{
	int iUtf8=100;
	int iAnsi=100;
	m_eState = eStart;
	m_nCur = 0;
	m_pRead = reinterpret_cast<ubyte*>(pcPos);
	m_pEnd = m_pRead + uiLen;
	
	for (; (iUtf8==100)&&(m_pRead<m_pEnd);	++m_pRead) 
	{
		switch (m_eState) {
		case eStart:
			if ((0xF8 & *m_pRead) == 0xF0) {
				iAnsi=0;
				m_eState = eSecondOf4Bytes;
			} else if ((0xF0 & *m_pRead) == 0xE0) {
				iAnsi=0;
				m_eState = ePenultimate;
			} else if ((0xE0 & *m_pRead) == 0xC0) {
				iAnsi=0;
				m_eState = eFinal;
			} else if ((0x80 & *m_pRead) == 0) {
				// ASCII
				toStart();
			}else {
				// ???
				iUtf8=0;
			}
			break;
		case eSecondOf4Bytes:
			if ((0xC0 & *m_pRead) == 0x80) 
			{
				m_eState = ePenultimate;
			}
			else
			{
				iUtf8=0;
			}
			break;
		case ePenultimate:
			if ((0xC0 & *m_pRead) == 0x80) 
			{
				m_eState = ePenultimate;
			}
			else
			{
				iUtf8=0;
			}
			m_eState = eFinal;
			break;
		case eFinal:
			if ((0xC0 & *m_pRead) == 0x80) 
			{
				m_eState = ePenultimate;
			}
			else
			{
				iUtf8=0;
			}
			toStart();
			break;
		}
	}

	if (iAnsi)
	{
		iUtf8=0;
	}
	return iUtf8;
}

//==================================================
Utf16_Iter::Utf16_Iter() {
	reset();
}

void Utf16_Iter::reset() {
	m_pBuf = NULL;
	m_pRead = NULL;
	m_pEnd = NULL;
	m_eGetState=eNull;
	m_eReadState = eStart;
	m_nCur = 0;
	m_nCur16 = 0;
	m_eEncoding = eUnknown;
}

void Utf16_Iter::set(const ubyte* pBuf, size_t _byteSize, Utf8_16::encodingType eEncoding) {
	m_pBuf = pBuf;
	m_pRead = pBuf;
	m_pEnd = pBuf + _byteSize;
	m_eEncoding = eEncoding;
	// operator++();
	// Note: m_eState, m_nCur, m_nCur16 not reinitialized.
}
//modified
Utf8_16::utf8 Utf16_Iter::get(){
	switch (m_eGetState) {
	case eStart:
		if (m_nCur16 < 0x80) {
			m_nCur = static_cast<ubyte>(m_nCur16 & 0xFF);
			m_eGetState = eNull;
			m_eReadState = eStart;
		} else if (m_nCur16 < 0x800) {
			m_nCur = static_cast<ubyte>(0xC0 | m_nCur16 >> 6);
			m_eGetState = eFinal;
		} else if (m_nCur16 < SURROGATE_FIRST_VALUE) {
			m_nCur = static_cast<ubyte>(0xE0 | m_nCur16 >> 12);
			m_eGetState = ePenultimate;
		} else {
			m_nCur = static_cast<ubyte>(0xF0 | m_nCur16 >> 18);
			m_eGetState = eSecondOf4Bytes;
		}
		break;
	case eSecondOf4Bytes:
		m_nCur = static_cast<ubyte>(0x80 | ((m_nCur16 >> 12) & 0x3F));
		m_eGetState = ePenultimate;
		break;
	case ePenultimate:
		m_nCur = static_cast<ubyte>(0x80 | ((m_nCur16 >> 6) & 0x3F));
		m_eGetState = eFinal;
		break;
	case eFinal:
		m_nCur = static_cast<ubyte>(0x80 | (m_nCur16 & 0x3F));
		m_eGetState = eNull;
		m_eReadState = eStart;
		break;
	}
	return m_nCur;
}

// Goes to the next byte.
// Not the next symbol which you might expect.
// This way we can continue from a partial buffer that doesn't align
//modified
void Utf16_Iter::operator++() {
	switch (m_eReadState) {
	case eStart:
		if (m_eEncoding == eUtf16LittleEndian) {
			m_nCur16 = *m_pRead;
		} else {
			m_nCur16 = static_cast<utf16>(*m_pRead << 8);
		}
		m_eReadState=eSecondOf4Bytes;
		break;
	case eSecondOf4Bytes:
		if (m_eEncoding == eUtf16LittleEndian) {
			m_nCur16 |= static_cast<utf16>(*m_pRead << 8);
		} else {
			m_nCur16 |= *m_pRead;
		}
		if (m_nCur16 >= SURROGATE_LEAD_FIRST && m_nCur16 <= SURROGATE_LEAD_LAST) {
			m_eReadState = ePenultimate;
		}else{
			m_eReadState = eNull;
			m_eGetState = eStart;
		}
		break;
	case ePenultimate:
		if (m_eEncoding == eUtf16LittleEndian) {
			trail = *m_pRead;
		} else {
			trail = static_cast<utf16>(*m_pRead << 8);
		}
		m_eReadState = eFinal;
		break;
	case eFinal:
		if (m_eEncoding == eUtf16LittleEndian) {
			trail |= static_cast<utf16>(*m_pRead << 8);
		} else {
			trail |= *m_pRead;
		}
		m_nCur16 = (((m_nCur16 & 0x3ff) << 10) | (trail & 0x3ff)) + SURROGATE_FIRST_VALUE;
		m_eReadState = eNull;
		m_eGetState = eStart;
		break;
	case eNull:
		return ;
	}
	++m_pRead;
}

//==================================================
Utf16_16Iter::Utf16_16Iter() {
	reset();
}

void Utf16_16Iter::reset() {
	m_pBuf = NULL;
	m_pRead = NULL;
	m_pEnd = NULL;
	m_eGetState=eNull;
	m_eReadState = eStart;
	m_nCur = 0;
	trail = 0;
}

void Utf16_16Iter::set
	(const ubyte* pBuf, size_t nLen) {
	m_pBuf = pBuf;
	m_pRead = pBuf;
	m_pEnd = pBuf + nLen;
	operator++();
	// Note: m_eState, m_nCur, m_nCur16 not reinitialized.
}

Utf8_16::utf8 Utf16_16Iter::get(){
	switch (m_eGetState) {
	case eStart:
		m_eGetState = eFinal;
		break;
	case eFinal:
		m_nCur=trail;
		m_eGetState = eNull;
		m_eReadState = eStart;
		break;
	}
	return m_nCur;
}

// Goes to the next byte.
// Not the next symbol which you might expect.
// This way we can continue from a partial buffer that doesn't align
void Utf16_16Iter::operator++() {
	switch (m_eReadState) {
	case eStart:
		trail = *m_pRead;
		m_eReadState=eFinal;
		break;
	case eFinal:
		m_nCur= *m_pRead;
		m_eReadState = eNull;
		m_eGetState = eStart;
		break;
	case eNull:
		return ;
	}
	++m_pRead;
}
