You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
925 lines
30 KiB
925 lines
30 KiB
// ============================================================================
|
|
// Internet Character Set Conversion: Input from ISO-2022-JP
|
|
// ============================================================================
|
|
|
|
#include "private.h"
|
|
#include "fechrcnv.h"
|
|
#include "jisobj.h"
|
|
|
|
#include "codepage.h"
|
|
|
|
/******************************************************************************
|
|
************************** C O N S T R U C T O R **************************
|
|
******************************************************************************/
|
|
|
|
CInccJisIn::CInccJisIn(UINT uCodePage, int nCodeSet) : CINetCodeConverter(uCodePage, nCodeSet)
|
|
{
|
|
Reset(); // initialization
|
|
return ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
******************************* R E S E T *********************************
|
|
******************************************************************************/
|
|
|
|
void CInccJisIn::Reset()
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_fShift = FALSE;
|
|
m_fJapan = FALSE;
|
|
m_fLeadByte = FALSE ;
|
|
m_tcLeadByte = 0 ;
|
|
m_nESCBytes = 0 ;
|
|
m_eEscState = JIS_ASCII ;
|
|
return ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
************************* C O N V E R T C H A R *************************
|
|
******************************************************************************/
|
|
|
|
HRESULT CInccJisIn::ConvertChar(UCHAR tc, int cchSrc)
|
|
{
|
|
BOOL fDone = (this->*m_pfnConv)(tc);
|
|
if (fDone)
|
|
return S_OK;
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
/******************************************************************************
|
|
***************************** C L E A N U P *****************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUp()
|
|
{
|
|
return (this->*m_pfnCleanUp)();
|
|
}
|
|
|
|
/******************************************************************************
|
|
**************************** C O N V M A I N ****************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::ConvMain(UCHAR tc)
|
|
{
|
|
BOOL fDone = TRUE;
|
|
|
|
switch (tc) {
|
|
case SO:
|
|
m_fShift = TRUE;
|
|
break;
|
|
|
|
case SI:
|
|
m_fShift = FALSE;
|
|
m_fLeadByte = FALSE;
|
|
break;
|
|
|
|
default:
|
|
if (m_fShift) {
|
|
fDone = Output(tc | 0x80);
|
|
// it may continue to convert to Unicode, so we need to know
|
|
// whether current byte is a lead byte or not
|
|
m_fLeadByte = ~m_fLeadByte ;
|
|
} else {
|
|
if (tc == ESC) {
|
|
m_pfnConv = ConvEsc;
|
|
m_pfnCleanUp = CleanUpEsc;
|
|
m_nESCBytes++;
|
|
} else {
|
|
if (m_fJapan) {
|
|
if (tc == '*') {
|
|
m_pfnConv = ConvStar;
|
|
m_pfnCleanUp = CleanUpStar;
|
|
} else {
|
|
m_pfnConv = ConvDoubleByte;
|
|
m_pfnCleanUp = CleanUpDoubleByte;
|
|
m_tcLeadByte = tc;
|
|
}
|
|
} else {
|
|
switch ( m_eEscState )
|
|
{
|
|
case JIS_ASCII:
|
|
fDone = Output(tc);
|
|
break ;
|
|
case JIS_Roman:
|
|
#if 0
|
|
if ( tc == 0x7e ) /* tilde in ACSII -> overline */
|
|
{
|
|
Output(0x81);
|
|
fDone = Output(0x50);
|
|
}
|
|
else
|
|
fDone = Output(tc);
|
|
#else
|
|
fDone = Output(tc);
|
|
#endif
|
|
break ;
|
|
case JIS_Kana:
|
|
fDone = Output(tc | 0x80 );
|
|
break ;
|
|
default:
|
|
fDone = Output(tc);
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return fDone;
|
|
}
|
|
|
|
/******************************************************************************
|
|
************************ C L E A N U P M A I N ************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUpMain()
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
***************************** C O N V E S C *****************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::ConvEsc(UCHAR tc)
|
|
{
|
|
switch (tc) {
|
|
case ISO2022_IN_CHAR:
|
|
m_pfnConv = ConvIsoIn;
|
|
m_pfnCleanUp = CleanUpIsoIn;
|
|
m_nESCBytes++;
|
|
return TRUE;
|
|
|
|
case ISO2022_OUT_CHAR:
|
|
m_pfnConv = ConvIsoOut;
|
|
m_pfnCleanUp = CleanUpIsoOut;
|
|
m_nESCBytes++;
|
|
return TRUE;
|
|
|
|
default:
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_nESCBytes = 0 ;
|
|
(void)Output(ESC);
|
|
if (SUCCEEDED(ConvertChar(tc)))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
************************* C L E A N U P E S C *************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUpEsc()
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
return Output(ESC);
|
|
}
|
|
|
|
/******************************************************************************
|
|
************************** C O N V I S O I N **************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::ConvIsoIn(UCHAR tc)
|
|
{
|
|
switch (tc) {
|
|
case ISO2022_IN_JP_CHAR1: /* 'B' */
|
|
case ISO2022_IN_JP_CHAR2: /* '@' */
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_fJapan = TRUE;
|
|
m_nESCBytes = 0 ;
|
|
return TRUE;
|
|
|
|
case ISO2022_IN_JP_CHAR3_1: /* '(' */
|
|
m_pfnConv = ConvIsoInJp;
|
|
m_pfnCleanUp = CleanUpIsoInJp;
|
|
m_nESCBytes++ ;
|
|
return TRUE;
|
|
|
|
default:
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_nESCBytes = 0 ;
|
|
(void)Output(ESC);
|
|
(void)ConvertChar(ISO2022_IN_CHAR);
|
|
if (SUCCEEDED(ConvertChar(tc)))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
********************** C L E A N U P I S O I N **********************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUpIsoIn()
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
|
|
(void)Output(ESC);
|
|
(void)ConvertChar(ISO2022_IN_CHAR);
|
|
return CleanUp();
|
|
}
|
|
|
|
/******************************************************************************
|
|
*********************** C O N V I S O I N J P ***********************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::ConvIsoInJp(UCHAR tc)
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_nESCBytes = 0 ;
|
|
|
|
if (tc == ISO2022_IN_JP_CHAR3_2) {
|
|
m_fJapan = TRUE;
|
|
return TRUE;
|
|
} else {
|
|
(void)Output(ESC);
|
|
(void)ConvertChar(ISO2022_IN_CHAR);
|
|
(void)ConvertChar(ISO2022_IN_JP_CHAR3_1);
|
|
if (SUCCEEDED(ConvertChar(tc)))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
******************* C L E A N U P I S O I N J P *******************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUpIsoInJp()
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_nESCBytes = 0 ;
|
|
|
|
(void)Output(ESC);
|
|
(void)ConvertChar(ISO2022_IN_CHAR);
|
|
(void)ConvertChar(ISO2022_IN_JP_CHAR3_1);
|
|
return CleanUp();
|
|
}
|
|
|
|
/******************************************************************************
|
|
************************* C O N V I S O O U T *************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::ConvIsoOut(UCHAR tc)
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_nESCBytes = 0 ;
|
|
|
|
switch (tc) {
|
|
case ISO2022_OUT_JP_CHAR1: /* B */
|
|
m_fJapan = FALSE;
|
|
m_eEscState = JIS_ASCII ;
|
|
return TRUE;
|
|
|
|
case ISO2022_OUT_JP_CHAR2: /* J */
|
|
case ISO2022_OUT_JP_CHAR4: /* H */
|
|
m_fJapan = FALSE;
|
|
m_eEscState = JIS_Roman ;
|
|
return TRUE;
|
|
|
|
case ISO2022_OUT_JP_CHAR3: /* I */
|
|
m_fJapan = FALSE;
|
|
m_eEscState = JIS_Kana ;
|
|
return TRUE;
|
|
|
|
default:
|
|
(void)Output(ESC);
|
|
(void)ConvertChar(ISO2022_OUT_CHAR);
|
|
if (SUCCEEDED(ConvertChar(tc)))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
********************* C L E A N U P I S O O U T *********************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUpIsoOut()
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
m_nESCBytes = 0 ;
|
|
|
|
(void)Output(ESC);
|
|
(void)ConvertChar(ISO2022_OUT_CHAR);
|
|
return CleanUp();
|
|
}
|
|
|
|
/******************************************************************************
|
|
**************************** C O N V S T A R ****************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::ConvStar(UCHAR tc)
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
|
|
return Output(tc | 0x80);
|
|
}
|
|
|
|
/******************************************************************************
|
|
************************ C L E A N U P S T A R ************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUpStar()
|
|
{
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
|
|
return Output('*');
|
|
}
|
|
|
|
/******************************************************************************
|
|
********************* C O N V D O U B L E B Y T E *********************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::ConvDoubleByte(UCHAR tc)
|
|
{
|
|
BOOL bRet ;
|
|
UCHAR tcSJisLB;
|
|
UCHAR tcSJisTB;
|
|
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
|
|
tcSJisLB = ((m_tcLeadByte - 0x21) >> 1) + 0x81;
|
|
if (tcSJisLB > 0x9f)
|
|
tcSJisLB += 0x40;
|
|
|
|
tcSJisTB = tc + (m_tcLeadByte & 1 ? 0x1f : 0x7d);
|
|
if (tcSJisTB >= 0x7f)
|
|
tcSJisTB++;
|
|
|
|
(void)Output(tcSJisLB);
|
|
bRet = Output(tcSJisTB);
|
|
|
|
m_tcLeadByte = 0 ;
|
|
return bRet ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
***************** C L E A N U P D O U B L E B Y T E *****************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisIn::CleanUpDoubleByte()
|
|
{
|
|
BOOL bRet ;
|
|
m_pfnConv = ConvMain;
|
|
m_pfnCleanUp = CleanUpMain;
|
|
|
|
bRet = Output(m_tcLeadByte);
|
|
m_tcLeadByte = 0 ;
|
|
return bRet ;
|
|
}
|
|
|
|
int CInccJisIn::GetUnconvertBytes()
|
|
{
|
|
if ( m_tcLeadByte || m_fLeadByte )
|
|
return 1 ;
|
|
else if ( m_nESCBytes )
|
|
return m_nESCBytes < 4 ? m_nESCBytes : 3 ;
|
|
else
|
|
return 0 ;
|
|
}
|
|
|
|
DWORD CInccJisIn::GetConvertMode()
|
|
{
|
|
// 0xC42C -> 50220 ISO-2022-JP
|
|
return ( m_fJapan ? 1 : 0 ) + ( m_fShift ? 2 : 0 ) | 0xC42C0000 ;
|
|
}
|
|
|
|
void CInccJisIn::SetConvertMode(DWORD mode)
|
|
{
|
|
Reset();
|
|
if ( mode & 0x00000001 )
|
|
m_fJapan = TRUE ;
|
|
if ( mode & 0x00000002 )
|
|
m_fShift = TRUE ;
|
|
|
|
return ;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Internet Character Set Conversion: Output to ISO-2022-JP
|
|
// ============================================================================
|
|
|
|
#define VOICE_MARK_OFFSET 0xA0
|
|
#define VOICE_MARK_DEDF_OFFSET 0xC8
|
|
|
|
#if 0 // Shift JIS Table - not used
|
|
// this is the table used to determine whether the kana char is voiced sound markable
|
|
// if it is, what is the combined full width kana.
|
|
static WCHAR g_wVoiceMarkKana[48] =
|
|
{
|
|
/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, */
|
|
|
|
/* a0-af */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8394, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
|
/* b0-bf */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x834B, 0x834D, 0x834f, 0x8351, 0x8353, 0x8355, 0x8357, 0x8359, 0x835B, 0x835D,
|
|
/* c0-cf */ 0x835F, 0x8361, 0x8364, 0x8366, 0x8368, 0x0, 0x0, 0x0, 0x0, 0x0, 0x836F, 0x8372, 0x8375, 0x8378, 0x837B, 0x0,
|
|
|
|
};
|
|
|
|
// special voiced sound mark '0xde' conversion
|
|
static WCHAR g_wMarkDEKana[16] =
|
|
{
|
|
/* c8-cf */ 0x0, 0x0, 0x836F, 0x8372, 0x8375, 0x8378, 0x837B, 0x0,
|
|
};
|
|
|
|
|
|
// special voiced sound mark '0xdf' conversion
|
|
static WCHAR g_wMarkDFKana[16] =
|
|
{
|
|
/* c8-cf */ 0x0, 0x0, 0x8370, 0x8373, 0x8376, 0x8379, 0x837C, 0x0,
|
|
};
|
|
|
|
// this is the table used to convert half width kana to full width kana
|
|
static WCHAR g_wFullWKana[64] =
|
|
{
|
|
/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, */
|
|
|
|
/* a0-af */ 0x0, 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x8392, 0x8340, 0x8342, 0x8344, 0x8346, 0x8348, 0x8383, 0x8385, 0x8387, 0x8362,
|
|
/* b0-bf */ 0x815B, 0x8341, 0x8343, 0x8345, 0x8347, 0x8349, 0x834A, 0x834C, 0x834E, 0x8350, 0x8352, 0x8354, 0x8356, 0x8358, 0x835A, 0x835C,
|
|
/* c0-cf */ 0x835E, 0x8360, 0x8363, 0x8365, 0x8367, 0x8369, 0x836A, 0x836B, 0x836C, 0x836D, 0x836E, 0x8371, 0x8374, 0x8377, 0x837A, 0x837D,
|
|
/* d0-df */ 0x837E, 0x8380, 0x8381, 0x8382, 0x8384, 0x8386, 0x8388, 0x8389, 0x838A, 0x838B, 0x838C, 0x838D, 0x838F, 0x8393, 0x814A, 0x814B,
|
|
};
|
|
#endif
|
|
|
|
// JIS Table
|
|
|
|
// this is the table used to determine whether the kana char is voiced sound markable
|
|
// if it is, what is the combined full width kana.
|
|
static WCHAR g_wVoiceMarkKana[48] =
|
|
{
|
|
/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, */
|
|
|
|
/* a0-af */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2574, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
|
/* b0-bf */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x252c, 0x252e, 0x2530, 0x2532, 0x2534, 0x2536, 0x2538, 0x253A, 0x253C, 0x253E,
|
|
/* c0-cf */ 0x2540, 0x2542, 0x2545, 0x2547, 0x2549, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2550, 0x2553, 0x2556, 0x2559, 0x255C, 0x0,
|
|
|
|
};
|
|
|
|
// special voiced sound mark '0xde' conversion
|
|
static WCHAR g_wMarkDEKana[16] =
|
|
{
|
|
/* c8-cf */ 0x0, 0x0, 0x2550, 0x2553, 0x2556, 0x2559, 0x255C, 0x0,
|
|
};
|
|
|
|
// special voiced sound mark '0xdf' conversion
|
|
static WCHAR g_wMarkDFKana[16] =
|
|
{
|
|
/* c8-cf */ 0x0, 0x0, 0x2551, 0x2554, 0x2557, 0x255A, 0x255D, 0x0,
|
|
};
|
|
|
|
// this is the table used to convert half width kana to full width kana
|
|
static WCHAR g_wFullWKana[64] =
|
|
{
|
|
/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, */
|
|
|
|
/* a0-af */ 0x0, 0x2123, 0x2156, 0x2157, 0x2122, 0x2126, 0x2572, 0x2521, 0x2523, 0x2525, 0x2527, 0x2529, 0x2563, 0x2565, 0x2567, 0x2543,
|
|
/* b0-bf */ 0x213C, 0x2522, 0x2524, 0x2526, 0x2528, 0x252A, 0x252B, 0x252D, 0x252f, 0x2531, 0x2533, 0x2535, 0x2537, 0x2539, 0x253B, 0x253D,
|
|
/* c0-cf */ 0x253F, 0x2541, 0x2544, 0x2546, 0x2548, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F, 0x2552, 0x2555, 0x2558, 0x255B, 0x255E,
|
|
/* d0-df */ 0x255F, 0x2560, 0x2561, 0x2562, 0x2564, 0x2566, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256F, 0x2573, 0x212B, 0x212C,
|
|
};
|
|
|
|
/******************************************************************************
|
|
************************** C O N S T R U C T O R **************************
|
|
******************************************************************************/
|
|
|
|
CInccJisOut::CInccJisOut(UINT uCodePage, int nCodeSet, DWORD dwFlag, WCHAR *lpFallBack) : CINetCodeConverter(uCodePage, nCodeSet)
|
|
{
|
|
m_dwFlag = dwFlag;
|
|
// Per Office team's request, we should disable BESTFITCHARS feature for now.
|
|
m_dwFlag &= ~MLCONVCHARF_NOBESTFITCHARS;
|
|
m_lpFallBack = lpFallBack;
|
|
Reset(); // initialization
|
|
return ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
******************************* R E S E T *********************************
|
|
******************************************************************************/
|
|
|
|
void CInccJisOut::Reset()
|
|
{
|
|
m_fDoubleByte = FALSE;
|
|
m_fKana = FALSE;
|
|
m_fJapan = FALSE;
|
|
m_fSaveByte = FALSE;
|
|
m_tcLeadByte = 0 ;
|
|
m_tcPrevByte = 0 ;
|
|
m_eKanaMode = SIO_MODE ;
|
|
return ;
|
|
}
|
|
|
|
/******************************************************************************
|
|
************************* C O N V E R T C H A R *************************
|
|
******************************************************************************/
|
|
|
|
HRESULT CInccJisOut::ConvertChar(UCHAR tc, int cchSrc)
|
|
{
|
|
BOOL fDone = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_fDoubleByte) {
|
|
if ((tc >= 0x81 && tc <= 0x9f) || (tc >= 0xe0 && tc <= 0xfc )) {
|
|
// Switch to Double Byte Code
|
|
if (m_fKana) {
|
|
if ( SIO_MODE == m_eKanaMode )
|
|
fDone = Output(SI);
|
|
else if ( (FULL_MODE == m_eKanaMode) && !(m_dwFlag & MLCONVCHARF_NOBESTFITCHARS))
|
|
{
|
|
fDone = KanaCleanUp();
|
|
m_fJapan = TRUE; // in FULL mode, Kana are bouble byte code too.
|
|
}
|
|
m_fKana = FALSE;
|
|
}
|
|
if (!m_fJapan) {
|
|
(void)Output(ESC); // ESC $ B - JIS-83
|
|
(void)Output(ISO2022_IN_CHAR);
|
|
fDone = Output(ISO2022_IN_JP_CHAR1);
|
|
m_fJapan = TRUE;
|
|
}
|
|
m_fDoubleByte = TRUE;
|
|
m_tcLeadByte = tc;
|
|
} else if (tc >= 0xa1 && tc <= 0xdf) {
|
|
// Single Byte Katakana Code
|
|
if (m_fJapan) {
|
|
if ( (FULL_MODE == m_eKanaMode) && !(m_dwFlag & MLCONVCHARF_NOBESTFITCHARS))
|
|
m_fKana = TRUE; // no mode changing
|
|
else if ( (SIO_MODE == m_eKanaMode) || (FULL_MODE == m_eKanaMode))
|
|
{
|
|
(void)Output(ESC); // ESC ( B - ACSII
|
|
(void)Output(ISO2022_OUT_CHAR);
|
|
fDone = Output(ISO2022_OUT_JP_CHAR1);
|
|
}
|
|
m_fJapan = FALSE;
|
|
}
|
|
if (!m_fKana) {
|
|
switch ( m_eKanaMode )
|
|
{
|
|
case SIO_MODE :
|
|
fDone = Output(SO);
|
|
break ;
|
|
case ESC_MODE :
|
|
(void)Output(ESC); // ESC ( I - Kana mode
|
|
(void)Output(ISO2022_OUT_CHAR);
|
|
fDone = Output(ISO2022_OUT_JP_CHAR3);
|
|
break ;
|
|
case FULL_MODE :
|
|
// Don't switch if NO_BEST_FIT_CHAR
|
|
if (!(m_dwFlag & MLCONVCHARF_NOBESTFITCHARS))
|
|
{
|
|
(void)Output(ESC); // ESC $ B - JIS 83
|
|
(void)Output(ISO2022_IN_CHAR);
|
|
fDone = Output(ISO2022_IN_JP_CHAR1);
|
|
}
|
|
break;
|
|
|
|
}
|
|
m_fKana = TRUE;
|
|
}
|
|
if ( FULL_MODE == m_eKanaMode )
|
|
{
|
|
hr = ConvFullWidthKana(tc);
|
|
if (SUCCEEDED(hr))
|
|
fDone = TRUE;
|
|
else
|
|
fDone = FALSE;
|
|
}
|
|
else
|
|
fDone = Output(tc & 0x7f);
|
|
} else {
|
|
// Single Byte Code
|
|
if (m_fKana) {
|
|
if ( SIO_MODE == m_eKanaMode )
|
|
fDone = Output(SI);
|
|
else {
|
|
if ( FULL_MODE == m_eKanaMode )
|
|
fDone = KanaCleanUp();
|
|
(void)Output(ESC); // ESC ( B - ACSII
|
|
(void)Output(ISO2022_OUT_CHAR);
|
|
fDone = Output(ISO2022_OUT_JP_CHAR1);
|
|
}
|
|
m_fKana = FALSE;
|
|
}
|
|
if (m_fJapan) {
|
|
(void)Output(ESC); // ESC ( B - ACSII
|
|
(void)Output(ISO2022_OUT_CHAR);
|
|
fDone = Output(ISO2022_OUT_JP_CHAR1);
|
|
m_fJapan = FALSE;
|
|
}
|
|
fDone = Output(tc);
|
|
}
|
|
} else {
|
|
|
|
// map extended char (0xfa40-0xfc4b) to a special range
|
|
if (m_tcLeadByte >= 0xfa && m_tcLeadByte <= 0xfc && tc >= 0x40 )
|
|
{
|
|
WCHAR wcDBCS ;
|
|
|
|
wcDBCS = ((WCHAR) m_tcLeadByte ) << 8 | tc ;
|
|
|
|
if ( wcDBCS >= 0xfa40 && wcDBCS <= 0xfa5b )
|
|
{
|
|
if ( wcDBCS <= 0xfa49 )
|
|
wcDBCS = wcDBCS - 0x0b51 ;
|
|
else if ( wcDBCS >= 0xfa4a && wcDBCS <= 0xfa53 )
|
|
wcDBCS = wcDBCS - 0x072f6 ;
|
|
else if ( wcDBCS >= 0xfa54 && wcDBCS <= 0xfa57 )
|
|
wcDBCS = wcDBCS - 0x0b5b ;
|
|
else if ( wcDBCS == 0xfa58 )
|
|
wcDBCS = 0x878a ;
|
|
else if ( wcDBCS == 0xfa59 )
|
|
wcDBCS = 0x8782 ;
|
|
else if ( wcDBCS == 0xfa5a )
|
|
wcDBCS = 0x8784 ;
|
|
else if ( wcDBCS == 0xfa5b )
|
|
wcDBCS = 0x879a ;
|
|
}
|
|
else if ( wcDBCS >= 0xfa5c && wcDBCS <= 0xfc4b )
|
|
{
|
|
if ( tc < 0x5c )
|
|
wcDBCS = wcDBCS - 0x0d5f;
|
|
else if ( tc >= 0x80 && tc <= 0x9B )
|
|
wcDBCS = wcDBCS - 0x0d1d;
|
|
else
|
|
wcDBCS = wcDBCS - 0x0d1c;
|
|
}
|
|
tc = (UCHAR) wcDBCS ;
|
|
m_tcLeadByte = (UCHAR) ( wcDBCS >> 8 ) ;
|
|
}
|
|
|
|
// Convert Double Byte Code
|
|
m_tcLeadByte -= ((m_tcLeadByte > 0x9f) ? 0xb1 : 0x71);
|
|
m_tcLeadByte = m_tcLeadByte * 2 + 1;
|
|
if (tc > 0x9e) {
|
|
tc -= 0x7e;
|
|
m_tcLeadByte++;
|
|
} else {
|
|
if (tc > 0x7e)
|
|
tc--;
|
|
tc -= 0x1f;
|
|
}
|
|
(void)Output(m_tcLeadByte);
|
|
fDone = Output(tc);
|
|
m_fDoubleByte = FALSE;
|
|
m_tcLeadByte = 0 ;
|
|
}
|
|
|
|
if (fDone)
|
|
return hr;
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
/******************************************************************************
|
|
***************************** C L E A N U P *****************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisOut::CleanUp()
|
|
{
|
|
BOOL fDone = TRUE;
|
|
|
|
// Discard m_byLeadByte: if (m_fDoubleByte) Output(m_byLeadByte);
|
|
|
|
fDone = KanaCleanUp();
|
|
|
|
if (m_fKana)
|
|
{
|
|
if ( SIO_MODE == m_eKanaMode )
|
|
fDone = Output(SI);
|
|
else if (!(m_dwFlag & MLCONVCHARF_NOBESTFITCHARS)) // FULL mode and ESC mode
|
|
{
|
|
(void)Output(ESC); // ESC ( B - ASCII
|
|
(void)Output(ISO2022_OUT_CHAR);
|
|
fDone = Output(ISO2022_OUT_JP_CHAR1);
|
|
}
|
|
m_fKana = FALSE ;
|
|
}
|
|
|
|
if (m_fJapan) {
|
|
(void)Output(ESC); // ESC ( B - ASCII
|
|
(void)Output(ISO2022_OUT_CHAR);
|
|
fDone = Output(ISO2022_OUT_JP_CHAR1);
|
|
m_fJapan = FALSE ;
|
|
}
|
|
|
|
return fDone;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
************************* C O N V E R T C H A R *************************
|
|
******************************************************************************/
|
|
|
|
HRESULT CInccJisOut::ConvFullWidthKana(UCHAR tc)
|
|
{
|
|
BOOL fDone = TRUE ;
|
|
int index ;
|
|
WCHAR DoubleBytes ;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (m_dwFlag & MLCONVCHARF_NOBESTFITCHARS)
|
|
{
|
|
UCHAR szDefaultChar[3] = {0x3f}; // possible DBCS + null
|
|
|
|
if (m_lpFallBack && (m_dwFlag & MLCONVCHARF_USEDEFCHAR))
|
|
{
|
|
// only take SBCS, no DBCS character
|
|
if ( 1 != WideCharToMultiByte(CP_JPN_SJ, 0,
|
|
(LPCWSTR)m_lpFallBack, 1,
|
|
(LPSTR)szDefaultChar, ARRAYSIZE(szDefaultChar), NULL, NULL ))
|
|
szDefaultChar[0] = 0x3f;
|
|
}
|
|
|
|
if (m_dwFlag & (MLCONVCHARF_NCR_ENTITIZE|MLCONVCHARF_NAME_ENTITIZE))
|
|
{
|
|
char szChar[2] = {0};
|
|
char szDstStr[10] = {0};
|
|
WCHAR szwChar[2];
|
|
int cCount;
|
|
|
|
szChar[0] = tc;
|
|
|
|
if (MultiByteToWideChar(CP_JPN_SJ, 0, szChar, -1, szwChar, ARRAYSIZE(szwChar)))
|
|
{
|
|
// Output NCR entity
|
|
Output('&');
|
|
Output('#');
|
|
_ultoa((unsigned long)szwChar[0], (char*)szDstStr, 10);
|
|
cCount = lstrlenA(szDstStr);
|
|
for (int i=0; i< cCount; i++)
|
|
{
|
|
Output(szDstStr[i]);
|
|
}
|
|
fDone = Output(';');
|
|
}
|
|
else
|
|
{
|
|
fDone = Output(szDefaultChar[0]); // use default char
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fDone = Output(szDefaultChar[0]); // use default char
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// voiced sound mark or semi-voiced sound mark
|
|
if ( m_fSaveByte && ( tc == 0xde || tc == 0xdf ) )
|
|
{
|
|
if ( m_tcPrevByte >= 0x0CA && m_tcPrevByte <= 0x0CE )
|
|
{
|
|
index = m_tcPrevByte - VOICE_MARK_DEDF_OFFSET ;
|
|
|
|
if ( tc == 0xde )
|
|
DoubleBytes = g_wMarkDEKana[index] ;
|
|
else
|
|
DoubleBytes = g_wMarkDFKana[index] ;
|
|
|
|
Output( (UCHAR) (DoubleBytes >> 8 ));
|
|
fDone = Output( (UCHAR) DoubleBytes );
|
|
m_fSaveByte = FALSE ;
|
|
m_tcPrevByte = '\0' ;
|
|
}
|
|
else
|
|
{
|
|
index = m_tcPrevByte - VOICE_MARK_OFFSET ;
|
|
|
|
// Invalid trail byte could cause buffer overrun, skip it
|
|
if (index < ARRAYSIZE(g_wVoiceMarkKana))
|
|
{
|
|
DoubleBytes = g_wVoiceMarkKana[index] ;
|
|
Output( (UCHAR) (DoubleBytes >> 8 ));
|
|
fDone = Output( (UCHAR) DoubleBytes );
|
|
m_fSaveByte = FALSE ;
|
|
m_tcPrevByte = '\0' ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
// output previous saved voice sound markable char
|
|
if ( m_fSaveByte )
|
|
{
|
|
index = m_tcPrevByte - VOICE_MARK_OFFSET ;
|
|
DoubleBytes = g_wFullWKana[index] ;
|
|
Output( (UCHAR) (DoubleBytes >> 8 ) );
|
|
fDone = Output( (UCHAR) DoubleBytes );
|
|
m_fSaveByte = FALSE ;
|
|
m_tcPrevByte = '\0' ;
|
|
}
|
|
|
|
// half width kana
|
|
if ( tc >= 0xa1 && tc <= 0xdf )
|
|
{
|
|
index = tc - VOICE_MARK_OFFSET ;
|
|
// check if this char can be combined with voice sound mark
|
|
if ( index < ARRAYSIZE(g_wVoiceMarkKana) && g_wVoiceMarkKana[index] )
|
|
{
|
|
m_fSaveByte = TRUE ;
|
|
m_tcPrevByte = tc ;
|
|
}
|
|
// convert half width kana to full width kana
|
|
else
|
|
{
|
|
DoubleBytes = g_wFullWKana[index] ;
|
|
Output( (UCHAR) ( DoubleBytes >> 8 ));
|
|
fDone = Output( (UCHAR) DoubleBytes );
|
|
}
|
|
}
|
|
else
|
|
fDone = Output(tc);
|
|
}
|
|
}
|
|
|
|
if (fDone)
|
|
return hr;
|
|
else
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
*************************** K A N A C L E A N U P ************************
|
|
******************************************************************************/
|
|
|
|
BOOL CInccJisOut::KanaCleanUp()
|
|
{
|
|
BOOL fDone = TRUE;
|
|
WCHAR DoubleBytes ;
|
|
int index ;
|
|
|
|
// output previous saved voice sound markable char
|
|
if ( m_fSaveByte )
|
|
{
|
|
index = m_tcPrevByte - VOICE_MARK_OFFSET ;
|
|
DoubleBytes = g_wFullWKana[index] ;
|
|
Output( (UCHAR) ( DoubleBytes >> 8 ));
|
|
fDone = Output( (UCHAR) DoubleBytes );
|
|
m_fSaveByte = FALSE ;
|
|
m_tcPrevByte = '\0' ;
|
|
}
|
|
|
|
return fDone;
|
|
}
|
|
|
|
int CInccJisOut::GetUnconvertBytes()
|
|
{
|
|
if ( m_tcLeadByte )
|
|
return 1 ;
|
|
else
|
|
return 0 ;
|
|
}
|
|
|
|
DWORD CInccJisOut::GetConvertMode()
|
|
{
|
|
return ( m_fJapan ? 1 : 0 ) + ( m_fKana ? 2 : 0 ) ;
|
|
}
|
|
|
|
void CInccJisOut::SetConvertMode(DWORD mode)
|
|
{
|
|
Reset();
|
|
if ( mode & 0x00000001 )
|
|
m_fJapan = TRUE ;
|
|
if ( mode & 0x00000002 )
|
|
m_fKana = TRUE ;
|
|
return ;
|
|
}
|
|
|
|
void CInccJisOut::SetKanaMode(UINT uCodePage)
|
|
{
|
|
switch ( uCodePage )
|
|
{
|
|
case CP_ISO_2022_JP_ESC:
|
|
m_eKanaMode = ESC_MODE ;
|
|
break ;
|
|
case CP_ISO_2022_JP_SIO:
|
|
m_eKanaMode = SIO_MODE ;
|
|
break ;
|
|
default :
|
|
m_eKanaMode = FULL_MODE ;
|
|
break ;
|
|
}
|
|
return ;
|
|
}
|