1132 lines
32 KiB
C
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);
|
||
|
}
|