STDAPI CEndCompositionEditSession::DoEditSession(TfEditCookie ec) { /* Clear the dummy text we set before, if any. */ ITfRange *pCompositionRange; if (_pComposition->GetRange(&pCompositionRange) == S_OK) pCompositionRange->SetText(ec, 0, L"", 0); _pComposition->EndComposition(ec); _pTextService->OnCompositionTerminated(ec, _pComposition); return S_OK; }
STDAPI CStartCompositionEditSession::DoEditSession(TfEditCookie ec) { HRESULT hr = E_FAIL; ITfInsertAtSelection *pInsertAtSelection = NULL; ITfRange *pRangeComposition = NULL; if (_pContext->QueryInterface(IID_ITfInsertAtSelection, (LPVOID *) &pInsertAtSelection) != S_OK) goto Exit; if (pInsertAtSelection->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, NULL, 0, &pRangeComposition) != S_OK) goto Exit; ITfContextComposition *pContextComposition = NULL; ITfComposition *pComposition = NULL; if (_pContext->QueryInterface(IID_ITfContextComposition, (LPVOID *) &pContextComposition) != S_OK) goto Exit; if ((pContextComposition->StartComposition(ec, pRangeComposition, _pTextService, &pComposition) == S_OK) && (pComposition != NULL)) { _pTextService->_SetComposition(pComposition); /* set selection */ /* WORKAROUND: * CUAS does not provide a correct GetTextExt() position unless the composition is filled with characters. * So we insert a dummy space character here. * This is the same workaround used by Microsoft Pinyin IME (New Experience). */ if (_fCUASWorkaroundEnabled) { pRangeComposition->SetText(ec, TF_ST_CORRECTION, L" ", 1); pRangeComposition->Collapse(ec, TF_ANCHOR_START); } TF_SELECTION tfSelection; tfSelection.range = pRangeComposition; tfSelection.style.ase = TF_AE_NONE; tfSelection.style.fInterimChar = FALSE; _pContext->SetSelection(ec, 1, &tfSelection); } Exit: if (pContextComposition != NULL) pContextComposition->Release(); if (pRangeComposition != NULL) pRangeComposition->Release(); if (pInsertAtSelection != NULL) pInsertAtSelection->Release(); return hr; }
HRESULT CSampleIME::_RemoveDummyCompositionForComposing(TfEditCookie ec, _In_ ITfComposition *pComposition) { HRESULT hr = S_OK; ITfRange* pRange = nullptr; if (pComposition) { hr = pComposition->GetRange(&pRange); if (SUCCEEDED(hr)) { pRange->SetText(ec, 0, nullptr, 0); pRange->Release(); } } return hr; }
void ToggleCase(TfEditCookie ec, ITfRange *pRange, BOOL fIgnoreRangeEnd) { ITfRange *pRangeToggle; ULONG cch; ULONG i; DWORD dwFlags; WCHAR achText[64]; // backup the current range if (pRange->Clone(&pRangeToggle) != S_OK) return; dwFlags = TF_TF_MOVESTART | (fIgnoreRangeEnd ? TF_TF_IGNOREEND : 0); while (TRUE) { // grab the next block of chars if (pRange->GetText(ec, dwFlags, achText, ARRAYSIZE(achText), &cch) != S_OK) break; // out of text? if (cch == 0) break; // toggle the case for (i=0; i<cch; i++) { achText[i] = ToggleChar(achText[i]); } // shift pRangeToggle so it covers just the text we read if (pRangeToggle->ShiftEndToRange(ec, pRange, TF_ANCHOR_START) != S_OK) break; // replace the text pRangeToggle->SetText(ec, 0, achText, cch); // prepare for next iteration pRangeToggle->Collapse(ec, TF_ANCHOR_END); } pRangeToggle->Release(); }
STDAPI CInlinePreeditEditSession::DoEditSession(TfEditCookie ec) { std::wstring preedit = _context->preedit.str; ITfRange *pRangeComposition = NULL; if ((_pComposition->GetRange(&pRangeComposition)) != S_OK) goto Exit; if ((pRangeComposition->SetText(ec, 0, preedit.c_str(), preedit.length())) != S_OK) goto Exit; int sel_start = 0, sel_end = 0; /* TODO: Check the availability and correctness of these values */ for (size_t i = 0; i < _context->preedit.attributes.size(); i++) if (_context->preedit.attributes.at(i).type == weasel::HIGHLIGHTED) { sel_start = _context->preedit.attributes.at(i).range.start; sel_end = _context->preedit.attributes.at(i).range.end; break; } /* Set caret */ LONG cch; TF_SELECTION tfSelection; pRangeComposition->Collapse(ec, TF_ANCHOR_START); pRangeComposition->ShiftEnd(ec, sel_end, &cch, NULL); pRangeComposition->ShiftStart(ec, sel_start, &cch, NULL); tfSelection.range = pRangeComposition; tfSelection.style.ase = TF_AE_NONE; tfSelection.style.fInterimChar = FALSE; _pContext->SetSelection(ec, 1, &tfSelection); Exit: if (pRangeComposition != NULL) pRangeComposition->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; }