HRESULT COVTSF::_HandleCompositionBackspace(TfEditCookie ec, _In_ ITfContext *pContext) { ITfRange* pRangeComposition = nullptr; TF_SELECTION tfSelection; ULONG fetched = 0; BOOL isCovered = TRUE; // Start the new (std::nothrow) compositon if there is no composition. if (!_IsComposing()) { return S_OK; } // first, test where a keystroke would go in the document if we did an insert if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1) { return S_FALSE; } // is the insertion point covered by a composition? if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition))) { isCovered = _IsRangeCovered(ec, tfSelection.range, pRangeComposition); pRangeComposition->Release(); if (!isCovered) { goto Exit; } } // // Add virtual key to composition processor engine // CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr; pCompositionProcessorEngine = _pCompositionProcessorEngine; DWORD_PTR vKeyLen = pCompositionProcessorEngine->GetVirtualKeyLength(); if (vKeyLen) { pCompositionProcessorEngine->RemoveVirtualKey(vKeyLen - 1); if (pCompositionProcessorEngine->GetVirtualKeyLength()) { _HandleCompositionInputWorker(pCompositionProcessorEngine, ec, pContext); } else { _HandleCancel(ec, pContext); } } Exit: tfSelection.range->Release(); return S_OK; }
HRESULT COVTSF::_HandleCompositionFinalize(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isCandidateList) { HRESULT hr = S_OK; if (isCandidateList && _pCandidateListUIPresenter) { // Finalize selected candidate string from CCandidateListUIPresenter DWORD_PTR candidateLen = 0; const WCHAR *pCandidateString = nullptr; candidateLen = _pCandidateListUIPresenter->_GetSelectedCandidateString(&pCandidateString); CStringRange candidateString; candidateString.Set(pCandidateString, candidateLen); if (candidateLen) { // Finalize character hr = _AddCharAndFinalize(ec, pContext, &candidateString); if (FAILED(hr)) { return hr; } } } else { // Finalize current text store strings if (_IsComposing()) { ULONG fetched = 0; TF_SELECTION tfSelection; if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1) { return S_FALSE; } ITfRange* pRangeComposition = nullptr; if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition))) { if (_IsRangeCovered(ec, tfSelection.range, pRangeComposition)) { _EndComposition(pContext); } pRangeComposition->Release(); } tfSelection.range->Release(); } } _HandleCancel(ec, pContext); return S_OK; }
STDAPI CSampleIME::OnEndEdit(__RPC__in_opt ITfContext *pContext, TfEditCookie ecReadOnly, __RPC__in_opt ITfEditRecord *pEditRecord) { BOOL isSelectionChanged; // // did the selection change? // The selection change includes the movement of caret as well. // The caret position is represent as the empty selection range when // there is no selection. // if (pEditRecord == nullptr) { return E_INVALIDARG; } if (SUCCEEDED(pEditRecord->GetSelectionStatus(&isSelectionChanged)) && isSelectionChanged) { // If the selection is moved to out side of the current composition, // we terminate the composition. This TextService supports only one // composition in one context object. if (_IsComposing()) { TF_SELECTION tfSelection; ULONG fetched = 0; if (pContext == nullptr) { return E_INVALIDARG; } if (FAILED(pContext->GetSelection(ecReadOnly, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1) { return S_FALSE; } ITfRange* pRangeComposition = nullptr; if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition))) { if (!_IsRangeCovered(ecReadOnly, tfSelection.range, pRangeComposition)) { _EndComposition(pContext); } pRangeComposition->Release(); } tfSelection.range->Release(); } } return S_OK; }
HRESULT COVTSF::_HandleCompositionInput(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch) { ITfRange* pRangeComposition = nullptr; TF_SELECTION tfSelection; ULONG fetched = 0; BOOL isCovered = TRUE; CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr; pCompositionProcessorEngine = _pCompositionProcessorEngine; if ((_pCandidateListUIPresenter != nullptr) && (_candidateMode != CANDIDATE_INCREMENTAL)) { _HandleCompositionFinalize(ec, pContext, FALSE); } // Start the new (std::nothrow) compositon if there is no composition. if (!_IsComposing()) { _StartComposition(pContext); } // first, test where a keystroke would go in the document if we did an insert if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched) != S_OK || fetched != 1) { return S_FALSE; } // is the insertion point covered by a composition? if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition))) { isCovered = _IsRangeCovered(ec, tfSelection.range, pRangeComposition); pRangeComposition->Release(); if (!isCovered) { goto Exit; } } // Add virtual key to composition processor engine pCompositionProcessorEngine->AddVirtualKey(wch); _HandleCompositionInputWorker(pCompositionProcessorEngine, ec, pContext); Exit: tfSelection.range->Release(); return S_OK; }
HRESULT CTextService::_SetText(TfEditCookie ec, ITfContext *pContext, const std::wstring &text, LONG cchCursor, LONG cchOkuri, BOOL fixed) { TF_SELECTION tfSelection; ULONG cFetched = 0; LONG cch, cchRes; if(pContext == NULL && _pCandidateList != NULL) //辞書登録用 { _pCandidateList->_SetText(text, fixed, FALSE, FALSE); return S_OK; } if(!_IsComposing()) { if(!_StartComposition(pContext)) { return S_FALSE; } } if(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) != S_OK) { return S_FALSE; } if(cFetched != 1) { SafeRelease(&tfSelection.range); return S_FALSE; } ITfRange *pRange; if(_IsComposing() && _pComposition->GetRange(&pRange) == S_OK) { if(_IsRangeCovered(ec, tfSelection.range, pRange)) { pRange->SetText(ec, 0, text.c_str(), (LONG)text.size()); // shift from end to start. // shift over mathematical operators (U+2200-U+22FF) is rejected by OneNote. if(cchCursor == 0) { cchRes = (LONG)cursoridx - (LONG)kana.size(); if((complement && okuriidx != 0) || (!cx_showmodemark && okuriidx != 0 && cursoridx <= okuriidx && cursoridx < kana.size())) { cchRes += 1; } } else { cchRes = cchCursor - (LONG)text.size(); if(cchRes > 0) { cchRes = 0; } else if(cchRes < -(LONG)text.size()) { cchRes = -(LONG)text.size(); } } tfSelection.range->ShiftEndToRange(ec, pRange, TF_ANCHOR_END); tfSelection.range->ShiftStartToRange(ec, pRange, TF_ANCHOR_END); tfSelection.range->ShiftStart(ec, cchRes, &cch, NULL); //decide cursor position tfSelection.range->Collapse(ec, TF_ANCHOR_START); pContext->SetSelection(ec, 1, &tfSelection); //composition attribute if(!fixed) { ITfRange *pRangeClone; if(pRange->Clone(&pRangeClone) == S_OK) { pRangeClone->ShiftEndToRange(ec, pRange, TF_ANCHOR_END); pRangeClone->ShiftStartToRange(ec, pRange, TF_ANCHOR_START); if(cchCursor == 0 || !showentry) { if(inputkey) { _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeInputMark); if(cx_showmodemark) { pRangeClone->ShiftStart(ec, 1, &cch, NULL); } } if(!display_attribute_series[1] || !inputkey) { _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeInputText); } if(cchOkuri != 0) { pRangeClone->ShiftStartToRange(ec, pRange, TF_ANCHOR_START); pRangeClone->ShiftStart(ec, cchOkuri, &cch, NULL); if(!display_attribute_series[2]) { _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeInputOkuri); } if(hintmode && text.find_first_of(CHAR_SKK_HINT) != std::wstring::npos) { LONG hintpos = (LONG)text.find_first_of(CHAR_SKK_HINT); if(cchOkuri < hintpos) { pRangeClone->ShiftStartToRange(ec, pRange, TF_ANCHOR_START); pRangeClone->ShiftStart(ec, hintpos, &cch, NULL); _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeInputText); } } } } else { _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeConvMark); if(cx_showmodemark) { pRangeClone->ShiftStart(ec, 1, &cch, NULL); } if(!display_attribute_series[4]) { _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeConvText); } if(cchOkuri != 0) { pRangeClone->ShiftStartToRange(ec, pRange, TF_ANCHOR_START); pRangeClone->ShiftStart(ec, cchOkuri, &cch, NULL); if(!display_attribute_series[5]) { _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeConvOkuri); } } pRangeClone->ShiftEndToRange(ec, pRange, TF_ANCHOR_END); pRangeClone->ShiftStartToRange(ec, tfSelection.range, TF_ANCHOR_END); if(!display_attribute_series[6]) { _SetCompositionDisplayAttributes(ec, pContext, pRangeClone, _gaDisplayAttributeConvAnnot); } } SafeRelease(&pRangeClone); } } // for Excel's PHONETIC function if(fixed && !text.empty()) { ITfProperty *pProperty; if(pContext->GetProperty(GUID_PROP_READING, &pProperty) == S_OK) { VARIANT var; var.vt = VT_BSTR; std::wstring phone(kana); if(okuriidx == 0) { switch(inputmode) { case im_hiragana: case im_katakana: case im_katakana_ank: //接辞 if(!abbrevmode && kana.size() >= 2) { if(kana.front() == L'>') { phone = kana.substr(1); } else if(kana.back() == L'>') { phone = kana.substr(0, kana.size() - 1); } } break; default: break; } } else { if(kana.size() > (okuriidx + 1)) { phone = kana.substr(0, okuriidx) + kana.substr(okuriidx + 1); } else if(kana.size() >= okuriidx) { phone = kana.substr(0, okuriidx); } } if(!phone.empty()) { var.bstrVal = SysAllocString(phone.c_str()); pProperty->SetValue(ec, pRange, &var); SysFreeString(var.bstrVal); } SafeRelease(&pProperty); } } } SafeRelease(&pRange); } SafeRelease(&tfSelection.range); return S_OK; }