STDMETHODIMP CSearchCandidateProvider::GetSearchCandidates(BSTR bstrQuery, BSTR bstrApplicationID, _Outptr_result_maybenull_ ITfCandidateList **pplist) { bstrApplicationID;bstrQuery; HRESULT hr = E_FAIL; *pplist = nullptr; if (nullptr == _pTip) { return hr; } CCompositionProcessorEngine* pCompositionProcessorEngine = ((CSampleIME*)_pTip)->GetCompositionProcessorEngine(); if (nullptr == pCompositionProcessorEngine) { return hr; } CSampleImeArray<CCandidateListItem> candidateList; pCompositionProcessorEngine->GetCandidateList(&candidateList, TRUE, FALSE); int cCand = min(candidateList.Count(), FAKECANDIDATENUMBER); if (0 < cCand) { hr = CTipCandidateList::CreateInstance(pplist, cCand); if (FAILED(hr)) { return hr; } for (int iCand = 0; iCand < cCand; iCand++) { ITfCandidateString* pCandStr = nullptr; CTipCandidateString::CreateInstance(IID_ITfCandidateString, (void**)&pCandStr); ((CTipCandidateString*)pCandStr)->SetIndex(iCand); ((CTipCandidateString*)pCandStr)->SetString(candidateList.GetAt(iCand)->_ItemString.Get(), candidateList.GetAt(iCand)->_ItemString.GetLength()); ((CTipCandidateList*)(*pplist))->SetCandidate(&pCandStr); } } hr = S_OK; return hr; }
VOID CBaseDictionaryEngine::MergeSortByFindKeyCode(_Inout_ CSampleImeArray<CCandidateListItem> *pItemList, int leftRange, int rightRange) { int candidateCount = CalculateCandidateCount(leftRange, rightRange); if (candidateCount > 2) { int mid = leftRange + (candidateCount / 2); MergeSortByFindKeyCode(pItemList, leftRange, mid); MergeSortByFindKeyCode(pItemList, mid, rightRange); CSampleImeArray<CCandidateListItem> ListItemTemp; int leftRangeTemp = 0; int midTemp = 0; for (leftRangeTemp = leftRange, midTemp = mid; leftRangeTemp != mid || midTemp != rightRange;) { CStringRange* psrgLeftTemp = nullptr; CStringRange* psrgMidTemp = nullptr; psrgLeftTemp = &pItemList->GetAt(leftRangeTemp)->_FindKeyCode; psrgMidTemp = &pItemList->GetAt(midTemp)->_FindKeyCode; CCandidateListItem* pLI = nullptr; pLI = ListItemTemp.Append(); if (pLI) { if (leftRangeTemp == mid) { *pLI = *pItemList->GetAt(midTemp++); } else if (midTemp == rightRange || CStringRange::Compare(_locale, psrgLeftTemp, psrgMidTemp) != CSTR_GREATER_THAN) { *pLI = *pItemList->GetAt(leftRangeTemp++); } else { *pLI = *pItemList->GetAt(midTemp++); } } } leftRangeTemp = leftRange; for (UINT count = 0; count < ListItemTemp.Count(); count++) { *pItemList->GetAt(leftRangeTemp++) = *ListItemTemp.GetAt(count); } } else if (candidateCount == 2) { CStringRange *psrgLeft = nullptr; CStringRange *psrgLeftNext = nullptr; psrgLeft = &pItemList->GetAt(leftRange )->_FindKeyCode; psrgLeftNext = &pItemList->GetAt(leftRange+1)->_FindKeyCode; if (CStringRange::Compare(_locale, psrgLeft, psrgLeftNext) == CSTR_GREATER_THAN) { CCandidateListItem ListItem; ListItem = *pItemList->GetAt(leftRange); *pItemList->GetAt(leftRange ) = *pItemList->GetAt(leftRange+1); *pItemList->GetAt(leftRange+1) = ListItem; } } }
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; }