1305 lines
34 KiB
C++
1305 lines
34 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 "SampleIME.h"
|
|
#include "CandidateWindow.h"
|
|
#include "CandidateListUIPresenter.h"
|
|
#include "CompositionProcessorEngine.h"
|
|
#include "SampleIMEBaseStructure.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CSampleIME candidate key handler methods
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
const int MOVEUP_ONE = -1;
|
|
const int MOVEDOWN_ONE = 1;
|
|
const int MOVETO_TOP = 0;
|
|
const int MOVETO_BOTTOM = -1;
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandleCandidateFinalize
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandleCandidateFinalize(TfEditCookie ec, _In_ ITfContext *pContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD_PTR candidateLen = 0;
|
|
const WCHAR* pCandidateString = nullptr;
|
|
CStringRange candidateString;
|
|
|
|
if (nullptr == _pCandidateListUIPresenter)
|
|
{
|
|
goto NoPresenter;
|
|
}
|
|
|
|
candidateLen = _pCandidateListUIPresenter->_GetSelectedCandidateString(&pCandidateString);
|
|
|
|
candidateString.Set(pCandidateString, candidateLen);
|
|
|
|
if (candidateLen)
|
|
{
|
|
hr = _AddComposingAndChar(ec, pContext, &candidateString);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
NoPresenter:
|
|
|
|
_HandleComplete(ec, pContext);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandleCandidateConvert
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandleCandidateConvert(TfEditCookie ec, _In_ ITfContext *pContext)
|
|
{
|
|
return _HandleCandidateWorker(ec, pContext);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandleCandidateWorker
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandleCandidateWorker(TfEditCookie ec, _In_ ITfContext *pContext)
|
|
{
|
|
HRESULT hrReturn = E_FAIL;
|
|
DWORD_PTR candidateLen = 0;
|
|
const WCHAR* pCandidateString = nullptr;
|
|
BSTR pbstr = nullptr;
|
|
CStringRange candidateString;
|
|
CSampleImeArray<CCandidateListItem> candidatePhraseList;
|
|
|
|
if (nullptr == _pCandidateListUIPresenter)
|
|
{
|
|
hrReturn = S_OK;
|
|
goto Exit;
|
|
}
|
|
|
|
candidateLen = _pCandidateListUIPresenter->_GetSelectedCandidateString(&pCandidateString);
|
|
if (0 == candidateLen)
|
|
{
|
|
hrReturn = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
candidateString.Set(pCandidateString, candidateLen);
|
|
|
|
BOOL fMakePhraseFromText = _pCompositionProcessorEngine->IsMakePhraseFromText();
|
|
if (fMakePhraseFromText)
|
|
{
|
|
_pCompositionProcessorEngine->GetCandidateStringInConverted(candidateString, &candidatePhraseList);
|
|
LCID locale = _pCompositionProcessorEngine->GetLocale();
|
|
|
|
_pCandidateListUIPresenter->RemoveSpecificCandidateFromList(locale, candidatePhraseList, candidateString);
|
|
}
|
|
|
|
// We have a candidate list if candidatePhraseList.Cnt is not 0
|
|
// If we are showing reverse conversion, use CCandidateListUIPresenter
|
|
CANDIDATE_MODE tempCandMode = CANDIDATE_NONE;
|
|
CCandidateListUIPresenter* pTempCandListUIPresenter = nullptr;
|
|
if (candidatePhraseList.Count())
|
|
{
|
|
tempCandMode = CANDIDATE_WITH_NEXT_COMPOSITION;
|
|
|
|
pTempCandListUIPresenter = new (std::nothrow) CCandidateListUIPresenter(this, Global::AtomCandidateWindow,
|
|
CATEGORY_CANDIDATE,
|
|
_pCompositionProcessorEngine->GetCandidateListIndexRange(),
|
|
FALSE);
|
|
if (nullptr == pTempCandListUIPresenter)
|
|
{
|
|
hrReturn = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// call _Start*Line for CCandidateListUIPresenter or CReadingLine
|
|
// we don't cache the document manager object so get it from pContext.
|
|
ITfDocumentMgr* pDocumentMgr = nullptr;
|
|
HRESULT hrStartCandidateList = E_FAIL;
|
|
if (pContext->GetDocumentMgr(&pDocumentMgr) == S_OK)
|
|
{
|
|
ITfRange* pRange = nullptr;
|
|
if (_pComposition->GetRange(&pRange) == S_OK)
|
|
{
|
|
if (pTempCandListUIPresenter)
|
|
{
|
|
hrStartCandidateList = pTempCandListUIPresenter->_StartCandidateList(_tfClientId, pDocumentMgr, pContext, ec, pRange, _pCompositionProcessorEngine->GetCandidateWindowWidth());
|
|
}
|
|
|
|
pRange->Release();
|
|
}
|
|
pDocumentMgr->Release();
|
|
}
|
|
|
|
// set up candidate list if it is being shown
|
|
if (SUCCEEDED(hrStartCandidateList))
|
|
{
|
|
pTempCandListUIPresenter->_SetTextColor(RGB(0, 0x80, 0), GetSysColor(COLOR_WINDOW)); // Text color is green
|
|
pTempCandListUIPresenter->_SetFillColor((HBRUSH)(COLOR_WINDOW+1)); // Background color is window
|
|
pTempCandListUIPresenter->_SetText(&candidatePhraseList, FALSE);
|
|
|
|
// Add composing character
|
|
hrReturn = _AddComposingAndChar(ec, pContext, &candidateString);
|
|
|
|
// close candidate list
|
|
if (_pCandidateListUIPresenter)
|
|
{
|
|
_pCandidateListUIPresenter->_EndCandidateList();
|
|
delete _pCandidateListUIPresenter;
|
|
_pCandidateListUIPresenter = nullptr;
|
|
|
|
_candidateMode = CANDIDATE_NONE;
|
|
_isCandidateWithWildcard = FALSE;
|
|
}
|
|
|
|
if (hrReturn == S_OK)
|
|
{
|
|
// copy temp candidate
|
|
_pCandidateListUIPresenter = pTempCandListUIPresenter;
|
|
|
|
_candidateMode = tempCandMode;
|
|
_isCandidateWithWildcard = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hrReturn = _HandleCandidateFinalize(ec, pContext);
|
|
}
|
|
|
|
if (pbstr)
|
|
{
|
|
SysFreeString(pbstr);
|
|
}
|
|
|
|
Exit:
|
|
return hrReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandleCandidateArrowKey
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandleCandidateArrowKey(TfEditCookie ec, _In_ ITfContext *pContext, _In_ KEYSTROKE_FUNCTION keyFunction)
|
|
{
|
|
ec;
|
|
pContext;
|
|
|
|
_pCandidateListUIPresenter->AdviseUIChangedByArrowKey(keyFunction);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandleCandidateSelectByNumber
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandleCandidateSelectByNumber(TfEditCookie ec, _In_ ITfContext *pContext, _In_ UINT uCode)
|
|
{
|
|
int iSelectAsNumber = _pCompositionProcessorEngine->GetCandidateListIndexRange()->GetIndex(uCode);
|
|
if (iSelectAsNumber == -1)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
if (_pCandidateListUIPresenter)
|
|
{
|
|
if (_pCandidateListUIPresenter->_SetSelectionInPage(iSelectAsNumber))
|
|
{
|
|
return _HandleCandidateConvert(ec, pContext);
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandlePhraseFinalize
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandlePhraseFinalize(TfEditCookie ec, _In_ ITfContext *pContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DWORD phraseLen = 0;
|
|
const WCHAR* pPhraseString = nullptr;
|
|
|
|
phraseLen = (DWORD)_pCandidateListUIPresenter->_GetSelectedCandidateString(&pPhraseString);
|
|
|
|
CStringRange phraseString;
|
|
phraseString.Set(pPhraseString, phraseLen);
|
|
|
|
if (phraseLen)
|
|
{
|
|
if ((hr = _AddCharAndFinalize(ec, pContext, &phraseString)) != S_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
_HandleComplete(ec, pContext);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandlePhraseArrowKey
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandlePhraseArrowKey(TfEditCookie ec, _In_ ITfContext *pContext, _In_ KEYSTROKE_FUNCTION keyFunction)
|
|
{
|
|
ec;
|
|
pContext;
|
|
|
|
_pCandidateListUIPresenter->AdviseUIChangedByArrowKey(keyFunction);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _HandlePhraseSelectByNumber
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSampleIME::_HandlePhraseSelectByNumber(TfEditCookie ec, _In_ ITfContext *pContext, _In_ UINT uCode)
|
|
{
|
|
int iSelectAsNumber = _pCompositionProcessorEngine->GetCandidateListIndexRange()->GetIndex(uCode);
|
|
if (iSelectAsNumber == -1)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
if (_pCandidateListUIPresenter)
|
|
{
|
|
if (_pCandidateListUIPresenter->_SetSelectionInPage(iSelectAsNumber))
|
|
{
|
|
return _HandlePhraseFinalize(ec, pContext);
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCandidateListUIPresenter class
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCandidateListUIPresenter::CCandidateListUIPresenter(_In_ CSampleIME *pTextService, ATOM atom, KEYSTROKE_CATEGORY Category, _In_ CCandidateRange *pIndexRange, BOOL hideWindow) : CTfTextLayoutSink(pTextService)
|
|
{
|
|
_atom = atom;
|
|
|
|
_pIndexRange = pIndexRange;
|
|
|
|
_parentWndHandle = nullptr;
|
|
_pCandidateWnd = nullptr;
|
|
|
|
_Category = Category;
|
|
|
|
_updatedFlags = 0;
|
|
|
|
_uiElementId = (DWORD)-1;
|
|
_isShowMode = TRUE; // store return value from BeginUIElement
|
|
_hideWindow = hideWindow; // Hide window flag from [Configuration] CandidateList.Phrase.HideWindow
|
|
|
|
_pTextService = pTextService;
|
|
_pTextService->AddRef();
|
|
|
|
_refCount = 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCandidateListUIPresenter::~CCandidateListUIPresenter()
|
|
{
|
|
_EndCandidateList();
|
|
_pTextService->Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::IUnknown::QueryInterface
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::QueryInterface(REFIID riid, _Outptr_ void **ppvObj)
|
|
{
|
|
if (CTfTextLayoutSink::QueryInterface(riid, ppvObj) == S_OK)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
if (ppvObj == nullptr)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppvObj = nullptr;
|
|
|
|
if (IsEqualIID(riid, IID_ITfUIElement) ||
|
|
IsEqualIID(riid, IID_ITfCandidateListUIElement))
|
|
{
|
|
*ppvObj = (ITfCandidateListUIElement*)this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfCandidateListUIElementBehavior))
|
|
{
|
|
*ppvObj = (ITfCandidateListUIElementBehavior*)this;
|
|
}
|
|
else if (IsEqualIID(riid, __uuidof(ITfIntegratableCandidateListUIElement)))
|
|
{
|
|
*ppvObj = (ITfIntegratableCandidateListUIElement*)this;
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::IUnknown::AddRef
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) CCandidateListUIPresenter::AddRef()
|
|
{
|
|
CTfTextLayoutSink::AddRef();
|
|
return ++_refCount;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::IUnknown::Release
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) CCandidateListUIPresenter::Release()
|
|
{
|
|
CTfTextLayoutSink::Release();
|
|
|
|
LONG cr = --_refCount;
|
|
|
|
assert(_refCount >= 0);
|
|
|
|
if (_refCount == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return cr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::ITfUIElement::GetDescription
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetDescription(BSTR *pbstr)
|
|
{
|
|
if (pbstr)
|
|
{
|
|
*pbstr = SysAllocString(L"Cand");
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::ITfUIElement::GetGUID
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetGUID(GUID *pguid)
|
|
{
|
|
*pguid = Global::SampleIMEGuidCandUIElement;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::ITfUIElement::Show
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::Show(BOOL showCandidateWindow)
|
|
{
|
|
if (showCandidateWindow)
|
|
{
|
|
ToShowCandidateWindow();
|
|
}
|
|
else
|
|
{
|
|
ToHideCandidateWindow();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CCandidateListUIPresenter::ToShowCandidateWindow()
|
|
{
|
|
if (_hideWindow)
|
|
{
|
|
_pCandidateWnd->_Show(FALSE);
|
|
}
|
|
else
|
|
{
|
|
_MoveWindowToTextExt();
|
|
|
|
_pCandidateWnd->_Show(TRUE);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CCandidateListUIPresenter::ToHideCandidateWindow()
|
|
{
|
|
if (_pCandidateWnd)
|
|
{
|
|
_pCandidateWnd->_Show(FALSE);
|
|
}
|
|
|
|
_updatedFlags = TF_CLUIE_SELECTION | TF_CLUIE_CURRENTPAGE;
|
|
_UpdateUIElement();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::ITfUIElement::IsShown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::IsShown(BOOL *pIsShow)
|
|
{
|
|
*pIsShow = _pCandidateWnd->_IsWindowVisible();
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::GetUpdatedFlags
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetUpdatedFlags(DWORD *pdwFlags)
|
|
{
|
|
*pdwFlags = _updatedFlags;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::GetDocumentMgr
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetDocumentMgr(ITfDocumentMgr **ppdim)
|
|
{
|
|
*ppdim = nullptr;
|
|
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::GetCount
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetCount(UINT *pCandidateCount)
|
|
{
|
|
if (_pCandidateWnd)
|
|
{
|
|
*pCandidateCount = _pCandidateWnd->_GetCount();
|
|
}
|
|
else
|
|
{
|
|
*pCandidateCount = 0;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::GetSelection
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetSelection(UINT *pSelectedCandidateIndex)
|
|
{
|
|
if (_pCandidateWnd)
|
|
{
|
|
*pSelectedCandidateIndex = _pCandidateWnd->_GetSelection();
|
|
}
|
|
else
|
|
{
|
|
*pSelectedCandidateIndex = 0;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::GetString
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetString(UINT uIndex, BSTR *pbstr)
|
|
{
|
|
if (!_pCandidateWnd || (uIndex > _pCandidateWnd->_GetCount()))
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
DWORD candidateLen = 0;
|
|
const WCHAR* pCandidateString = nullptr;
|
|
|
|
candidateLen = _pCandidateWnd->_GetCandidateString(uIndex, &pCandidateString);
|
|
|
|
*pbstr = (candidateLen == 0) ? nullptr : SysAllocStringLen(pCandidateString, candidateLen);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::GetPageIndex
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetPageIndex(UINT *pIndex, UINT uSize, UINT *puPageCnt)
|
|
{
|
|
if (!_pCandidateWnd)
|
|
{
|
|
if (pIndex)
|
|
{
|
|
*pIndex = 0;
|
|
}
|
|
*puPageCnt = 0;
|
|
return S_OK;
|
|
}
|
|
return _pCandidateWnd->_GetPageIndex(pIndex, uSize, puPageCnt);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::SetPageIndex
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::SetPageIndex(UINT *pIndex, UINT uPageCnt)
|
|
{
|
|
if (!_pCandidateWnd)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
return _pCandidateWnd->_SetPageIndex(pIndex, uPageCnt);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElement::GetCurrentPage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetCurrentPage(UINT *puPage)
|
|
{
|
|
if (!_pCandidateWnd)
|
|
{
|
|
*puPage = 0;
|
|
return S_OK;
|
|
}
|
|
return _pCandidateWnd->_GetCurrentPage(puPage);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElementBehavior::SetSelection
|
|
// It is related of the mouse clicking behavior upon the suggestion window
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::SetSelection(UINT nIndex)
|
|
{
|
|
if (_pCandidateWnd)
|
|
{
|
|
_pCandidateWnd->_SetSelection(nIndex);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElementBehavior::Finalize
|
|
// It is related of the mouse clicking behavior upon the suggestion window
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::Finalize(void)
|
|
{
|
|
_CandidateChangeNotification(CAND_ITEM_SELECT);
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfCandidateListUIElementBehavior::Abort
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::Abort(void)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfIntegratableCandidateListUIElement::SetIntegrationStyle
|
|
// To show candidateNumbers on the suggestion window
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::SetIntegrationStyle(GUID guidIntegrationStyle)
|
|
{
|
|
return (guidIntegrationStyle == GUID_INTEGRATIONSTYLE_SEARCHBOX) ? S_OK : E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfIntegratableCandidateListUIElement::GetSelectionStyle
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::GetSelectionStyle(_Out_ TfIntegratableCandidateListSelectionStyle *ptfSelectionStyle)
|
|
{
|
|
*ptfSelectionStyle = STYLE_ACTIVE_SELECTION;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfIntegratableCandidateListUIElement::OnKeyDown
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::OnKeyDown(_In_ WPARAM wParam, _In_ LPARAM lParam, _Out_ BOOL *pIsEaten)
|
|
{
|
|
wParam;
|
|
lParam;
|
|
|
|
*pIsEaten = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfIntegratableCandidateListUIElement::ShowCandidateNumbers
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::ShowCandidateNumbers(_Out_ BOOL *pIsShow)
|
|
{
|
|
*pIsShow = TRUE;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ITfIntegratableCandidateListUIElement::FinalizeExactCompositionString
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCandidateListUIPresenter::FinalizeExactCompositionString()
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _StartCandidateList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateListUIPresenter::_StartCandidateList(TfClientId tfClientId, _In_ ITfDocumentMgr *pDocumentMgr, _In_ ITfContext *pContextDocument, TfEditCookie ec, _In_ ITfRange *pRangeComposition, UINT wndWidth)
|
|
{
|
|
pDocumentMgr;tfClientId;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (FAILED(_StartLayout(pContextDocument, ec, pRangeComposition)))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
BeginUIElement();
|
|
|
|
hr = MakeCandidateWindow(pContextDocument, wndWidth);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
Show(_isShowMode);
|
|
|
|
RECT rcTextExt;
|
|
if (SUCCEEDED(_GetTextExt(&rcTextExt)))
|
|
{
|
|
_LayoutChangeNotification(&rcTextExt);
|
|
}
|
|
|
|
Exit:
|
|
if (FAILED(hr))
|
|
{
|
|
_EndCandidateList();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _EndCandidateList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateListUIPresenter::_EndCandidateList()
|
|
{
|
|
EndUIElement();
|
|
|
|
DisposeCandidateWindow();
|
|
|
|
_EndLayout();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetText
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateListUIPresenter::_SetText(_In_ CSampleImeArray<CCandidateListItem> *pCandidateList, BOOL isAddFindKeyCode)
|
|
{
|
|
AddCandidateToCandidateListUI(pCandidateList, isAddFindKeyCode);
|
|
|
|
SetPageIndexWithScrollInfo(pCandidateList);
|
|
|
|
if (_isShowMode)
|
|
{
|
|
_pCandidateWnd->_InvalidateRect();
|
|
}
|
|
else
|
|
{
|
|
_updatedFlags = TF_CLUIE_COUNT |
|
|
TF_CLUIE_SELECTION |
|
|
TF_CLUIE_STRING |
|
|
TF_CLUIE_PAGEINDEX |
|
|
TF_CLUIE_CURRENTPAGE;
|
|
_UpdateUIElement();
|
|
}
|
|
}
|
|
|
|
void CCandidateListUIPresenter::AddCandidateToCandidateListUI(_In_ CSampleImeArray<CCandidateListItem> *pCandidateList, BOOL isAddFindKeyCode)
|
|
{
|
|
for (UINT index = 0; index < pCandidateList->Count(); index++)
|
|
{
|
|
_pCandidateWnd->_AddString(pCandidateList->GetAt(index), isAddFindKeyCode);
|
|
}
|
|
}
|
|
|
|
void CCandidateListUIPresenter::SetPageIndexWithScrollInfo(_In_ CSampleImeArray<CCandidateListItem> *pCandidateList)
|
|
{
|
|
UINT candCntInPage = _pIndexRange->Count();
|
|
UINT bufferSize = pCandidateList->Count() / candCntInPage + 1;
|
|
UINT* puPageIndex = new (std::nothrow) UINT[ bufferSize ];
|
|
if (puPageIndex != nullptr)
|
|
{
|
|
for (UINT i = 0; i < bufferSize; i++)
|
|
{
|
|
puPageIndex[i] = i * candCntInPage;
|
|
}
|
|
|
|
_pCandidateWnd->_SetPageIndex(puPageIndex, bufferSize);
|
|
delete [] puPageIndex;
|
|
}
|
|
_pCandidateWnd->_SetScrollInfo(pCandidateList->Count(), candCntInPage); // nMax:range of max, nPage:number of items in page
|
|
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _ClearList
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateListUIPresenter::_ClearList()
|
|
{
|
|
_pCandidateWnd->_ClearList();
|
|
_pCandidateWnd->_InvalidateRect();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetTextColor
|
|
// _SetFillColor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateListUIPresenter::_SetTextColor(COLORREF crColor, COLORREF crBkColor)
|
|
{
|
|
_pCandidateWnd->_SetTextColor(crColor, crBkColor);
|
|
}
|
|
|
|
void CCandidateListUIPresenter::_SetFillColor(HBRUSH hBrush)
|
|
{
|
|
_pCandidateWnd->_SetFillColor(hBrush);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _GetSelectedCandidateString
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD_PTR CCandidateListUIPresenter::_GetSelectedCandidateString(_Outptr_result_maybenull_ const WCHAR **ppwchCandidateString)
|
|
{
|
|
return _pCandidateWnd->_GetSelectedCandidateString(ppwchCandidateString);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _MoveSelection
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateListUIPresenter::_MoveSelection(_In_ int offSet)
|
|
{
|
|
BOOL ret = _pCandidateWnd->_MoveSelection(offSet, TRUE);
|
|
if (ret)
|
|
{
|
|
if (_isShowMode)
|
|
{
|
|
_pCandidateWnd->_InvalidateRect();
|
|
}
|
|
else
|
|
{
|
|
_updatedFlags = TF_CLUIE_SELECTION;
|
|
_UpdateUIElement();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _SetSelection
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateListUIPresenter::_SetSelection(_In_ int selectedIndex)
|
|
{
|
|
BOOL ret = _pCandidateWnd->_SetSelection(selectedIndex, TRUE);
|
|
if (ret)
|
|
{
|
|
if (_isShowMode)
|
|
{
|
|
_pCandidateWnd->_InvalidateRect();
|
|
}
|
|
else
|
|
{
|
|
_updatedFlags = TF_CLUIE_SELECTION |
|
|
TF_CLUIE_CURRENTPAGE;
|
|
_UpdateUIElement();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _MovePage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCandidateListUIPresenter::_MovePage(_In_ int offSet)
|
|
{
|
|
BOOL ret = _pCandidateWnd->_MovePage(offSet, TRUE);
|
|
if (ret)
|
|
{
|
|
if (_isShowMode)
|
|
{
|
|
_pCandidateWnd->_InvalidateRect();
|
|
}
|
|
else
|
|
{
|
|
_updatedFlags = TF_CLUIE_SELECTION |
|
|
TF_CLUIE_CURRENTPAGE;
|
|
_UpdateUIElement();
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _MoveWindowToTextExt
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCandidateListUIPresenter::_MoveWindowToTextExt()
|
|
{
|
|
RECT rc;
|
|
|
|
if (FAILED(_GetTextExt(&rc)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
_pCandidateWnd->_Move(rc.left, rc.bottom);
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _LayoutChangeNotification
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID CCandidateListUIPresenter::_LayoutChangeNotification(_In_ RECT *lpRect)
|
|
{
|
|
RECT rectCandidate = {0, 0, 0, 0};
|
|
POINT ptCandidate = {0, 0};
|
|
|
|
_pCandidateWnd->_GetClientRect(&rectCandidate);
|
|
_pCandidateWnd->_GetWindowExtent(lpRect, &rectCandidate, &ptCandidate);
|
|
_pCandidateWnd->_Move(ptCandidate.x, ptCandidate.y);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _LayoutDestroyNotification
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID CCandidateListUIPresenter::_LayoutDestroyNotification()
|
|
{
|
|
_EndCandidateList();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _CandidateChangeNotifiction
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateListUIPresenter::_CandidateChangeNotification(_In_ enum CANDWND_ACTION action)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
TfClientId tfClientId = _pTextService->_GetClientId();
|
|
ITfThreadMgr* pThreadMgr = nullptr;
|
|
ITfDocumentMgr* pDocumentMgr = nullptr;
|
|
ITfContext* pContext = nullptr;
|
|
|
|
_KEYSTROKE_STATE KeyState;
|
|
KeyState.Category = _Category;
|
|
KeyState.Function = FUNCTION_FINALIZE_CANDIDATELIST;
|
|
|
|
if (CAND_ITEM_SELECT != action)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pThreadMgr = _pTextService->_GetThreadMgr();
|
|
if (nullptr == pThreadMgr)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = pThreadMgr->GetFocus(&pDocumentMgr);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = pDocumentMgr->GetTop(&pContext);
|
|
if (FAILED(hr))
|
|
{
|
|
pDocumentMgr->Release();
|
|
goto Exit;
|
|
}
|
|
|
|
CKeyHandlerEditSession *pEditSession = new (std::nothrow) CKeyHandlerEditSession(_pTextService, pContext, 0, 0, KeyState);
|
|
if (nullptr != pEditSession)
|
|
{
|
|
HRESULT hrSession = S_OK;
|
|
hr = pContext->RequestEditSession(tfClientId, pEditSession, TF_ES_SYNC | TF_ES_READWRITE, &hrSession);
|
|
if (hrSession == TF_E_SYNCHRONOUS || hrSession == TS_E_READONLY)
|
|
{
|
|
hr = pContext->RequestEditSession(tfClientId, pEditSession, TF_ES_ASYNC | TF_ES_READWRITE, &hrSession);
|
|
}
|
|
pEditSession->Release();
|
|
}
|
|
|
|
pContext->Release();
|
|
pDocumentMgr->Release();
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _CandWndCallback
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
// static
|
|
HRESULT CCandidateListUIPresenter::_CandWndCallback(_In_ void *pv, _In_ enum CANDWND_ACTION action)
|
|
{
|
|
CCandidateListUIPresenter* fakeThis = (CCandidateListUIPresenter*)pv;
|
|
|
|
return fakeThis->_CandidateChangeNotification(action);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _UpdateUIElement
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateListUIPresenter::_UpdateUIElement()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ITfThreadMgr* pThreadMgr = _pTextService->_GetThreadMgr();
|
|
if (nullptr == pThreadMgr)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
ITfUIElementMgr* pUIElementMgr = nullptr;
|
|
|
|
hr = pThreadMgr->QueryInterface(IID_ITfUIElementMgr, (void **)&pUIElementMgr);
|
|
if (hr == S_OK)
|
|
{
|
|
pUIElementMgr->UpdateUIElement(_uiElementId);
|
|
pUIElementMgr->Release();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnSetThreadFocus
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateListUIPresenter::OnSetThreadFocus()
|
|
{
|
|
if (_isShowMode)
|
|
{
|
|
Show(TRUE);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnKillThreadFocus
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCandidateListUIPresenter::OnKillThreadFocus()
|
|
{
|
|
if (_isShowMode)
|
|
{
|
|
Show(FALSE);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
void CCandidateListUIPresenter::RemoveSpecificCandidateFromList(_In_ LCID Locale, _Inout_ CSampleImeArray<CCandidateListItem> &candidateList, _In_ CStringRange &candidateString)
|
|
{
|
|
for (UINT index = 0; index < candidateList.Count();)
|
|
{
|
|
CCandidateListItem* pLI = candidateList.GetAt(index);
|
|
|
|
if (CStringRange::Compare(Locale, &candidateString, &pLI->_ItemString) == CSTR_EQUAL)
|
|
{
|
|
candidateList.RemoveAt(index);
|
|
continue;
|
|
}
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
void CCandidateListUIPresenter::AdviseUIChangedByArrowKey(_In_ KEYSTROKE_FUNCTION arrowKey)
|
|
{
|
|
switch (arrowKey)
|
|
{
|
|
case FUNCTION_MOVE_UP:
|
|
{
|
|
_MoveSelection(MOVEUP_ONE);
|
|
break;
|
|
}
|
|
case FUNCTION_MOVE_DOWN:
|
|
{
|
|
_MoveSelection(MOVEDOWN_ONE);
|
|
break;
|
|
}
|
|
case FUNCTION_MOVE_PAGE_UP:
|
|
{
|
|
_MovePage(MOVEUP_ONE);
|
|
break;
|
|
}
|
|
case FUNCTION_MOVE_PAGE_DOWN:
|
|
{
|
|
_MovePage(MOVEDOWN_ONE);
|
|
break;
|
|
}
|
|
case FUNCTION_MOVE_PAGE_TOP:
|
|
{
|
|
_SetSelection(MOVETO_TOP);
|
|
break;
|
|
}
|
|
case FUNCTION_MOVE_PAGE_BOTTOM:
|
|
{
|
|
_SetSelection(MOVETO_BOTTOM);
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
HRESULT CCandidateListUIPresenter::BeginUIElement()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ITfThreadMgr* pThreadMgr = _pTextService->_GetThreadMgr();
|
|
if (nullptr ==pThreadMgr)
|
|
{
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
ITfUIElementMgr* pUIElementMgr = nullptr;
|
|
hr = pThreadMgr->QueryInterface(IID_ITfUIElementMgr, (void **)&pUIElementMgr);
|
|
if (hr == S_OK)
|
|
{
|
|
pUIElementMgr->BeginUIElement(this, &_isShowMode, &_uiElementId);
|
|
pUIElementMgr->Release();
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CCandidateListUIPresenter::EndUIElement()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
ITfThreadMgr* pThreadMgr = _pTextService->_GetThreadMgr();
|
|
if ((nullptr == pThreadMgr) || (-1 == _uiElementId))
|
|
{
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
ITfUIElementMgr* pUIElementMgr = nullptr;
|
|
hr = pThreadMgr->QueryInterface(IID_ITfUIElementMgr, (void **)&pUIElementMgr);
|
|
if (hr == S_OK)
|
|
{
|
|
pUIElementMgr->EndUIElement(_uiElementId);
|
|
pUIElementMgr->Release();
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CCandidateListUIPresenter::MakeCandidateWindow(_In_ ITfContext *pContextDocument, _In_ UINT wndWidth)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (nullptr != _pCandidateWnd)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
_pCandidateWnd = new (std::nothrow) CCandidateWindow(_CandWndCallback, this, _pIndexRange, _pTextService->_IsStoreAppMode());
|
|
if (_pCandidateWnd == nullptr)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
HWND parentWndHandle = nullptr;
|
|
ITfContextView* pView = nullptr;
|
|
if (SUCCEEDED(pContextDocument->GetActiveView(&pView)))
|
|
{
|
|
pView->GetWnd(&parentWndHandle);
|
|
}
|
|
|
|
if (!_pCandidateWnd->_Create(_atom, wndWidth, parentWndHandle))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
void CCandidateListUIPresenter::DisposeCandidateWindow()
|
|
{
|
|
if (nullptr == _pCandidateWnd)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_pCandidateWnd->_Destroy();
|
|
|
|
delete _pCandidateWnd;
|
|
_pCandidateWnd = nullptr;
|
|
} |