windows-nt/Source/XPSP1/NT/windows/feime/kor/hatmt.c
2020-09-26 16:20:57 +08:00

1132 lines
32 KiB
C

/******************************************************************************
*
* File Name: hatmt.c
*
* - HangeulAutomata of IME for Chicago-H.
*
* Author: Beomseok Oh (BeomOh)
*
* Copyright (C) Microsoft Corp 1993-1994. All rights reserved.
*
******************************************************************************/
#include "precomp.h"
extern DWORD gdwSystemInfoFlags;
BOOL HangeulAutomata(BYTE bCode, LPDWORD lpdwTransKey, LPCOMPOSITIONSTRING lpCompStr)
{
BYTE bKind;
BOOL fOpen = FALSE;
if (bCode > 0xE0) bKind = JongSung;
else if (bCode > 0xC0) bKind = ChoSung;
else if (bCode > 0xA0) bKind = MoEum;
else if (bCode > 0x80) bKind = JaEum;
else if (bCode == 0x80) // For Backspace handling.
{
if (fCurrentCompDel == FALSE)
{
// Simulate CHO state deletion - just clear current interim char.
bState = CHO;
mCho = 0;
}
switch (bState)
{
case JONG :
if (mJong)
{
mJong = 0;
if (!fComplete && uCurrentInputMethod == IDD_2BEOL)
{
Cho1 = Jong2Cho[Jong1];
bState = CHO;
}
break;
}
else if (fComplete)
{
bState = JUNG;
break;
}
// fall through...
case JUNG :
if (mJung)
{
mJung = 0;
break;
}
else if (fComplete)
{
bState = CHO;
fComplete = FALSE;
break;
}
// fall through...
case CHO :
if (mCho)
{
mCho = 0;
break;
}
else
{
lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
// Initialize all Automata Variables.
bState = NUL;
JohabChar.w = WansungChar.w = mCho = mJung = mJong = 0;
fComplete = FALSE;
if (lpdwTransKey)
{
// Send Empty Composition String Clear Message.
lpdwTransKey += iTotalNumMsg*3 + 1;
*lpdwTransKey++ = WM_IME_COMPOSITION;
*lpdwTransKey++ = 0L;
*lpdwTransKey++ = GCS_COMPSTR | GCS_COMPATTR | CS_INSERTCHAR | CS_NOMOVECARET;
// Send Close Composition Window Message.
*lpdwTransKey++ = WM_IME_ENDCOMPOSITION;
*lpdwTransKey++ = 0L;
*lpdwTransKey++ = 0L;
iTotalNumMsg += 2;
}
return TRUE;
}
case NUL :
if (lpdwTransKey)
{
// Put the Backspace message into return buffer.
lpdwTransKey += iTotalNumMsg*3 + 1;
*lpdwTransKey++ = WM_CHAR;
*lpdwTransKey++ = (DWORD)VK_BACK;
*lpdwTransKey++ = VKBACK_LPARAM;
iTotalNumMsg++;
}
return FALSE;
}
MakeInterim(lpCompStr);
// Put the interim character into return buffer.
if (lpdwTransKey)
{
lpdwTransKey += iTotalNumMsg*3 + 1;
*lpdwTransKey++ = WM_IME_COMPOSITION;
*lpdwTransKey++ = (DWORD)WansungChar.w;
*lpdwTransKey++ = GCS_COMPSTR | GCS_COMPATTR | CS_INSERTCHAR | CS_NOMOVECARET;
iTotalNumMsg++;
}
return TRUE;
}
else bKind = Wrong;
bCode &= 0x1F; // Mask out for Component code
switch (bState)
{
case NUL :
switch (bKind)
{
case JaEum :
case ChoSung :
Cho1 = bCode;
bState = CHO;
break;
case MoEum :
Cho1 = CFILL;
Jung1 = bCode;
bState = JUNG;
break;
case JongSung :
Cho1 = CFILL;
Jung1 = VFILL;
Jong1 = bCode;
bState = JONG;
break;
}
MakeInterim(lpCompStr);
fOpen = TRUE;
break;
case CHO :
switch (bKind)
{
case JaEum :
Jong1 = Cho2Jong[Cho1];
if (CheckMJong(Cho2Jong[bCode]))
{
Cho1 = CFILL;
Jung1 = VFILL;
Jong2 = Cho2Jong[bCode];
bState = JONG;
}
else
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
}
break;
case MoEum :
Jung1 = bCode;
bState = JUNG;
fComplete = TRUE;
break;
case ChoSung :
if (!mCho && CheckMCho(bCode))
{
Cho2 = bCode;
}
else
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
}
break;
case JongSung :
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = VFILL;
Jong1 = bCode;
bState = JONG;
break;
}
if (!MakeInterim(lpCompStr))// Check whether can be WANSUNG code.
{ // For MoEum case only.
bState = CHO; // Other case can NOT fall in here.
fComplete = FALSE;
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = bCode;
bState = JUNG;
MakeInterim(lpCompStr);
}
break;
case JUNG :
switch (bKind)
{
case JaEum :
if (!fComplete)
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
MakeInterim(lpCompStr);
}
else
{
Jong1 = Cho2Jong[bCode];
bState = JONG;
if (!MakeInterim(lpCompStr))
{
bState = JUNG;
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
MakeInterim(lpCompStr);
}
}
break;
case MoEum :
if (!mJung && CheckMJung(bCode))
{
Jung2 = bCode;
if (!MakeInterim(lpCompStr))
{
mJung = 0;
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = bCode;
bState = JUNG;
MakeInterim(lpCompStr);
}
}
else
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = bCode;
bState = JUNG;
MakeInterim(lpCompStr);
}
break;
case ChoSung :
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
MakeInterim(lpCompStr);
break;
case JongSung :
if (!fComplete)
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = VFILL;
Jong1 = bCode;
bState = JONG;
MakeInterim(lpCompStr);
}
else
{
Jong1 = bCode;
bState = JONG;
if (!MakeInterim(lpCompStr))
{
bState = JUNG;
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = VFILL;
Jong1 = bCode;
bState = JONG;
MakeInterim(lpCompStr);
}
}
break;
}
break;
case JONG :
switch (bKind)
{
case JaEum :
if (!mJong && CheckMJong(Cho2Jong[bCode]))
{
Jong2 = Cho2Jong[bCode];
if (!MakeInterim(lpCompStr))
{
mJong = 0;
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
MakeInterim(lpCompStr);
}
}
else
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
MakeInterim(lpCompStr);
}
break;
case MoEum :
if (uCurrentInputMethod == IDD_2BEOL)
{
JOHAB tmpJohab;
WORD tmpWansung;
BOOL tmpfComplete;
tmpJohab.h.flag = 1;
tmpJohab.h.cho = (mJong)? Jong2Cho[Jong2]: Jong2Cho[Jong1];
tmpJohab.h.jung = bCode;
tmpJohab.h.jong = CFILL;
tmpfComplete = fComplete;
fComplete = TRUE;
#ifdef JOHAB_IME
tmpWansung = tmpJohab.w;
#else
tmpWansung = Johab2Wansung(tmpJohab.w);
#endif
fComplete = tmpfComplete;
if (!tmpWansung)
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = bCode;
bState = JUNG;
}
else
{
MakeFinal(TRUE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = (mJong)? Jong2Cho[Jong2]: Jong2Cho[Jong1];
Jung1 = bCode;
fComplete = TRUE;
bState = JUNG;
mJong = 0;
}
}
else
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = bCode;
bState = JUNG;
}
MakeInterim(lpCompStr);
break;
case ChoSung :
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = bCode;
bState = CHO;
MakeInterim(lpCompStr);
break;
case JongSung :
if (!mJong && CheckMJong(bCode))
{
Jong2 = bCode;
if (!MakeInterim(lpCompStr))
{
mJong = 0;
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = VFILL;
Jong1 = bCode;
bState = JONG;
MakeInterim(lpCompStr);
}
}
else
{
MakeFinal(FALSE, lpdwTransKey, FALSE, lpCompStr);
Cho1 = CFILL;
Jung1 = VFILL;
Jong1 = bCode;
bState = JONG;
MakeInterim(lpCompStr);
}
break;
}
break;
}
if (lpdwTransKey)
{
lpdwTransKey += iTotalNumMsg*3 + 1;
if (fOpen)
{
// Send Open Composition Window Message.
*lpdwTransKey++ = WM_IME_STARTCOMPOSITION;
*lpdwTransKey++ = 0L;
*lpdwTransKey++ = 0L;
iTotalNumMsg++;
}
// Put the interim character into return buffer.
*lpdwTransKey++ = WM_IME_COMPOSITION;
*lpdwTransKey++ = (DWORD)WansungChar.w;
*lpdwTransKey++ = GCS_COMPSTR | GCS_COMPATTR | CS_INSERTCHAR | CS_NOMOVECARET;
iTotalNumMsg++;
}
return FALSE;
}
BOOL MakeInterim(LPCOMPOSITIONSTRING lpCompStr)
{
JohabChar.h.flag = 1;
JohabChar.h.cho = (mCho)? mCho: Cho1;
switch (bState)
{
case CHO :
JohabChar.h.jung = VFILL;
JohabChar.h.jong = CFILL;
break;
case JUNG :
JohabChar.h.jung = (mJung)? mJung: Jung1;
JohabChar.h.jong = CFILL;
break;
case JONG :
JohabChar.h.jung = (mJung)? mJung: Jung1;
JohabChar.h.jong = (mJong)? mJong: Jong1;
break;
}
#ifdef JOHAB_IME
WansungChar.w = JohabChar.w;
#else
WansungChar.w = Johab2Wansung(JohabChar.w);
#endif
if (WansungChar.w)
{
// Update IME Context.
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = WansungChar.e.high;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = WansungChar.e.low;
lpCompStr->dwCompStrLen = 2;
// AttrLen should be 2.
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
lpCompStr->dwCompAttrLen = 2;
return TRUE;
}
else
return FALSE;
}
void MakeFinal(BOOL bCount, LPDWORD lpdwTransKey, BOOL fClose, LPCOMPOSITIONSTRING lpCompStr)
{
if (bCount == TRUE)
if (mJong)
if (fComplete)
{
mJong = 0;
MakeInterim(lpCompStr);
mJong = 1;
}
else
{
Cho1 = Jong2Cho[Jong1];
bState = CHO;
MakeInterim(lpCompStr);
}
else
{
bState = JUNG;
MakeInterim(lpCompStr);
}
else
{
if (!WansungChar.w)
MakeInterim(lpCompStr);
mJong = 0;
}
if (lpdwTransKey)
{
lpdwTransKey += iTotalNumMsg*3 + 1;
if (fClose)
{
// Send Close Composition Window Message.
*lpdwTransKey++ = WM_IME_ENDCOMPOSITION;
*lpdwTransKey++ = 0L;
*lpdwTransKey++ = 0L;
iTotalNumMsg++;
}
// Put the finalized character into return buffer.
*lpdwTransKey++ = WM_IME_COMPOSITION;
*lpdwTransKey++ = (DWORD)WansungChar.w;
*lpdwTransKey++ = GCS_RESULTSTR;
iTotalNumMsg++;
}
// Update IME Context.
lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset) = WansungChar.e.high;
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 1) = WansungChar.e.low;
lpCompStr->dwResultStrLen = 2;
// add a null terminator
*(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + sizeof(WCHAR)) = '\0';
// Initialize all Automata Variables.
bState = NUL;
JohabChar.w = WansungChar.w = mCho = mJung = 0;
fComplete = FALSE;
}
void MakeFinalMsgBuf(HIMC hIMC, WPARAM VKey)
{
LPINPUTCONTEXT lpIMC;
LPCOMPOSITIONSTRING lpCompStr;
LPDWORD lpdwMsgBuf;
lpIMC = ImmLockIMC(hIMC);
if (lpIMC == NULL)
return;
lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
if (lpCompStr == NULL) {
ImmUnlockIMC(hIMC);
return;
}
if (!WansungChar.w)
MakeInterim(lpCompStr);
mJong = 0;
// Put the finalized character into return buffer.
lpIMC->dwNumMsgBuf = (VKey)? 3: 2;
lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, sizeof(DWORD)*3 * lpIMC->dwNumMsgBuf);
lpdwMsgBuf = (LPDWORD)ImmLockIMCC(lpIMC->hMsgBuf);
*lpdwMsgBuf++ = WM_IME_ENDCOMPOSITION;
*lpdwMsgBuf++ = 0L;
*lpdwMsgBuf++ = 0L;
*lpdwMsgBuf++ = WM_IME_COMPOSITION;
*lpdwMsgBuf++ = (DWORD)WansungChar.w;
*lpdwMsgBuf++ = GCS_RESULTSTR;
if (VKey)
{
*lpdwMsgBuf++ = WM_IME_KEYDOWN;
*lpdwMsgBuf++ = VKey;
*lpdwMsgBuf++ = 1L;
}
ImmUnlockIMCC(lpIMC->hMsgBuf);
// Update IME Context.
lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset) = WansungChar.e.high;
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 1) = WansungChar.e.low;
lpCompStr->dwResultStrLen = 2;
// add a null terminator
*(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + sizeof(WCHAR)) = '\0';
ImmUnlockIMCC(lpIMC->hCompStr);
ImmUnlockIMC(hIMC);
ImmGenerateMessage(hIMC);
// Initialize all Automata Variables.
bState = NUL;
JohabChar.w = WansungChar.w = mCho = mJung = 0;
fComplete = FALSE;
}
void Banja2Junja(BYTE bChar, LPDWORD lpdwTransKey, LPCOMPOSITIONSTRING lpCompStr)
{
if (bChar == ' ')
#ifdef JOHAB_IME
WansungChar.w = 0xD931;
#else
WansungChar.w = 0xA1A1;
#endif
else if (bChar == '~')
#ifdef JOHAB_IME
WansungChar.w = 0xD9A6;
#else
WansungChar.w = 0xA2A6;
#endif
else
{
#ifdef JOHAB_IME
WansungChar.e.high = 0xDA;
WansungChar.e.low = bChar + (BYTE)((bChar <= 'n')? 0x10: 0x22);
#else
WansungChar.e.high = 0xA3;
WansungChar.e.low = bChar + (BYTE)0x80;
#endif
}
// Update IME Context.
lpCompStr->dwCompStrLen = lpCompStr->dwCompAttrLen = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompAttrOffset + 1) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset) = 0;
*((LPSTR)lpCompStr + lpCompStr->dwCompStrOffset + 1) = 0;
if (lpCompStr->dwResultStrLen)
{
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 2) = WansungChar.e.high;
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 3) = WansungChar.e.low;
// add a null terminator
*(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 2 + sizeof(WCHAR)) = '\0';
}
else
{
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset) = WansungChar.e.high;
*((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + 1) = WansungChar.e.low;
// add a null terminator
*(LPTSTR)((LPSTR)lpCompStr + lpCompStr->dwResultStrOffset + sizeof(WCHAR)) = '\0';
if (lpdwTransKey)
{
// Put the finalized character into return buffer.
lpdwTransKey += iTotalNumMsg*3 + 1;
*lpdwTransKey++ = WM_IME_COMPOSITION;
*lpdwTransKey++ = (DWORD)WansungChar.w;
*lpdwTransKey++ = GCS_RESULTSTR;
iTotalNumMsg++;
}
}
lpCompStr->dwResultStrLen += 2;
}
BOOL CheckMCho(BYTE bCode)
{
int i;
if (Cho1 != bCode)
return FALSE;
for (i = 0; i < 5; i++)
if (rgbMChoTbl[i][0] == Cho1 && rgbMChoTbl[i][1] == bCode)
{
mCho = rgbMChoTbl[i][2];
return TRUE;
}
return FALSE;
}
BOOL CheckMJung(BYTE bCode)
{
int i;
for (i = 0; i < 7; i++)
if (rgbMJungTbl[i][0] == Jung1 && rgbMJungTbl[i][1] == bCode)
{
mJung = rgbMJungTbl[i][2];
return TRUE;
}
return FALSE;
}
BOOL CheckMJong(BYTE bCode)
{
int i;
if (uCurrentInputMethod == IDD_2BEOL && Jong1 == bCode)
return FALSE;
for (i = 0; i < 13; i++)
if (rgbMJongTbl[i][0] == Jong1 && rgbMJongTbl[i][1] == bCode)
{
mJong = rgbMJongTbl[i][2];
return TRUE;
}
return FALSE;
}
#ifndef JOHAB_IME
#ifdef XWANSUNG_IME
BOOL IsPossibleToUseUHC()
{
/*
* No UHC support for 16-bits app.
*/
return (gdwSystemInfoFlags & IME_SYSINFO_WOW16) == 0;
}
BOOL UseXWansung(void)
{
#ifdef LATER
DWORD idProcess;
idProcess = GetCurrentProcessId();
if ((fCurrentUseXW && (!(GetProcessDword(idProcess, GPD_FLAGS) & GPF_WIN16_PROCESS)
|| (GetProcessDword(idProcess, GPD_EXP_WINVER) >= 0x0400)))
|| (IMECOMPAT_USEXWANSUNG & ImmGetAppIMECompatFlags(0L)))
#else
if ( fCurrentUseXW && IsPossibleToUseUHC())
#endif
return TRUE;
else
return FALSE;
}
//
// iXWType array is 8x3 matrix of Lead for Row, Tail for Column
//
static BYTE iXWType[8][3] =
{
XWT_EXTENDED, XWT_EXTENDED, XWT_EXTENDED, // Lead = 0x81-0xA0
XWT_EXTENDED, XWT_EXTENDED, XWT_JUNJA, // Lead = 0xA1-0xAC
XWT_EXTENDED, XWT_EXTENDED, XWT_INVALID, // Lead = 0xAD-0xAF
XWT_EXTENDED, XWT_EXTENDED, XWT_WANSUNG, // Lead = 0xB0-0xC5
XWT_EXTENDED, XWT_INVALID, XWT_WANSUNG, // Lead = 0xC6
XWT_INVALID, XWT_INVALID, XWT_WANSUNG, // Lead = 0xC7-0xC8
XWT_INVALID, XWT_INVALID, XWT_UDC, // Lead = 0xC9, 0xFE
XWT_INVALID, XWT_INVALID, XWT_HANJA // Lead = 0xCA-0xFD
};
int GetXWType( WORD wXW )
{
BYTE bL = ( wXW >> 8 ) & 0xFF;
BYTE bT = wXW & 0xFF;
int iLType = -1, iTType = -1;
if ( ( bT >= 0x41 ) && ( bT <= 0xFE ) )
{
if ( bT <= 0x52 )
iTType = 0; // Tail Range 0x41-0x52
else
{
if ( bT >= 0xA1 )
iTType = 2; // Tail Range 0xA1-0xFE
else if ( ( bT <= 0x5A ) || ( bT >= 0x81 ) ||
( ( bT >= 0x61 ) && ( bT <= 0x7A ) ) )
iTType = 1; // Tail Range 0x53-0x5A, 0x61-0x7A, 0x81-0xA0
}
}
if ( iTType < 0 ) return( -1 );
if ( ( bL >= 0x81 ) && ( bL <= 0xFE ) )
{
if ( bL < 0xB0 )
{
if ( bL <= 0xA0 )
iLType = 0; // Lead Range 0x81-0xA0
else if ( bL <= 0xAC )
iLType = 1; // Lead Range 0xA1-0xAC
else
iLType = 2; // Lead Range 0xAD-0xAF
}
else
{
if ( bL <= 0xC8 )
{
if ( bL < 0xC6 )
iLType = 3; // Lead Range 0xB0-0xC5
else if ( bL == 0xC6 )
iLType = 4; // Lead Range 0xC6
else
iLType = 5; // Lead Range 0xC7-0xC8
}
else
{
if ( ( bL == 0xC9 ) || ( bL == 0xFE ) )
iLType = 6; // Lead Range 0xC9, 0xFE
else
iLType = 7; // Lead Range 0xCA-0xFD
}
}
}
return( ( iLType < 0 ) ? -1 : iXWType[iLType][iTType] );
}
WORD ConvXW2J( WORD wXW )
{
const WORD *pTF;
int iTO;
BYTE bL, bT;
switch ( GetXWType( wXW ) )
{
case XWT_EXTENDED :
bL = ( ( wXW >> 8 ) & 0xFF ) - 0x81;
bT = wXW & 0xFF;
if ( ( bT -= 0x41 ) > 0x19 )
if ( ( bT -= 6 ) > 0x33 )
bT -= 6;
iTO = bT + iTailOffX[bL];
pTF = iTailFirstX + ( bL = iLeadMapX[bL] );
break;
case XWT_WANSUNG :
bL = ( ( wXW >> 8 ) & 0xFF ) - 0xB0;
iTO = ( wXW & 0xFF ) - 0xA1 + iTailOff[bL];
pTF = iTailFirst + ( bL = iLeadMap[bL] );
break;
default:
return( 0 );
}
iTO += *pTF++;
while ( iTO >= *pTF++ ) bL++;
return( (WORD) ( bL + 0x88 ) * 256 + bTailTable[iTO] );
}
static int BinarySearch( WORD wJ, const WORD iTF[] )
{
int iL;
BYTE bT;
int iStart, iEnd, iMiddle;
iL = ( ( wJ >> 8 ) & 0xFF ) - 0x88;
bT = wJ & 0xFF;
iStart = iTF[iL];
iEnd = iTF[iL+1] - 1;
while ( iStart <= iEnd )
{
iMiddle = ( iStart + iEnd ) / 2;
if ( bT == bTailTable[iMiddle] )
return( iMiddle );
else if ( bT < bTailTable[iMiddle] )
iEnd = iMiddle - 1;
else
iStart = iMiddle + 1;
}
return( -1 );
}
WORD ConvJ2XW( WORD wJ )
{
int iIndex;
BYTE bL, bT;
iIndex = BinarySearch( wJ, iTailFirst );
if ( iIndex < 0 )
{
if (!UseXWansung())
return 0;
iIndex = BinarySearch( wJ, iTailFirstX ) - N_WANSUNG;
if ( iIndex < 5696 )
{
bL = iIndex / 178 + 0x81;
bT = iIndex % 178;
}
else
{
iIndex -= 5696;
bL = iIndex / 84 + 0xA1;
bT = iIndex % 84;
}
if ( ( bT += 0x41 ) > 0x5A )
if ( ( bT += 6 ) > 0x7A )
bT += 6;
return( (WORD) bL * 256 + bT );
}
else
return( ( iIndex / 94 + 0xB0 ) * 256 + ( iIndex % 94 ) + 0xA1 );
}
#endif
WORD Johab2Wansung(WORD wJohab)
{
#ifndef XWANSUNG_IME
int iHead = 0, iTail = 2349, iMid;
#endif
BYTE bCount, bMaxCount;
WORD wWansung;
PWORD pwKSCompCode;
if (fComplete)
{
#ifdef XWANSUNG_IME
wWansung = ConvJ2XW(wJohab);
#else
wWansung = 0;
while (iHead <= iTail && !wWansung)
{
iMid = (iHead + iTail) / 2;
if (wKSCharCode[iMid] > wJohab)
iTail = iMid - 1;
else if (wKSCharCode[iMid] < wJohab)
iHead = iMid + 1;
else
wWansung = ((iMid / 94 + 0xB0) << 8) | (iMid % 94 + 0xA1);
}
#endif
}
else
{
if (bState == JONG)
{ // For 3 Beolsik only.
bMaxCount = 30;
pwKSCompCode = (PWORD)wKSCompCode2;
}
else
{
bMaxCount = 51;
pwKSCompCode = (PWORD)wKSCompCode;
}
for (bCount = 0; pwKSCompCode[bCount] != wJohab
&& bCount < bMaxCount; bCount++)
;
wWansung = (bCount == bMaxCount)? 0: bCount + 0xA4A1;
}
return (wWansung);
}
WORD Wansung2Johab(WORD wWansung)
{
WORD wJohab;
#ifndef XWANSUNG_IME
UINT uLoc;
#endif
if (wWansung >= (WORD)0xA4A1 && wWansung <= (WORD)0xA4D3)
wJohab = wKSCompCode[wWansung - 0xA4A1];
#ifdef XWANSUNG_IME
else
wJohab = ConvXW2J(wWansung);
#else
else if (wWansung >= (WORD)0xB0A1 && wWansung <= (WORD)0xC8FE
&& (wWansung & 0x00FF) != (BYTE)0xFF)
{
uLoc = ((wWansung >> 8) - 176) * 94;
uLoc += (wWansung & 0x00FF) - 161;
wJohab = wKSCharCode[uLoc];
}
else
wJohab = 0;
#endif
return (wJohab);
}
#endif
void Code2Automata(void)
{
int i;
#ifdef JOHAB_IME
JohabChar.w = WansungChar.w;
#else
JohabChar.w = Wansung2Johab(WansungChar.w);
#endif
// Initialize all Automata Variables.
bState = NUL;
Cho1 = Cho2 = Jung1 = Jung2 = Jong1 = Jong2 = 0;
mCho = mJung = mJong = 0;
fComplete = FALSE;
if (JohabChar.w)
{
if (JohabChar.h.cho != CFILL)
{
if (uCurrentInputMethod == IDD_2BEOL)
{
Cho1 = (BYTE)JohabChar.h.cho;
Cho2 = mCho = 0;
}
else
{
for (i = 0; i < 5; i++)
if (rgbMChoTbl[i][2] == JohabChar.h.cho)
{
Cho1 = rgbMChoTbl[i][0];
Cho2 = rgbMChoTbl[i][1];
mCho = rgbMChoTbl[i][2];
break;
}
if (i == 5)
{
Cho1 = (BYTE)JohabChar.h.cho;
Cho2 = mCho = 0;
}
}
fComplete = FALSE;
bState = CHO;
}
else
{
Cho1 = CFILL;
Cho2 = mCho = 0;
}
if (JohabChar.h.jung != VFILL)
{
for (i = 0; i < 7; i++)
if (rgbMJungTbl[i][2] == JohabChar.h.jung)
{
Jung1 = rgbMJungTbl[i][0];
Jung2 = rgbMJungTbl[i][1];
mJung = rgbMJungTbl[i][2];
break;
}
if (i == 7)
{
Jung1 = (BYTE)JohabChar.h.jung;
Jung2 = mJung = 0;
}
if (bState == CHO)
fComplete = TRUE;
bState = JUNG;
}
else
{
Jung1 = VFILL;
Jung2 = mJung = 0;
}
if (JohabChar.h.jong != CFILL)
{
for (i = 0; i < 13; i++)
if (rgbMJongTbl[i][2] == JohabChar.h.jong)
{
if (uCurrentInputMethod == IDD_2BEOL
&& rgbMJongTbl[i][0] == rgbMJongTbl[i][1])
{
Jong1 = (BYTE)JohabChar.h.jong;
Jong2 = mJong = 0;
}
else
{
Jong1 = rgbMJongTbl[i][0];
Jong2 = rgbMJongTbl[i][1];
mJong = rgbMJongTbl[i][2];
}
break;
}
if (i == 13)
{
Jong1 = (BYTE)JohabChar.h.jong;
Jong2 = mJong = 0;
}
if (bState != JUNG)
fComplete = FALSE;
bState = JONG;
}
else
{
Jong1 = CFILL;
Jong2 = mJong = 0;
}
}
}
void UpdateOpenCloseState(HIMC hIMC)
{
LPINPUTCONTEXT lpIMC;
lpIMC = ImmLockIMC(hIMC);
if (lpIMC != NULL) {
if ((lpIMC->fdwConversion & IME_CMODE_HANGEUL) ||
(lpIMC->fdwConversion & IME_CMODE_FULLSHAPE))
ImmSetOpenStatus(hIMC, TRUE);
else
ImmSetOpenStatus(hIMC, FALSE);
ImmUnlockIMC(hIMC);
}
}
int SearchHanjaIndex(WORD wHChar)
{
int iHead = 0, iTail = 490, iMid;
#ifdef JOHAB_IME
while (iHead < 18)
if (wHanjaMap[iHead++] == wHChar)
return (iHead - 1);
#endif
while (iHead <= iTail)
{
iMid = (iHead + iTail) / 2;
if (wHanjaMap[iMid] > wHChar)
iTail = iMid - 1;
else if (wHanjaMap[iMid] < wHChar)
iHead = iMid + 1;
else
return (iMid);
}
return (-1);
}