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.
 
 
 
 
 
 

1012 lines
28 KiB

/*++
Copyright (c) 2001, Microsoft Corporation
Module Name:
context.cpp
Abstract:
This file implements the CicInputContext Class.
Author:
Revision History:
Notes:
--*/
#include "private.h"
#include "context.h"
#include "globals.h"
#include "msime.h"
#include "icocb.h"
#include "txtevcb.h"
#include "tmgrevcb.h"
#include "cmpevcb.h"
#include "reconvcb.h"
#include "korimx.h"
#include "profile.h"
#include "delay.h"
//+---------------------------------------------------------------------------
//
// CicInputContext::IUnknown::QueryInterface
// CicInputContext::IUnknown::AddRef
// CicInputContext::IUnknown::Release
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::QueryInterface(
REFIID riid,
void** ppvObj)
{
*ppvObj = NULL;
if (IsEqualIID(riid, IID_ITfCleanupContextSink))
{
*ppvObj = static_cast<ITfCleanupContextSink*>(this);
}
else if (IsEqualGUID(riid, IID_ITfContextOwnerCompositionSink))
{
*ppvObj = static_cast<ITfContextOwnerCompositionSink*>(this);
}
else if (IsEqualGUID(riid, IID_IUnknown))
{
*ppvObj = this;
}
if (*ppvObj) {
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG
CicInputContext::AddRef(
)
{
return InterlockedIncrement(&m_ref);
}
ULONG
CicInputContext::Release(
)
{
ULONG cr = InterlockedDecrement(&m_ref);
if (cr == 0) {
delete this;
}
return cr;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::ITfCleanupContextSink::OnCleanupContext
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::OnCleanupContext(
TfEditCookie ecWrite,
ITfContext* pic)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::OnCleanupContext"));
TLS* ptls = TLS::ReferenceTLS(); // Should not allocate TLS. ie. TLS::GetTLS
// DllMain -> ImeDestroy -> DeactivateIMMX -> Deactivate
if (ptls == NULL)
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. ptls==NULL."));
return E_OUTOFMEMORY;
}
LANGID langid;
CicProfile* _pProfile = ptls->GetCicProfile();
if (_pProfile == NULL)
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. _pProfile==NULL."));
return E_OUTOFMEMORY;
}
_pProfile->GetLangId(&langid);
IMEINFO ImeInfo;
WCHAR szWndCls[MAX_PATH];
if (Inquire(&ImeInfo, szWndCls, 0, (HKL)UlongToHandle(langid)) != S_OK)
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. ImeInfo==NULL."));
return E_FAIL;
}
if (ImeInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT)
{
#if 0
ImmIfCompositionComplete *pImmIfCallBack = new ImmIfCompositionComplete;
if (!pImmIfCallBack)
return E_OUTOFMEMORY;
pImmIfCallBack->CompComplete(ecWrite, m_hImc, FALSE, pic, m_pImmIfIME);
delete pImmIfCallBack;
#else
//
// Remove GUID_PROP_COMPOSING
//
ITfRange *rangeFull = NULL;
ITfProperty *prop;
ITfRange *rangeTmp;
if (SUCCEEDED(pic->GetProperty(GUID_PROP_COMPOSING, &prop)))
{
IEnumTfRanges *enumranges;
if (SUCCEEDED(prop->EnumRanges(ecWrite, &enumranges, rangeFull)))
{
while (enumranges->Next(1, &rangeTmp, NULL) == S_OK)
{
VARIANT var;
QuickVariantInit(&var);
prop->GetValue(ecWrite, rangeTmp, &var);
if ((var.vt == VT_I4) && (var.lVal != 0))
{
prop->Clear(ecWrite, rangeTmp);
}
rangeTmp->Release();
}
enumranges->Release();
}
prop->Release();
}
#endif
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::ITfContextOwnerCompositionSink::OnStartComposition
// CicInputContext::ITfContextOwnerCompositionSink::OnUpdateComposition
// CicInputContext::ITfContextOwnerCompositionSink::OnEndComposition
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::OnStartComposition(
ITfCompositionView* pComposition,
BOOL* pfOk)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::OnStartComposition"));
if (m_cCompositions > 0 && m_fModifyingDoc.IsResetFlag())
{
*pfOk = FALSE;
}
else
{
*pfOk = TRUE;
m_cCompositions++;
}
return S_OK;
}
HRESULT
CicInputContext::OnUpdateComposition(
ITfCompositionView* pComposition,
ITfRange* pRangeNew)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::OnUpdateComposition"));
return S_OK;
}
HRESULT
CicInputContext::OnEndComposition(
ITfCompositionView* pComposition)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::OnEndComposition"));
m_cCompositions--;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::ITfCompositionSink::OnCompositionTerminated
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::OnCompositionTerminated(
TfEditCookie ecWrite,
ITfComposition* pComposition)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::OnCompositionTerminated"));
return S_OK;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::CreateInputContext
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::CreateInputContext(
ITfThreadMgr_P* ptim_P,
IMCLock& imc)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::CreateInputContext"));
// do this once for the life time of this context
m_fStartComposition.ResetFlag();
HRESULT hr;
//
// Create document manager.
//
if (m_pdim == NULL) {
if (FAILED(hr = ptim_P->CreateDocumentMgr(&m_pdim)))
{
return hr;
}
//
// mark this is an owned dim.
//
SetCompartmentDWORD(m_tid, m_pdim, GUID_COMPARTMENT_CTFIME_DIMFLAGS,
COMPDIMFLAG_OWNEDDIM, FALSE);
}
//
// Create input context
//
TfEditCookie ecTmp;
hr = m_pdim->CreateContext(m_tid, 0, (ITfContextOwnerCompositionSink*)this, &m_pic, &ecTmp);
if (FAILED(hr)) {
DestroyInputContext();
return hr;
}
//
// associate CicInputContext in PIC.
//
Interface<IUnknown> punk;
if (SUCCEEDED(QueryInterface(IID_IUnknown, punk))) {
SetCompartmentUnknown(m_tid, m_pic,
GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT,
punk);
}
//
// set AppProp mapping
//
ITfContext_P *picp;
if (SUCCEEDED(m_pic->QueryInterface(IID_ITfContext_P, (void **)&picp)))
{
picp->MapAppProperty(TSATTRID_Text_ReadOnly, GUID_PROP_MSIMTF_READONLY);
picp->Release();
}
//
// Create Input Context Owner Callback
//
if (m_pICOwnerSink == NULL) {
m_pICOwnerSink = new CInputContextOwnerCallBack(m_tid, m_pic, m_pLibTLS);
if (m_pICOwnerSink == NULL) {
DebugMsg(TF_ERROR, TEXT("Couldn't create ICOwnerSink tim!"));
Assert(0); // couldn't activate thread!
DestroyInputContext();
return E_FAIL;
}
if (!m_pICOwnerSink->Init()) {
DebugMsg(TF_ERROR, TEXT("Couldn't initialize ICOwnerSink tim!"));
Assert(0); // couldn't activate thread!
DestroyInputContext();
return E_FAIL;
}
m_pICOwnerSink->SetCallbackDataPointer(m_pICOwnerSink);
}
//
// Advise IC.
//
m_pICOwnerSink->_Advise(m_pic);
Interface<ITfSourceSingle> SourceSingle;
if (m_pic->QueryInterface(IID_ITfSourceSingle, (void **)SourceSingle) == S_OK)
{
// setup a cleanup callback
// nb: a real tip doesn't need to be this aggressive, for instance
// kimx probably only needs this sink on the focus ic.
SourceSingle->AdviseSingleSink(m_tid, IID_ITfCleanupContextSink, (ITfCleanupContextSink *)this);
}
//
// Push IC.
//
hr = m_pdim->Push(m_pic);
if (m_piccb == NULL) {
m_pic->QueryInterface(IID_ITfContextOwnerServices,
(void **)&m_piccb);
}
//
// Create Text Event Sink Callback
//
if (m_pTextEventSink == NULL) {
m_pTextEventSink = new CTextEventSinkCallBack((HIMC)imc, m_tid, m_pic, m_pLibTLS);
if (m_pTextEventSink == NULL) {
DestroyInputContext();
return E_FAIL;
}
m_pTextEventSink->SetCallbackDataPointer(m_pTextEventSink);
Interface_Attach<ITfContext> ic(GetInputContext());
m_pTextEventSink->_Advise(ic.GetPtr(), ICF_TEXTDELTA);
}
//
// Create KBD TIP Open/Close Compartment Event Sink Callback
//
if (m_pKbdOpenCloseEventSink == NULL) {
m_pKbdOpenCloseEventSink = new CKbdOpenCloseEventSink(m_tid, (HIMC)imc, m_pic, m_pLibTLS);
if (m_pKbdOpenCloseEventSink == NULL) {
DestroyInputContext();
return E_FAIL;
}
m_pKbdOpenCloseEventSink->SetCallbackDataPointer(m_pKbdOpenCloseEventSink);
m_pKbdOpenCloseEventSink->_Advise(ptim_P, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, FALSE);
m_pKbdOpenCloseEventSink->_Advise(ptim_P, GUID_COMPARTMENT_KORIMX_CONVMODE, FALSE);
}
//
// Create Candidate UI Window Open/Close Compartment Event Sink Callback
//
if (m_pCandidateWndOpenCloseEventSink == NULL) {
m_pCandidateWndOpenCloseEventSink = new CCandidateWndOpenCloseEventSink(m_tid, (HIMC)imc, m_pic, m_pLibTLS);
if (m_pCandidateWndOpenCloseEventSink == NULL) {
DestroyInputContext();
return E_FAIL;
}
m_pCandidateWndOpenCloseEventSink->SetCallbackDataPointer(m_pCandidateWndOpenCloseEventSink);
m_pCandidateWndOpenCloseEventSink->_Advise(m_pic, GUID_COMPARTMENT_MSCANDIDATEUI_WINDOW, FALSE);
}
//
// Create Start reconversion notify Sink
//
if (m_pStartReconvSink == NULL) {
m_pStartReconvSink = new CStartReconversionNotifySink((HIMC)imc);
if (m_pStartReconvSink == NULL) {
DestroyInputContext();
return E_FAIL;
}
m_pStartReconvSink->_Advise(m_pic);
}
//
// Create Message Buffer
//
if (m_pMessageBuffer == NULL) {
m_pMessageBuffer = new CFirstInFirstOut<TRANSMSG, TRANSMSG>;
if (m_pMessageBuffer == NULL) {
DestroyInputContext();
return E_FAIL;
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::DestroyInputContext
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::DestroyInputContext()
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::DestroyInputContext"));
Interface<ITfSourceSingle> SourceSingle;
if (m_pic && m_pic->QueryInterface(IID_ITfSourceSingle, (void **)SourceSingle) == S_OK)
{
SourceSingle->UnadviseSingleSink(m_tid, IID_ITfCleanupContextSink);
}
if (m_pMessageBuffer) {
delete m_pMessageBuffer;
m_pMessageBuffer = NULL;
}
if (m_pTextEventSink) {
m_pTextEventSink->_Unadvise();
m_pTextEventSink->Release();
m_pTextEventSink = NULL;
}
if (m_pCandidateWndOpenCloseEventSink) {
m_pCandidateWndOpenCloseEventSink->_Unadvise();
m_pCandidateWndOpenCloseEventSink->Release();
m_pCandidateWndOpenCloseEventSink = NULL;
}
if (m_pKbdOpenCloseEventSink) {
m_pKbdOpenCloseEventSink->_Unadvise();
m_pKbdOpenCloseEventSink->Release();
m_pKbdOpenCloseEventSink = NULL;
}
if (m_pStartReconvSink) {
m_pStartReconvSink->_Unadvise();
m_pStartReconvSink->Release();
m_pStartReconvSink = NULL;
}
HRESULT hr;
if (m_pdim)
{
hr = m_pdim->Pop(TF_POPF_ALL);
}
//
// un-associate CicInputContext in PIC.
//
if (m_pic) {
ClearCompartment(m_tid, m_pic,
GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT,
FALSE);
}
if (m_pic) {
m_pic->Release();
m_pic = NULL;
}
if (m_piccb) {
m_piccb->Release();
m_piccb = NULL;
}
// ic owner is auto unadvised during the Pop by cicero
// in any case, it must not be unadvised before the pop
// since it will be used to handle mouse sinks, etc.
if (m_pICOwnerSink) {
m_pICOwnerSink->_Unadvise();
m_pICOwnerSink->Release();
m_pICOwnerSink = NULL;
}
if (m_pdim)
{
m_pdim->Release();
m_pdim = NULL;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::GenerateMessage
//
//----------------------------------------------------------------------------
void
CicInputContext::GenerateMessage(
IMCLock& imc)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::GenerateMessage"));
TranslateImeMessage(imc);
if (FAILED(imc.GetResult()))
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::GenerateMessage. imc==NULL"));
}
IMCCLock<CTFIMECONTEXT> imc_ctfime(imc->hCtfImeContext);
DWORD dwImeCompatFlags = ImmGetAppCompatFlags(NULL);
BOOL fSendMsg;
CicInputContext* _pCicContext = imc_ctfime->m_pCicContext;
if (_pCicContext == NULL)
return;
if (!(_pCicContext->m_fInToAsciiEx.IsSetFlag() ||
_pCicContext->m_fInProcessKey.IsSetFlag() ) ||
_pCicContext->m_fInDocFeedReconvert.IsSetFlag() ||
MsimtfIsWindowFiltered(::GetFocus()))
{
//
// Generate SendMessage.
//
fSendMsg = TRUE;
CtfImmGenerateMessage((HIMC)imc, fSendMsg);
}
else
{
//
// Generate PostMessage.
//
fSendMsg = FALSE;
CtfImmGenerateMessage((HIMC)imc, fSendMsg);
}
}
//+---------------------------------------------------------------------------
//
// CicInputContext::TranslateImeMessage
//
//----------------------------------------------------------------------------
UINT
CicInputContext::TranslateImeMessage(
IMCLock& imc,
TRANSMSGLIST* lpTransMsgList) // default = NULL
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::TranslateImeMessage"));
if (m_pMessageBuffer == NULL)
return 0;
INT_PTR NumMsg = m_pMessageBuffer->GetSize();
if (NumMsg == 0)
return 0;
UINT retNumMsg = 0;
if (lpTransMsgList && NumMsg < (INT_PTR)lpTransMsgList->uMsgCount) {
LPTRANSMSG lpTransMsg = &lpTransMsgList->TransMsg[0];
while (NumMsg--) {
if (! m_pMessageBuffer->GetData(*lpTransMsg++))
break;
retNumMsg++;
}
}
else {
if (imc->hMsgBuf == NULL) {
imc->hMsgBuf = ImmCreateIMCC((DWORD)(NumMsg * sizeof(TRANSMSG)));
}
else if (ImmGetIMCCSize(imc->hMsgBuf) < NumMsg * sizeof(TRANSMSG)) {
imc->hMsgBuf = ImmReSizeIMCC(imc->hMsgBuf, (DWORD)(NumMsg * sizeof(TRANSMSG)));
}
imc->dwNumMsgBuf = 0;
IMCCLock<TRANSMSG> pdw(imc->hMsgBuf);
if (pdw.Valid()) {
LPTRANSMSG lpTransMsg = pdw;
while (NumMsg--) {
if (! m_pMessageBuffer->GetData(*lpTransMsg++))
break;
retNumMsg++;
}
imc->dwNumMsgBuf = retNumMsg;
}
}
return retNumMsg;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::InquireIMECharPosition
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::InquireIMECharPosition(
LANGID langid,
IMCLock& imc,
IME_QUERY_POS* pfQueryPos)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::InquireIMECharPosition"));
if (m_fQueryPos == IME_QUERY_POS_UNKNOWN) {
//
// Bug#500488 - Don't WM_MSIME_QUERYPOSITION for Korea
//
DWORD dwImeCompatFlags = ImmGetAppCompatFlags(NULL);
if ((PRIMARYLANGID(langid) != LANG_KOREAN) ||
((PRIMARYLANGID(langid) == LANG_KOREAN) &&
(dwImeCompatFlags & (IMECOMPAT_AIMM12 | IMECOMPAT_AIMM_LEGACY_CLSID | IMECOMPAT_AIMM12_TRIDENT)))
) {
//
// Is apps support "query positioning" ?
//
IMECHARPOSITION ip = {0};
ip.dwSize = sizeof(IMECHARPOSITION);
m_fQueryPos = QueryCharPos(imc, &ip) ? IME_QUERY_POS_YES : IME_QUERY_POS_NO;
#ifdef DEBUG
//
// if QeuryCharPos() fails, the candidate window pos won't be correct.
//
if (m_fQueryPos == IME_QUERY_POS_NO)
{
Assert(0);
}
#endif
}
}
if (pfQueryPos) {
*pfQueryPos = m_fQueryPos;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::RetrieveIMECharPosition
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::RetrieveIMECharPosition(
IMCLock& imc,
IMECHARPOSITION* ip)
{
return QueryCharPos(imc, ip) ? S_OK : E_FAIL;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::QueryCharPos
//
//----------------------------------------------------------------------------
BOOL
CicInputContext::QueryCharPos(
IMCLock& imc,
IMECHARPOSITION* position)
{
LRESULT lRet;
//
// First Step. Query by local method.
//
lRet = ::SendMessage(imc->hWnd,
WM_MSIME_QUERYPOSITION,
VERSION_QUERYPOSITION,
(LPARAM)position);
if (lRet) {
return TRUE;
}
//
// Second Step. Query by IMM method.
// (IsOnNT5() || IsOn98())
//
if (ImmRequestMessage((HIMC)imc,
IMR_QUERYCHARPOSITION,
(LPARAM)position)) {
return TRUE;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::MsImeMouseHandler
//
//----------------------------------------------------------------------------
LRESULT
CicInputContext::MsImeMouseHandler(
ULONG uEdge,
ULONG uQuadrant,
ULONG dwBtnStatus,
IMCLock& imc)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::MsImeMouseHandler"));
LRESULT ret = m_pICOwnerSink->MsImeMouseHandler(uEdge, uQuadrant, dwBtnStatus, imc);
if (dwBtnStatus & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) {
EscbUpdateCompositionString(imc);
}
return ret;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::SetCompositionString
//
//----------------------------------------------------------------------------
BOOL
CicInputContext::SetCompositionString(
IMCLock& imc,
ITfThreadMgr_P* ptim_P,
DWORD dwIndex,
void* pComp,
DWORD dwCompLen,
void* pRead,
DWORD dwReadLen,
UINT cp)
{
DebugMsg(TF_FUNC, TEXT("CicInputContext::SetCompositionString"));
HRESULT hr;
switch (dwIndex)
{
case SCS_SETSTR:
{
CWCompString wCompStr(imc, (LPWSTR)pComp, dwCompLen / sizeof(WCHAR)); // dwCompLen is byte count.
CWCompString wCompReadStr(imc, (LPWSTR)pRead, dwReadLen / sizeof(WCHAR)); // dwReadLen is byte count.
hr = Internal_SetCompositionString(imc, wCompStr, wCompReadStr);
if (SUCCEEDED(hr))
return TRUE;
}
break;
case SCS_CHANGEATTR:
case SCS_CHANGECLAUSE:
return FALSE;
case SCS_SETRECONVERTSTRING:
{
CWReconvertString wReconvStr(imc, (LPRECONVERTSTRING)pComp, dwCompLen);
CWReconvertString wReconvReadStr(imc, (LPRECONVERTSTRING)pRead, dwReadLen);
hr = Internal_ReconvertString(imc, ptim_P, wReconvStr, wReconvReadStr);
if (SUCCEEDED(hr))
return TRUE;
}
break;
case SCS_QUERYRECONVERTSTRING:
// AdjustZeroCompLenReconvertString((LPRECONVERTSTRING)pComp, cp, FALSE);
// hr = S_OK;
hr = Internal_QueryReconvertString(imc, ptim_P, (LPRECONVERTSTRING)pComp, cp, FALSE);
if (SUCCEEDED(hr))
return TRUE;
break;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::GetGuidAtom
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::GetGuidAtom(
IMCLock& imc,
BYTE bAttr,
TfGuidAtom* atom)
{
HRESULT hr;
IMCCLock<COMPOSITIONSTRING> comp(imc->hCompStr);
if (FAILED(hr=comp.GetResult()))
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::GetGuidAtom. comp==NULL"));
return hr;
}
if (bAttr < usGuidMapSize)
{
*atom = aGuidMap[bAttr];
return S_OK;
}
return E_FAIL;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::MapAttributes
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::MapAttributes(
IMCLock& imc)
{
HRESULT hr;
IMCCLock<COMPOSITIONSTRING> comp(imc->hCompStr);
if (FAILED(hr=comp.GetResult()))
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::MapAttributes. comp==NULL"));
return hr;
}
GuidMapAttribute guid_map(GuidMapAttribute::GetData(comp));
if (guid_map.Invalid())
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::MapAttributes. guid_map==NULL"));
return E_OUTOFMEMORY;
}
if (usGuidMapSize == 0)
{
//
// Make transration table.
//
usGuidMapSize = ATTR_LAYER_GUID_START;
for (USHORT i = 0; i < guid_map->dwTfGuidAtomLen; ++i)
{
//
// Check if this GUID is already registered
//
for (USHORT j = ATTR_LAYER_GUID_START; j < usGuidMapSize; ++j)
{
if (aGuidMap[j] == ((TfGuidAtom*)guid_map.GetOffsetPointer(guid_map->dwTfGuidAtomOffset))[i])
{
break;
}
}
BYTE bAttr;
if (j >= usGuidMapSize)
{
//
// Couldn't find the GUID registered.
//
if (usGuidMapSize < ARRAYSIZE(aGuidMap) - 1)
{
bAttr = static_cast<BYTE>(usGuidMapSize);
aGuidMap[usGuidMapSize++] = ((TfGuidAtom*)guid_map.GetOffsetPointer(guid_map->dwTfGuidAtomOffset))[i];
}
else
{
// # of GUID exceeds the # of available attribute...
// Maybe it should fail, but for now give it a bogus attirbute.
bAttr = ATTR_TARGET_CONVERTED;
}
}
else
{
bAttr = static_cast<BYTE>(j);
}
((BYTE*)guid_map.GetOffsetPointer(guid_map->dwGuidMapAttrOffset))[i] = bAttr;
}
guid_map->dwGuidMapAttrLen = guid_map->dwTfGuidAtomLen;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// CicInputContext::WantThisKey
//
//----------------------------------------------------------------------------
BOOL
CicInputContext::WantThisKey(
UINT uVirtKey)
{
if (! IsTopNow())
{
return FALSE;
}
switch (BYTE(uVirtKey))
{
case VK_RETURN:
case VK_ESCAPE:
case VK_BACK:
case VK_DELETE:
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
case VK_HOME:
case VK_END:
/*
* If we don't have a composition string, then we should return FALSE.
*/
if (m_fStartComposition.IsResetFlag())
{
return FALSE;
}
return TRUE;
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// OnSetCandidatePos
//
//----------------------------------------------------------------------------
HRESULT
CicInputContext::OnSetCandidatePos(
TLS* ptls,
IMCLock& imc)
{
DebugMsg(TF_FUNC, TEXT("CicBridge::OnSetCandidatePos"));
RECT rcAppPosForCandidatePos = {0};
RECT rcAppCandidatePos = {0};
//
// #510404
//
// check the previous candidate pos and we don't have to move them
// if it is not changed.
//
GetWindowRect(imc->hWnd, &rcAppPosForCandidatePos);
if ((imc->hWnd == m_hwndPrevCandidatePos) &&
!memcmp(&rcAppPosForCandidatePos,
&m_rcPrevAppPosForCandidatePos, sizeof(RECT)))
{
BOOL fCheckQueryCharPos = FALSE;
if (!memcmp(&imc->cfCandForm[0],
&m_cfPrevCandidatePos, sizeof(CANDIDATEFORM)))
{
LANGID langid;
CicProfile* _pProfile = ptls->GetCicProfile();
if (_pProfile == NULL)
{
DebugMsg(TF_ERROR, TEXT("CicInputContext::OnCleanupContext. _pProfile==NULL."));
return E_OUTOFMEMORY;
}
_pProfile->GetLangId(&langid);
CCandidatePosition cand_pos(m_tid, m_pic, m_pLibTLS);
if (SUCCEEDED(cand_pos.GetRectFromApp(imc, *this, langid, &rcAppCandidatePos)))
{
if (!memcmp(&rcAppCandidatePos,
&m_rcPrevAppCandidatePos, sizeof(RECT)))
return S_OK;
}
else
return S_OK;
}
}
HWND hDefImeWnd;
//
// When this is in the reconvert session, candidate window position is
// not caret position of cfCandForm->ptCurrentPos.
//
if (m_fInReconvertEditSession.IsResetFlag() &&
IsWindow(hDefImeWnd=ImmGetDefaultIMEWnd(NULL)) &&
ptls->IsCTFUnaware() // bug:5213 WinWord
// WinWord10 calls ImmSetCandidateWindow() while receive WM_LBUTTONUP.
)
{
/*
* A-Synchronize call ITfContextOwnerServices::OnLayoutChange
* because this method had a protected.
*/
PostMessage(hDefImeWnd, WM_IME_NOTIFY, IMN_PRIVATE_STARTLAYOUTCHANGE, 0);
}
m_hwndPrevCandidatePos = imc->hWnd;
memcpy(&m_rcPrevAppPosForCandidatePos, &rcAppPosForCandidatePos, sizeof(RECT));
memcpy(&m_cfPrevCandidatePos, &imc->cfCandForm[0], sizeof(CANDIDATEFORM));
memcpy(&m_rcPrevAppCandidatePos, &rcAppCandidatePos, sizeof(RECT));
return S_OK;
}