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

221 lines
4.6 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 "TfTextLayoutSink.h"
#include "SampleIME.h"
#include "GetTextExtentEditSession.h"
CTfTextLayoutSink::CTfTextLayoutSink(_In_ CSampleIME *pTextService)
{
_pTextService = pTextService;
_pTextService->AddRef();
_pRangeComposition = nullptr;
_pContextDocument = nullptr;
_tfEditCookie = TF_INVALID_EDIT_COOKIE;
_dwCookieTextLayoutSink = TF_INVALID_COOKIE;
_refCount = 1;
DllAddRef();
}
CTfTextLayoutSink::~CTfTextLayoutSink()
{
if (_pTextService)
{
_pTextService->Release();
}
DllRelease();
}
STDAPI CTfTextLayoutSink::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
{
if (ppvObj == nullptr)
{
return E_INVALIDARG;
}
*ppvObj = nullptr;
if (IsEqualIID(riid, IID_IUnknown) ||
IsEqualIID(riid, IID_ITfTextLayoutSink))
{
*ppvObj = (ITfTextLayoutSink *)this;
}
if (*ppvObj)
{
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDAPI_(ULONG) CTfTextLayoutSink::AddRef()
{
return ++_refCount;
}
STDAPI_(ULONG) CTfTextLayoutSink::Release()
{
LONG cr = --_refCount;
assert(_refCount >= 0);
if (_refCount == 0)
{
delete this;
}
return cr;
}
//+---------------------------------------------------------------------------
//
// ITfTextLayoutSink::OnLayoutChange
//
//----------------------------------------------------------------------------
STDAPI CTfTextLayoutSink::OnLayoutChange(_In_ ITfContext *pContext, TfLayoutCode lcode, _In_ ITfContextView *pContextView)
{
// we're interested in only document context.
if (pContext != _pContextDocument)
{
return S_OK;
}
switch (lcode)
{
case TF_LC_CHANGE:
{
CGetTextExtentEditSession* pEditSession = nullptr;
pEditSession = new (std::nothrow) CGetTextExtentEditSession(_pTextService, pContext, pContextView, _pRangeComposition, this);
if (nullptr != (pEditSession))
{
HRESULT hr = S_OK;
pContext->RequestEditSession(_pTextService->_GetClientId(), pEditSession, TF_ES_SYNC | TF_ES_READ, &hr);
pEditSession->Release();
}
}
break;
case TF_LC_DESTROY:
_LayoutDestroyNotification();
break;
}
return S_OK;
}
HRESULT CTfTextLayoutSink::_StartLayout(_In_ ITfContext *pContextDocument, TfEditCookie ec, _In_ ITfRange *pRangeComposition)
{
_pContextDocument = pContextDocument;
_pContextDocument->AddRef();
_pRangeComposition = pRangeComposition;
_pRangeComposition->AddRef();
_tfEditCookie = ec;
return _AdviseTextLayoutSink();
}
VOID CTfTextLayoutSink::_EndLayout()
{
if (_pRangeComposition)
{
_pRangeComposition->Release();
_pRangeComposition = nullptr;
}
if (_pContextDocument)
{
_UnadviseTextLayoutSink();
_pContextDocument->Release();
_pContextDocument = nullptr;
}
}
HRESULT CTfTextLayoutSink::_AdviseTextLayoutSink()
{
HRESULT hr = S_OK;
ITfSource* pSource = nullptr;
hr = _pContextDocument->QueryInterface(IID_ITfSource, (void **)&pSource);
if (FAILED(hr))
{
return hr;
}
hr = pSource->AdviseSink(IID_ITfTextLayoutSink, (ITfTextLayoutSink *)this, &_dwCookieTextLayoutSink);
if (FAILED(hr))
{
pSource->Release();
return hr;
}
pSource->Release();
return hr;
}
HRESULT CTfTextLayoutSink::_UnadviseTextLayoutSink()
{
HRESULT hr = S_OK;
ITfSource* pSource = nullptr;
if (nullptr == _pContextDocument)
{
return E_FAIL;
}
hr = _pContextDocument->QueryInterface(IID_ITfSource, (void **)&pSource);
if (FAILED(hr))
{
return hr;
}
hr = pSource->UnadviseSink(_dwCookieTextLayoutSink);
if (FAILED(hr))
{
pSource->Release();
return hr;
}
pSource->Release();
return hr;
}
HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect)
{
HRESULT hr = S_OK;
BOOL isClipped = TRUE;
ITfContextView* pContextView = nullptr;
hr = _pContextDocument->GetActiveView(&pContextView);
if (FAILED(hr))
{
return hr;
}
if (FAILED(hr = pContextView->GetTextExt(_tfEditCookie, _pRangeComposition, lpRect, &isClipped)))
{
return hr;
}
pContextView->Release();
return S_OK;
}