2025-11-28 00:35:46 +09:00

432 lines
10 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#include "Private.h"
#include "globals.h"
#include "SampleIME.h"
#include "CandidateListUIPresenter.h"
#include "CompositionProcessorEngine.h"
#include "Compartment.h"
//+---------------------------------------------------------------------------
//
// CreateInstance
//
//----------------------------------------------------------------------------
/* static */
HRESULT CSampleIME::CreateInstance(_In_ IUnknown *pUnkOuter, REFIID riid, _Outptr_ void **ppvObj)
{
CSampleIME* pSampleIME = nullptr;
HRESULT hr = S_OK;
if (ppvObj == nullptr)
{
return E_INVALIDARG;
}
*ppvObj = nullptr;
if (nullptr != pUnkOuter)
{
return CLASS_E_NOAGGREGATION;
}
pSampleIME = new (std::nothrow) CSampleIME();
if (pSampleIME == nullptr)
{
return E_OUTOFMEMORY;
}
hr = pSampleIME->QueryInterface(riid, ppvObj);
pSampleIME->Release();
return hr;
}
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CSampleIME::CSampleIME()
{
DllAddRef();
_pThreadMgr = nullptr;
_threadMgrEventSinkCookie = TF_INVALID_COOKIE;
_pTextEditSinkContext = nullptr;
_textEditSinkCookie = TF_INVALID_COOKIE;
_activeLanguageProfileNotifySinkCookie = TF_INVALID_COOKIE;
_dwThreadFocusSinkCookie = TF_INVALID_COOKIE;
_pComposition = nullptr;
_pCompositionProcessorEngine = nullptr;
_candidateMode = CANDIDATE_NONE;
_pCandidateListUIPresenter = nullptr;
_isCandidateWithWildcard = FALSE;
_pDocMgrLastFocused = nullptr;
_pSIPIMEOnOffCompartment = nullptr;
_dwSIPIMEOnOffCompartmentSinkCookie = 0;
_msgWndHandle = nullptr;
_pContext = nullptr;
_refCount = 1;
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CSampleIME::~CSampleIME()
{
if (_pCandidateListUIPresenter)
{
delete _pCandidateListUIPresenter;
_pCandidateListUIPresenter = nullptr;
}
DllRelease();
}
//+---------------------------------------------------------------------------
//
// QueryInterface
//
//----------------------------------------------------------------------------
STDAPI CSampleIME::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
{
if (ppvObj == nullptr)
{
return E_INVALIDARG;
}
*ppvObj = nullptr;
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_ITfTextInputProcessor))
{
*ppvObj = (ITfTextInputProcessor *)this;
}
else if (IsEqualIID(riid, IID_ITfTextInputProcessorEx))
{
*ppvObj = (ITfTextInputProcessorEx *)this;
}
else if (IsEqualIID(riid, IID_ITfThreadMgrEventSink))
{
*ppvObj = (ITfThreadMgrEventSink *)this;
}
else if (IsEqualIID(riid, IID_ITfTextEditSink))
{
*ppvObj = (ITfTextEditSink *)this;
}
else if (IsEqualIID(riid, IID_ITfKeyEventSink))
{
*ppvObj = (ITfKeyEventSink *)this;
}
else if (IsEqualIID(riid, IID_ITfActiveLanguageProfileNotifySink))
{
*ppvObj = (ITfActiveLanguageProfileNotifySink *)this;
}
else if (IsEqualIID(riid, IID_ITfCompositionSink))
{
*ppvObj = (ITfKeyEventSink *)this;
}
else if (IsEqualIID(riid, IID_ITfDisplayAttributeProvider))
{
*ppvObj = (ITfDisplayAttributeProvider *)this;
}
else if (IsEqualIID(riid, IID_ITfThreadFocusSink))
{
*ppvObj = (ITfThreadFocusSink *)this;
}
else if (IsEqualIID(riid, IID_ITfFunctionProvider))
{
*ppvObj = (ITfFunctionProvider *)this;
}
else if (IsEqualIID(riid, IID_ITfFunction))
{
*ppvObj = (ITfFunction *)this;
}
else if (IsEqualIID(riid, IID_ITfFnGetPreferredTouchKeyboardLayout))
{
*ppvObj = (ITfFnGetPreferredTouchKeyboardLayout *)this;
}
if (*ppvObj)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
//+---------------------------------------------------------------------------
//
// AddRef
//
//----------------------------------------------------------------------------
STDAPI_(ULONG) CSampleIME::AddRef()
{
return ++_refCount;
}
//+---------------------------------------------------------------------------
//
// Release
//
//----------------------------------------------------------------------------
STDAPI_(ULONG) CSampleIME::Release()
{
LONG cr = --_refCount;
assert(_refCount >= 0);
if (_refCount == 0)
{
delete this;
}
return cr;
}
//+---------------------------------------------------------------------------
//
// ITfTextInputProcessorEx::ActivateEx
//
//----------------------------------------------------------------------------
STDAPI CSampleIME::ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClientId, DWORD dwFlags)
{
_pThreadMgr = pThreadMgr;
_pThreadMgr->AddRef();
_tfClientId = tfClientId;
_dwActivateFlags = dwFlags;
if (!_InitThreadMgrEventSink())
{
goto ExitError;
}
ITfDocumentMgr* pDocMgrFocus = nullptr;
if (SUCCEEDED(_pThreadMgr->GetFocus(&pDocMgrFocus)) && (pDocMgrFocus != nullptr))
{
_InitTextEditSink(pDocMgrFocus);
pDocMgrFocus->Release();
}
if (!_InitKeyEventSink())
{
goto ExitError;
}
if (!_InitActiveLanguageProfileNotifySink())
{
goto ExitError;
}
if (!_InitThreadFocusSink())
{
goto ExitError;
}
if (!_InitDisplayAttributeGuidAtom())
{
goto ExitError;
}
if (!_InitFunctionProviderSink())
{
goto ExitError;
}
if (!_AddTextProcessorEngine())
{
goto ExitError;
}
return S_OK;
ExitError:
Deactivate();
return E_FAIL;
}
//+---------------------------------------------------------------------------
//
// ITfTextInputProcessorEx::Deactivate
//
//----------------------------------------------------------------------------
STDAPI CSampleIME::Deactivate()
{
if (_pCompositionProcessorEngine)
{
delete _pCompositionProcessorEngine;
_pCompositionProcessorEngine = nullptr;
}
ITfContext* pContext = _pContext;
if (_pContext)
{
pContext->AddRef();
_EndComposition(_pContext);
}
if (_pCandidateListUIPresenter)
{
delete _pCandidateListUIPresenter;
_pCandidateListUIPresenter = nullptr;
if (pContext)
{
pContext->Release();
}
_candidateMode = CANDIDATE_NONE;
_isCandidateWithWildcard = FALSE;
}
_UninitFunctionProviderSink();
_UninitThreadFocusSink();
_UninitActiveLanguageProfileNotifySink();
_UninitKeyEventSink();
_UninitThreadMgrEventSink();
CCompartment CompartmentKeyboardOpen(_pThreadMgr, _tfClientId, GUID_COMPARTMENT_KEYBOARD_OPENCLOSE);
CompartmentKeyboardOpen._ClearCompartment();
CCompartment CompartmentDoubleSingleByte(_pThreadMgr, _tfClientId, Global::SampleIMEGuidCompartmentDoubleSingleByte);
CompartmentDoubleSingleByte._ClearCompartment();
CCompartment CompartmentPunctuation(_pThreadMgr, _tfClientId, Global::SampleIMEGuidCompartmentPunctuation);
CompartmentDoubleSingleByte._ClearCompartment();
if (_pThreadMgr != nullptr)
{
_pThreadMgr->Release();
}
_tfClientId = TF_CLIENTID_NULL;
if (_pDocMgrLastFocused)
{
_pDocMgrLastFocused->Release();
_pDocMgrLastFocused = nullptr;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// ITfFunctionProvider::GetType
//
//----------------------------------------------------------------------------
HRESULT CSampleIME::GetType(__RPC__out GUID *pguid)
{
HRESULT hr = E_INVALIDARG;
if (pguid)
{
*pguid = Global::SampleIMECLSID;
hr = S_OK;
}
return hr;
}
//+---------------------------------------------------------------------------
//
// ITfFunctionProvider::::GetDescription
//
//----------------------------------------------------------------------------
HRESULT CSampleIME::GetDescription(__RPC__deref_out_opt BSTR *pbstrDesc)
{
HRESULT hr = E_INVALIDARG;
if (pbstrDesc != nullptr)
{
*pbstrDesc = nullptr;
hr = E_NOTIMPL;
}
return hr;
}
//+---------------------------------------------------------------------------
//
// ITfFunctionProvider::::GetFunction
//
//----------------------------------------------------------------------------
HRESULT CSampleIME::GetFunction(__RPC__in REFGUID rguid, __RPC__in REFIID riid, __RPC__deref_out_opt IUnknown **ppunk)
{
HRESULT hr = E_NOINTERFACE;
if ((IsEqualGUID(rguid, GUID_NULL))
&& (IsEqualGUID(riid, __uuidof(ITfFnSearchCandidateProvider))))
{
hr = _pITfFnSearchCandidateProvider->QueryInterface(riid, (void**)ppunk);
}
else if (IsEqualGUID(rguid, GUID_NULL))
{
hr = QueryInterface(riid, (void **)ppunk);
}
return hr;
}
//+---------------------------------------------------------------------------
//
// ITfFunction::GetDisplayName
//
//----------------------------------------------------------------------------
HRESULT CSampleIME::GetDisplayName(_Out_ BSTR *pbstrDisplayName)
{
HRESULT hr = E_INVALIDARG;
if (pbstrDisplayName != nullptr)
{
*pbstrDisplayName = nullptr;
hr = E_NOTIMPL;
}
return hr;
}
//+---------------------------------------------------------------------------
//
// ITfFnGetPreferredTouchKeyboardLayout::GetLayout
// The tkblayout will be Optimized layout.
//----------------------------------------------------------------------------
HRESULT CSampleIME::GetLayout(_Out_ TKBLayoutType *ptkblayoutType, _Out_ WORD *pwPreferredLayoutId)
{
HRESULT hr = E_INVALIDARG;
if ((ptkblayoutType != nullptr) && (pwPreferredLayoutId != nullptr))
{
*ptkblayoutType = TKBLT_OPTIMIZED;
*pwPreferredLayoutId = TKBL_OPT_SIMPLIFIED_CHINESE_PINYIN;
hr = S_OK;
}
return hr;
}