STDAPI WeaselTSF::DoEditSession(TfEditCookie ec) { ITfInsertAtSelection *pInsertAtSelection; ITfRange *pRange; TF_SELECTION tfSelection; if (_pEditSessionContext->QueryInterface(IID_ITfInsertAtSelection, (LPVOID *) &pInsertAtSelection) != S_OK) return E_FAIL; /* insert the text */ if (pInsertAtSelection->InsertTextAtSelection(ec, 0, _pEditSessionText, _cEditSessionText, &pRange) != S_OK) { pInsertAtSelection->Release(); return E_FAIL; } /* update the selection to an insertion point just past the inserted text. */ pRange->Collapse(ec, TF_ANCHOR_END); tfSelection.range = pRange; tfSelection.style.ase = TF_AE_NONE; tfSelection.style.fInterimChar = FALSE; _pEditSessionContext->SetSelection(ec, 1, &tfSelection); pRange->Release(); pInsertAtSelection->Release(); return S_OK; }
void InsertTextAtSelection(TfEditCookie ec, ITfContext *pContext, const WCHAR *pchText, ULONG cchText) { ITfInsertAtSelection *pInsertAtSelection; ITfRange *pRange; TF_SELECTION tfSelection; // we need a special interface to insert text at the selection if (pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pInsertAtSelection) != S_OK) return; // insert the text if (pInsertAtSelection->InsertTextAtSelection(ec, 0, pchText, cchText, &pRange) != S_OK) goto Exit; // update the selection, we'll make it an insertion point just past // the inserted text. pRange->Collapse(ec, TF_ANCHOR_END); tfSelection.range = pRange; tfSelection.style.ase = TF_AE_NONE; tfSelection.style.fInterimChar = FALSE; pContext->SetSelection(ec, 1, &tfSelection); pRange->Release(); Exit: pInsertAtSelection->Release(); }
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::_SetInputString(TfEditCookie ec, _In_ ITfContext *pContext, _Out_opt_ ITfRange *pRange, _In_ const std::wstring &pstrAddString, BOOL exist_composing) { ITfRange* pRangeInsert = nullptr; if (!exist_composing) { _InsertAtSelection(ec, pContext, pstrAddString, &pRangeInsert); if (pRangeInsert == nullptr) { return S_OK; } pRange = pRangeInsert; } if (pRange != nullptr) { pRange->SetText(ec, 0, pstrAddString.c_str(), pstrAddString.length()); } /* sets GUID_PROP_LANGID */ _SetCompositionLanguage(ec, pContext); /* sets GUID_PROP_ATTRIBUTE */ _SetCompositionDisplayAttributes(ec, pContext, _gaDisplayAttributeInput); // update the selection, we'll make it an insertion point just past // the inserted text. ITfRange* pSelection = nullptr; TF_SELECTION sel; if ((pRange != nullptr) && (pRange->Clone(&pSelection) == S_OK)) { pSelection->Collapse(ec, TF_ANCHOR_END); sel.range = pSelection; sel.style.ase = TF_AE_NONE; sel.style.fInterimChar = FALSE; pContext->SetSelection(ec, 1, &sel); pSelection->Release(); } if (pRangeInsert) { pRangeInsert->Release(); } return S_OK; }
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(); }
HRESULT CTextService::_HandleCharShift(TfEditCookie ec, ITfContext *pContext) { if(showentry || (!inputkey && !kana.empty() && roman.empty())) { _EndCompletionList(ec, pContext); //leave composition cursoridx = kana.size(); _Update(ec, pContext, TRUE); if(pContext != NULL) { ITfRange *pRange; if(_IsComposing() && _pComposition->GetRange(&pRange) == S_OK) { pRange->Collapse(ec, TF_ANCHOR_END); _pComposition->ShiftStart(ec, pRange); SafeRelease(&pRange); } } _ResetStatus(); } return S_OK; }
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 CDIME::_SetInputString(TfEditCookie ec, _In_ ITfContext *pContext, _Out_opt_ ITfRange *pRange, _In_ CStringRange *pstrAddString, BOOL exist_composing) { debugPrint(L"CDIME::_SetInputString() exist_composing = %x", exist_composing); ITfRange* pRangeInsert = nullptr; HRESULT hr = S_OK; if (!exist_composing) { _InsertAtSelection(ec, pContext, pstrAddString, &pRangeInsert); if (pRangeInsert == nullptr) { return hr; } pRange = pRangeInsert; } if (pRange != nullptr) { hr = pRange->SetText(ec, 0, pstrAddString->Get(), (LONG)pstrAddString->GetLength()); if (FAILED(hr)) { debugPrint(L"CDIME::_SetInputString() pRange->SetText() failed with hr = %x", hr); goto exit; } } if (!_SetCompositionLanguage(ec, pContext)) { debugPrint(L"CDIME::_SetInputString() _SetCompositionLanguage failed"); hr = E_FAIL; goto exit; } if (!_SetCompositionDisplayAttributes(ec, pContext, _gaDisplayAttributeInput)) { debugPrint(L"CDIME::_SetInputString() _SetCompositionDisplayAttributes() failed"); hr = E_FAIL; goto exit; } // update the selection, we'll make it an insertion point just past // the inserted text. ITfRange* pSelection = nullptr; TF_SELECTION sel; if ((pRange != nullptr) && (pRange->Clone(&pSelection) == S_OK)) { hr = pSelection->Collapse(ec, TF_ANCHOR_END); if (FAILED(hr)) { debugPrint(L"CDIME::_SetInputString() pSelection->Collapse() failed, hr = %x", hr); goto exit; } sel.range = pSelection; sel.style.ase = TF_AE_NONE; sel.style.fInterimChar = FALSE; pContext->SetSelection(ec, 1, &sel); pSelection->Release(); } exit: if (pRangeInsert) pRangeInsert->Release(); return hr; }