|
|
/*++
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; }
|