Leaked source code of windows server 2003
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.
 
 
 
 
 
 

692 lines
21 KiB

/****************************************************************************
IMC.H
Owner: cslim
Copyright (c) 1997-1999 Microsoft Corporation
IME Context abstraction class
History:
21-JUL-1999 cslim Created
*****************************************************************************/
#include "precomp.h"
#include "hanja.h"
#include "imc.h"
#include "debug.h"
/*----------------------------------------------------------------------------
CIMECtx::CIMECtx
Ctor
----------------------------------------------------------------------------*/
CIMECtx::CIMECtx(HIMC hIMC)
{
m_fUnicode = fTrue; // default is UNICODE
m_dwMessageSize = 0;
m_dwCandInfoSize = 0;
// Init Context variables
m_hIMC = hIMC;
m_pIMC = OurImmLockIMC(m_hIMC);
//m_hCandInfo = m_pIMC->hCandInfo;
m_pCandInfo = (LPCANDIDATEINFO)OurImmLockIMCC(GetHCandInfo());
//m_hCompStr = m_pIMC->hCompStr;
InitCompStrStruct();
//m_hMessage = m_pIMC->hMsgBuf;
m_pMessage = (LPTRANSMSG)OurImmLockIMCC(GetHMsgBuf());
// Reset composition info.
ResetComposition();
// Reset candidate infos
m_pCandStr = NULL;
m_rgpCandMeaningStr = NULL;
ResetCandidate();
// Reset GCS flag to zero
ResetGCS();
// initialize message buffer
ResetMessage();
// clear hCompStr
ClearCompositionStrBuffer();
//////////////////////////////////////////////////////////////////////
// initialize Shared memory. If this is only IME in the system
// Shared memory will be created as file mapping object.
//////////////////////////////////////////////////////////////////////
m_pCIMEData = new CIMEData;
DbgAssert(m_pCIMEData != 0);
// Initialize IME shared memory to default value and set reg value if avaliable
// Read registry: Do not call it in the DllMain
if (m_pCIMEData)
{
m_pCIMEData->InitImeData();
}
// Initialize Hangul Automata
//GetAutomata()->InitState();
//////////////////////////////////////////////////////////////////////////
// Create All three IME Automata instances
m_rgpHangulAutomata[KL_2BEOLSIK] = new CHangulAutomata2;
m_rgpHangulAutomata[KL_3BEOLSIK_390] = new CHangulAutomata3;
m_rgpHangulAutomata[KL_3BEOLSIK_FINAL] = new CHangulAutomata3Final;
}
/*----------------------------------------------------------------------------
CIMECtx::CIMECtx
Dtor
----------------------------------------------------------------------------*/
CIMECtx::~CIMECtx()
{
if (m_pCIMEData)
{
delete m_pCIMEData;
m_pCIMEData = NULL;
}
// Release Cand info
if (GetHCandInfo())
OurImmUnlockIMCC(GetHCandInfo());
m_pCandInfo = NULL;
// Release Comp str
if (GetHCompStr())
OurImmUnlockIMCC(GetHCompStr());
m_pCompStr = NULL;
// Release Msg buffer
ResetMessage();
if (GetHMsgBuf())
OurImmUnlockIMCC(GetHMsgBuf());
m_pMessage = NULL;
// Reset hIMC
OurImmUnlockIMC(m_hIMC);
m_pIMC = NULL;
m_hIMC = NULL;
// Free candidate private buffer
if (m_pCandStr)
{
GlobalFree(m_pCandStr);
m_pCandStr = NULL;
}
if (m_rgpCandMeaningStr)
{
ClearCandMeaningArray();
GlobalFree(m_rgpCandMeaningStr);
m_rgpCandMeaningStr = NULL;
}
// delete Automata
for (INT i=0; i<NUM_OF_IME_KL; i++)
if (m_rgpHangulAutomata[i])
delete m_rgpHangulAutomata[i];
}
/*----------------------------------------------------------------------------
CIMECtx::InitCompStrStruct
Initialize and reallocater composition string buffer
----------------------------------------------------------------------------*/
VOID CIMECtx::InitCompStrStruct()
{
INT iAllocSize;
if (m_pIMC == NULL)
return;
// Calc COMPOSITIONSTRING buffer size.
iAllocSize = sizeof(COMPOSITIONSTRING) +
// composition string plus NULL terminator
nMaxCompStrLen * sizeof(WCHAR) + sizeof(WCHAR) +
// composition attribute
nMaxCompStrLen * sizeof(WORD) +
// result string plus NULL terminator
nMaxResultStrLen * sizeof(WCHAR) + sizeof(WCHAR);
// For avoiding miss alignment
iAllocSize += 2;
// Reallocation COMPOSITION buffer
m_pIMC->hCompStr = OurImmReSizeIMCC(GetHCompStr(), iAllocSize);
AST_EX(m_pIMC->hCompStr != (HIMCC)0);
if (m_pIMC->hCompStr == (HIMCC)0)
{
DbgAssert(0);
return;
}
if (m_pCompStr = (LPCOMPOSITIONSTRING)OurImmLockIMCC(GetHCompStr()))
{
// CONFIRM: Need to clear memory??
ZeroMemory(m_pCompStr, iAllocSize);
// Store total size
m_pCompStr->dwSize = iAllocSize;
// REVIEW: Does we need Null termination??
// Store offset. All offset is static which will be calculated in compile time
m_pCompStr->dwCompStrOffset = sizeof(COMPOSITIONSTRING);
m_pCompStr->dwCompAttrOffset = sizeof(COMPOSITIONSTRING) +
nMaxCompStrLen * sizeof(WCHAR) + sizeof(WCHAR); // length of comp str
m_pCompStr->dwResultStrOffset = sizeof(COMPOSITIONSTRING) +
nMaxCompStrLen * sizeof(WCHAR) + sizeof(WCHAR) + // length of comp str
nMaxCompStrLen * sizeof(WORD) + 2; // length of comp str attr
}
Dbg(DBGID_CompChar, "InitCompStrStruct m_pIMC->hCompStr = 0x%x, m_pCompStr = 0x%x", m_pIMC->hCompStr, m_pCompStr);
}
/*----------------------------------------------------------------------------
CIMECtx::StoreComposition
Store all composition result to IME context buffer
----------------------------------------------------------------------------*/
VOID CIMECtx::StoreComposition()
{
LPWSTR pwsz;
LPSTR psz;
Dbg(DBGID_Key, "StoreComposition GCS = 0x%x", GetGCS());
// Check composition handle validity
if (GetHCompStr() == NULL || m_pCompStr == NULL)
return ;
//////////////////////////////////////////////////////////////////////////
// Comp Str
if (GetGCS() & GCS_COMPSTR)
{
Dbg(DBGID_Key, "StoreComposition - GCS_COMPSTR comp str = 0x%04X", m_wcComp);
DbgAssert(m_wcComp != 0);
// Composition string. dw*StrLen contains character count
if (IsUnicodeEnv())
{
m_pCompStr->dwCompStrLen = 1;
pwsz = (LPWSTR)((LPBYTE)m_pCompStr + m_pCompStr->dwCompStrOffset);
*pwsz++ = m_wcComp; // Store composition char
*pwsz = L'\0';
}
else
{
// Byte length
m_pCompStr->dwCompStrLen = 2;
// Convert to ANSI
WideCharToMultiByte(CP_KOREA, 0,
&m_wcComp, 1, (LPSTR)m_szComp, sizeof(m_szComp),
NULL, NULL );
psz = (LPSTR)((LPBYTE)m_pCompStr + m_pCompStr->dwCompStrOffset);
*psz++ = m_szComp[0];
*psz++ = m_szComp[1];
*psz = '\0';
}
// Composition attribute. Always set
m_pCompStr->dwCompAttrLen = 1;
*((LPBYTE)m_pCompStr + m_pCompStr->dwCompAttrOffset) = ATTR_INPUT;
}
else
{
// Reset length
m_pCompStr->dwCompStrLen = 0;
m_pCompStr->dwCompAttrLen = 0;
}
//////////////////////////////////////////////////////////////////////////
// Result Str
if (GetGCS() & GCS_RESULTSTR)
{
Dbg(DBGID_Key, "StoreComposition - GCS_RESULTSTR comp str = 0x%04x, 0x%04X", m_wzResult[0], m_wzResult[1]);
// Composition string. dw*StrLen contains character count
if (IsUnicodeEnv())
{
// Result string length 1 or 2
m_pCompStr->dwResultStrLen = m_wzResult[1] ? 2 : 1; // lstrlenW(m_wzResult);
pwsz = (LPWSTR)((LPBYTE)m_pCompStr + m_pCompStr->dwResultStrOffset);
*pwsz++ = m_wzResult[0]; // Store composition result string
if (m_wzResult[1])
*pwsz++ = m_wzResult[1]; // Store composition result string
*pwsz = L'\0';
}
else
{
// Result string length 2 or 3
m_pCompStr->dwResultStrLen = m_wzResult[1] ? 3 : 2; // lstrlenW(m_wzResult);
// Convert to ANSI
WideCharToMultiByte(CP_KOREA, 0,
m_wzResult, (m_wzResult[1] ? 2 : 1),
(LPSTR)m_szResult, sizeof(m_szResult),
NULL, NULL );
psz = (LPSTR)((LPBYTE)m_pCompStr + m_pCompStr->dwResultStrOffset);
*psz++ = m_szResult[0];
*psz++ = m_szResult[1];
if (m_wzResult[1])
*psz++ = m_szResult[2];
*psz = '\0';
}
}
else
{
m_pCompStr->dwResultStrLen = 0;
}
}
/////////////////////////////////////////////////
// CANDIDATEINFO STRUCTURE SUPPORT
/////////////////////////////////////////////////
VOID CIMECtx::AppendCandidateStr(WCHAR wcCand, LPWSTR wszMeaning)
{
Dbg(DBGID_Hanja, "AppendCandidateStr");
// Alocate cand string and meaning buffer
if (m_pCandStr == NULL)
{
m_pCandStr =(LPWSTR)GlobalAlloc(GPTR, sizeof(WCHAR)*MAX_CANDSTR);
DbgAssert(m_pCandStr != NULL);
}
if (m_rgpCandMeaningStr == NULL)
{
m_rgpCandMeaningStr = (LPWSTR*)GlobalAlloc(GPTR, sizeof(LPWSTR)*MAX_CANDSTR);
DbgAssert(m_rgpCandMeaningStr != NULL);
}
if (m_pCandStr == NULL || m_rgpCandMeaningStr == NULL)
return;
// Append candidate char
DbgAssert(m_iciCandidate < MAX_CANDSTR);
if (m_iciCandidate >= MAX_CANDSTR)
return;
m_pCandStr[m_iciCandidate] = wcCand;
// Append candidate meaning
if (wszMeaning[0])
{
m_rgpCandMeaningStr[m_iciCandidate] = (LPWSTR)GlobalAlloc(GPTR, sizeof(WCHAR)*(lstrlenW(wszMeaning)+1));
if (m_rgpCandMeaningStr[m_iciCandidate] == NULL)
return;
StrCopyW(m_rgpCandMeaningStr[m_iciCandidate], wszMeaning);
}
else
m_rgpCandMeaningStr[m_iciCandidate] = NULL;
m_iciCandidate++;
}
WCHAR CIMECtx::GetCandidateStr(INT iIdx)
{
if (iIdx < 0 || iIdx >= MAX_CANDSTR)
{
DbgAssert(0);
return L'\0';
}
if (iIdx >= m_iciCandidate)
{
DbgAssert(0);
return L'\0';
}
return m_pCandStr[iIdx];
}
LPWSTR CIMECtx::GetCandidateMeaningStr(INT iIdx)
{
if (m_rgpCandMeaningStr == NULL ||
m_rgpCandMeaningStr[iIdx] == NULL ||
iIdx >= MAX_CANDSTR || iIdx < 0)
{
// DbgAssert(0); It happen for symbol mapping
return NULL;
}
else
return m_rgpCandMeaningStr[iIdx];
}
VOID CIMECtx::StoreCandidate()
{
INT iAllocSize;
LPCANDIDATELIST lpCandList;
Dbg(DBGID_Key, "StoreCandidate");
if (GetHCandInfo() == NULL)
return ; // do nothing
// Calc CANDIDATEINFO buffer size
iAllocSize = sizeof(CANDIDATEINFO) +
sizeof(CANDIDATELIST) + // candlist struct
m_iciCandidate * sizeof(DWORD) + // cand index
m_iciCandidate * sizeof(WCHAR) * 2; // cand strings with null termination
// Alllocate buffer
if (m_dwCandInfoSize < (DWORD)iAllocSize) // need to re-allocate
{
// reallocation COMPOSITION buffer
OurImmUnlockIMCC(GetHCandInfo());
m_pIMC->hCandInfo = OurImmReSizeIMCC(GetHCandInfo(), iAllocSize);
AST_EX(m_pIMC->hCandInfo != (HIMCC)0);
if (m_pIMC->hCandInfo == (HIMCC)0)
return;
m_pCandInfo = (CANDIDATEINFO*)OurImmLockIMCC(GetHCandInfo());
m_dwCandInfoSize = (DWORD)iAllocSize;
}
// Check if m_pCandInfo is valid
if (m_pCandInfo == NULL)
return;
// Fill cand info
m_pCandInfo->dwSize = iAllocSize;
m_pCandInfo->dwCount = 1;
m_pCandInfo->dwOffset[0] = sizeof(CANDIDATEINFO);
// Fill cand list
lpCandList = (LPCANDIDATELIST)((LPBYTE)m_pCandInfo + m_pCandInfo->dwOffset[0]);
lpCandList->dwSize = iAllocSize - sizeof(CANDIDATEINFO);
lpCandList->dwStyle = IME_CAND_READ;
lpCandList->dwCount = m_iciCandidate;
lpCandList->dwPageStart = lpCandList->dwSelection = 0;
lpCandList->dwPageSize = CAND_PAGE_SIZE;
INT iOffset = sizeof(CANDIDATELIST)
+ sizeof(DWORD) * (m_iciCandidate); // for dwOffset array
for (INT i = 0; i < m_iciCandidate; i++)
{
LPWSTR wszCandStr;
LPSTR szCandStr;
CHAR szCand[4] = "\0\0"; // Cand string always 1 char(2 bytes) + extra one byte
lpCandList->dwOffset[i] = iOffset;
if (IsUnicodeEnv())
{
wszCandStr = (LPWSTR)((LPSTR)lpCandList + iOffset);
*wszCandStr++ = m_pCandStr[i];
*wszCandStr++ = L'\0';
iOffset += sizeof(WCHAR) * 2;
}
else
{
// Convert to ANSI
WideCharToMultiByte(CP_KOREA, 0,
&m_pCandStr[m_iciCandidate], 1, (LPSTR)szCand, sizeof(szCand),
NULL, NULL );
szCandStr = (LPSTR)((LPSTR)lpCandList + iOffset);
*szCandStr++ = szCand[0];
*szCandStr++ = szCand[1];
*szCandStr = '\0';
iOffset += 3; // DBCS + NULL
}
}
}
/////////////////////////////////////////////////
// MSGBUF STRUCTURE SUPPORT
BOOL CIMECtx::FinalizeMessage()
{
DWORD dwCurrentGCS;
WPARAM wParam;
Dbg(DBGID_Key, "FinalizeMessage");
// support WM_IME_STARTCOMPOSITION
if (m_fStartComposition == fTrue)
{
Dbg(DBGID_Key, "FinalizeMessage - WM_IME_STARTCOMPOSITION");
AddMessage(WM_IME_STARTCOMPOSITION);
}
// support WM_IME_ENDCOMPOSITION
if (m_fEndComposition == fTrue)
{
Dbg(DBGID_Key, "FinalizeMessage - WM_IME_ENDCOMPOSITION");
AddMessage(WM_IME_ENDCOMPOSITION);
// Clear all automata states
if (GetAutomata() != NULL)
{
GetAutomata()->InitState();
}
}
// GCS validation before set to IMC
dwCurrentGCS = ValidateGCS();
if (dwCurrentGCS & GCS_RESULTSTR)
{
Dbg(DBGID_Key, "FinalizeMessage - WM_IME_COMPOSITION - GCS_RESULTSTR 0x%04x", m_wzResult[0]);
if (IsUnicodeEnv())
AddMessage(WM_IME_COMPOSITION, m_wzResult[0], GCS_RESULTSTR);
else
{
// Set ANSI code
wParam = ((WPARAM)m_szResult[0] << 8) | m_szResult[1];
AddMessage(WM_IME_COMPOSITION, wParam, GCS_RESULTSTR);
}
}
if (dwCurrentGCS & GCS_COMP_KOR)
{
Dbg(DBGID_Key, "FinalizeMessage - WM_IME_COMPOSITION - GCS_COMP_KOR 0x%04x", m_wcComp);
if (IsUnicodeEnv())
AddMessage(WM_IME_COMPOSITION, m_wcComp, (GCS_COMP_KOR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
else
{
// Set ANSI code
wParam = ((WPARAM)m_szComp[0] << 8) | m_szComp[1];
AddMessage(WM_IME_COMPOSITION, wParam, (GCS_COMP_KOR|GCS_COMPATTR|CS_INSERTCHAR|CS_NOMOVECARET));
}
}
ResetGCS(); // reset now
// O10 Bug #150012
// support WM_IME_ENDCOMPOSITION
if (m_fEndComposition == fTrue)
{
ResetComposition();
ResetCandidate();
}
FlushCandMessage();
//////////////////////////////////////////////////////////////////////////
// WM_IME_KEYDOWN: This should be added after all composition message
if (m_fKeyDown)
AddMessage(WM_IME_KEYDOWN, m_wParamKeyDown, (m_lParamKeyDown << 16) | 1UL);
return TRUE;
}
VOID CIMECtx::FlushCandMessage()
{
switch (m_uiSendCand)
{
case MSG_NONE: // Do nothing
break;
case MSG_OPENCAND:
AddMessage(WM_IME_NOTIFY, IMN_OPENCANDIDATE, 1);
break;
case MSG_CLOSECAND:
AddMessage(WM_IME_NOTIFY, IMN_CLOSECANDIDATE, 1);
ResetCandidate();
break;
case MSG_CHANGECAND:
AddMessage(WM_IME_NOTIFY, IMN_CHANGECANDIDATE, 1);
break;
default:
DbgAssert(0); // Error
break;
}
m_uiSendCand = MSG_NONE;
}
BOOL CIMECtx::GenerateMessage()
{
BOOL fResult = fFalse;
INT iMsgCount;
Dbg(DBGID_Key, "GenerateMessage");
if (IsProcessKeyStatus())
return fFalse; // Do nothing
FinalizeMessage();
iMsgCount = GetMessageCount();
ResetMessage();
if (iMsgCount > 0)
fResult = OurImmGenerateMessage(m_hIMC);
return fResult;
}
INT CIMECtx::AddMessage(UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
LPTRANSMSG pImeMsg;
Dbg(DBGID_Key, "AddMessage uiMessage=0x%X, wParam=0x%04X, lParam=0x%08lX", uiMessage, wParam, lParam);
if (GetHMsgBuf() == NULL)
return m_uiMsgCount;
m_uiMsgCount++;
//////////////////////////////////////////////////////////////////////////
// Check if this data stream created by ImeToAsciiEx()
if (m_pTransMessage)
{
Dbg(DBGID_Key, "AddMessage - use Transbuffer(ImeToAscii)");
// Check if need reallocate message buffer
if (m_pTransMessage->uMsgCount >= m_uiMsgCount)
{
// Fill msg buffer
pImeMsg = &m_pTransMessage->TransMsg[m_uiMsgCount - 1];
pImeMsg->message = uiMessage;
pImeMsg->wParam = wParam;
pImeMsg->lParam = lParam;
}
else
{
DbgAssert(0);
// pre-allocated buffer is full - use hMsgBuf instead.
UINT uiMsgCountOrg = m_uiMsgCount; // backup
m_uiMsgCount = 0; // reset anyway
LPTRANSMSGLIST pHeader = m_pTransMessage; // backup
SetTransMessage(NULL); // use hMsgBuf
for (UINT i=0; i<uiMsgCountOrg; i++)
AddMessage(pHeader->TransMsg[i].message, pHeader->TransMsg[i].wParam, pHeader->TransMsg[i].lParam);
// finally adds current message
AddMessage(uiMessage, wParam, lParam);
}
}
else // m_pTransMessage. Not called from ImeToAsciiEx()
{
UINT iMaxMsg = m_dwMessageSize / sizeof(TRANSMSG);
DWORD dwNewSize;
Dbg(DBGID_Key, "AddMessage - use hMsgBuf");
if (m_uiMsgCount > iMaxMsg)
{
Dbg(DBGID_Key, "AddMessage - Reallocate");
// Reallocation message buffer
OurImmUnlockIMCC(GetHMsgBuf());
dwNewSize = max(16, m_uiMsgCount) * sizeof(TRANSMSG); // At least 16 cand list
m_pIMC->hMsgBuf = OurImmReSizeIMCC(GetHMsgBuf(), dwNewSize);
AST_EX(m_pIMC->hMsgBuf != (HIMCC)0);
if (m_pIMC->hMsgBuf == (HIMCC)0)
return m_uiMsgCount;
m_pMessage = (LPTRANSMSG)OurImmLockIMCC(GetHMsgBuf());
m_dwMessageSize = dwNewSize;
}
// Fill msg buffer
pImeMsg = m_pMessage + m_uiMsgCount - 1;
pImeMsg->message = uiMessage;
pImeMsg->wParam = wParam;
pImeMsg->lParam = lParam;
// set message count
m_pIMC->dwNumMsgBuf = m_uiMsgCount;
}
return m_uiMsgCount;
}
/*----------------------------------------------------------------------------
CIMECtx::GetCompBufStr
Get current hCompStr comp str. If Win95, convert it to Unicode
----------------------------------------------------------------------------*/
WCHAR CIMECtx::GetCompBufStr()
{
WCHAR wch;
if (GetHCompStr() == NULL || m_pCompStr == NULL)
return L'\0';
if (IsUnicodeEnv())
return *(LPWSTR)((LPBYTE)m_pCompStr + m_pCompStr->dwCompStrOffset);
else
{
if (MultiByteToWideChar(CP_KOREA, MB_PRECOMPOSED,
(LPSTR)((LPBYTE)m_pCompStr + m_pCompStr->dwCompStrOffset),
2,
&wch,
1))
return wch;
else
return L'\0';
}
}
/*----------------------------------------------------------------------------
CIMECtx::ClearCandMeaningArray
----------------------------------------------------------------------------*/
void CIMECtx::ClearCandMeaningArray()
{
if (m_rgpCandMeaningStr == NULL)
return;
for (int i=0; i<MAX_CANDSTR; i++)
{
if (m_rgpCandMeaningStr[i] == NULL)
break;
GlobalFree(m_rgpCandMeaningStr[i]);
m_rgpCandMeaningStr[i] = 0;
}
}