Example #1
0
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;
}
Example #2
0
// callback from edit session for starting composition
HRESULT TextService::doStartCompositionEditSession(TfEditCookie cookie, StartCompositionEditSession* session) {
	ITfContext* context = session->context();
	ITfContextComposition* contextComposition;
	if(context->QueryInterface(IID_ITfContextComposition, (void**)&contextComposition) == S_OK) {
		// get current insertion point in the current context
		ITfRange* range = NULL;
		ITfInsertAtSelection* insertAtSelection;
		if(context->QueryInterface(IID_ITfInsertAtSelection, (void **)&insertAtSelection) == S_OK) {
			// get current selection range & insertion position (query only, did not insert any text)
			insertAtSelection->InsertTextAtSelection(cookie, TF_IAS_QUERYONLY, NULL, 0, &range);
			insertAtSelection->Release();
		}

		if(range) {
			if(contextComposition->StartComposition(cookie, range, (ITfCompositionSink*)this, &composition_) == S_OK) {
				// according to the TSF sample provided by M$, we need to reset current
				// selection here. (maybe the range is altered by StartComposition()?
				// So mysterious. TSF is absolutely overly-engineered!
				TF_SELECTION selection;
				selection.range = range;
				selection.style.ase = TF_AE_NONE;
				selection.style.fInterimChar = FALSE;
				context->SetSelection(cookie, 1, &selection);
				// we did not release composition_ object. we store it for use later
			}
			range->Release();
		}
		contextComposition->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)
{
    ITfInsertAtSelection *pInsertAtSelection = NULL;
    ITfRange *pRangeInsert = NULL;
    ITfContextComposition *pContextComposition = NULL;
    ITfComposition *pComposition = NULL;
    HRESULT hr = E_FAIL;

    // we need a special interface to insert text at the selection
    if (_pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pInsertAtSelection) != S_OK)
    {
        goto Exit;
    }

    // insert the text
    if (pInsertAtSelection->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, NULL, 0, &pRangeInsert) != S_OK)
    {
        goto Exit;
    }

    // get an interface on the context we can use to deal with compositions
    if (_pContext->QueryInterface(IID_ITfContextComposition, (void **)&pContextComposition) != S_OK)
    {
        goto Exit;
    }

    // start the new composition
    if ((pContextComposition->StartComposition(ec, pRangeInsert, _pTextService, &pComposition) == S_OK) && (pComposition != NULL))
    {
        // Store the pointer of this new composition object in the instance
        // of the CTextService class. So this instance of the CTextService
        // class can know now it is in the composition stage.
        _pTextService->_SetComposition(pComposition);

        //
        //  set selection to the adjusted range
        //
        TF_SELECTION tfSelection;
        tfSelection.range = pRangeInsert;
        tfSelection.style.ase = TF_AE_NONE;
        tfSelection.style.fInterimChar = FALSE;
        _pContext->SetSelection(ec, 1, &tfSelection);
    }

Exit:
    if (pContextComposition != NULL)
        pContextComposition->Release();

    if (pRangeInsert != NULL)
        pRangeInsert->Release();

    if (pInsertAtSelection != NULL)
        pInsertAtSelection->Release();

    return S_OK;
}
STDAPI CStartCompositionEditSession::DoEditSession(TfEditCookie ec)
{
    ITfInsertAtSelection* pInsertAtSelection = nullptr;
    ITfRange* pRangeInsert = nullptr;
    ITfContextComposition* pContextComposition = nullptr;
    ITfComposition* pComposition = nullptr;

    if (FAILED(_pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pInsertAtSelection)))
    {
        goto Exit;
    }

    if (FAILED(pInsertAtSelection->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, NULL, 0, &pRangeInsert)))
    {
        goto Exit;
    }

    if (FAILED(_pContext->QueryInterface(IID_ITfContextComposition, (void **)&pContextComposition)))
    {
        goto Exit;
    }

    if (SUCCEEDED(pContextComposition->StartComposition(ec, pRangeInsert, _pTextService, &pComposition)) && (nullptr != pComposition))
    {
        _pTextService->_SetComposition(pComposition);

        // set selection to the adjusted range
        TF_SELECTION tfSelection;
        tfSelection.range = pRangeInsert;
        tfSelection.style.ase = TF_AE_NONE;
        tfSelection.style.fInterimChar = FALSE;

        _pContext->SetSelection(ec, 1, &tfSelection);
        _pTextService->_SaveCompositionContext(_pContext);
    }

Exit:
    if (nullptr != pContextComposition)
    {
        pContextComposition->Release();
    }

    if (nullptr != pRangeInsert)
    {
        pRangeInsert->Release();
    }

    if (nullptr != pInsertAtSelection)
    {
        pInsertAtSelection->Release();
    }

    return S_OK;
}
Example #6
0
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;
}
Example #7
0
HRESULT CDIME::_InsertAtSelection(TfEditCookie ec, _In_ ITfContext *pContext, _In_ CStringRange *pstrAddString, _Outptr_ ITfRange **ppCompRange)
{
	debugPrint(L"CDIME::_InsertAtSelection()");
    ITfRange* rangeInsert = nullptr;
    ITfInsertAtSelection* pias = nullptr;
    HRESULT hr = S_OK;

    if (ppCompRange == nullptr || pContext == nullptr || pstrAddString == nullptr)
    {
		debugPrint(L"CDIME::_InsertAtSelection() failed with null ppCompRange or pContext or pstrAddstring");
        hr = E_INVALIDARG;
        goto Exit;
    }

    *ppCompRange = nullptr;

    hr = pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pias);
    if (FAILED(hr) || pias == nullptr)
    {
		debugPrint(L"CDIME::_InsertAtSelection() failed with null pias or QueryInterface failed");
        goto Exit;
    }

    hr = pias->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, pstrAddString->Get(), (LONG)pstrAddString->GetLength(), &rangeInsert);

    if ( FAILED(hr) || rangeInsert == nullptr)
    {
		debugPrint(L"CDIME::_InsertAtSelection() InsertTextAtSelection failed");
        rangeInsert = nullptr;
        pias->Release();
        goto Exit;
    }
	WCHAR rangeText[256];
	rangeText[0] = NULL;
	ULONG fetched = 0;
	hr = rangeInsert->GetText(ec, 0, rangeText, 256, &fetched);
	if (SUCCEEDED(hr) && rangeText)
		debugPrint(L"CDIME::_InsertAtSelection() text in range = %s", rangeText);
    *ppCompRange = rangeInsert;
    pias->Release();
    hr = S_OK;

Exit:
    return hr;
}
Example #8
0
STDAPI CGetTextExtentEditSession::DoEditSession(TfEditCookie ec)
{
	ITfInsertAtSelection *pInsertAtSelection = NULL;
	ITfRange *pRangeComposition = NULL;
	RECT rc;
	BOOL fClipped;
	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;

	if ((_pContextView->GetTextExt(ec, pRangeComposition, &rc, &fClipped)) == S_OK)
		_pTextService->_SetCompositionPosition(rc);

Exit:
	if (pRangeComposition != NULL)
		pRangeComposition->Release();
	if (pInsertAtSelection != NULL)
		pInsertAtSelection->Release();
	return S_OK;
}
HRESULT CSampleIME::_InsertAtSelection(TfEditCookie ec, _In_ ITfContext *pContext, _In_ const std::wstring &pstrAddString, _Outptr_ ITfRange **ppCompRange)
{
    ITfRange* rangeInsert = nullptr;
    ITfInsertAtSelection* pias = nullptr;
    HRESULT hr = S_OK;

    if (ppCompRange == nullptr)
    {
        hr = E_INVALIDARG;
        goto Exit;
    }

    *ppCompRange = nullptr;

    hr = pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pias);
    if (FAILED(hr))
    {
        goto Exit;
    }

    hr = pias->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, pstrAddString.c_str(), pstrAddString.length(), &rangeInsert);

    if ( FAILED(hr) || rangeInsert == nullptr)
    {
        rangeInsert = nullptr;
        pias->Release();
        goto Exit;
    }

    *ppCompRange = rangeInsert;
    pias->Release();
    hr = S_OK;

Exit:
    return hr;
}
STDAPI CCompositionEditSession::DoEditSession(TfEditCookie ec)
{
    ITfInsertAtSelection *pInsertAtSelection;
    ITfContextComposition *pContextComposition;
    ITfComposition *pComposition;
    ITfRange *pRangeComposition;
    ITfRange *pRangeInsert;
    ITfContext *pCompositionContext;
    HRESULT hr;
    BOOL fEqualContexts;

    // get an interface on the context we can use to deal with compositions
    if (_pContext->QueryInterface(IID_ITfContextComposition, (void **)&pContextComposition) != S_OK)
        return E_FAIL;

    hr = E_FAIL;

    pInsertAtSelection = NULL;

    if (_pMark->_IsComposing())
    {
        // we have a composition, let's terminate it
        
        // it's possible our current composition is in another context...let's find out
        fEqualContexts = TRUE;
        if (_pMark->_GetComposition()->GetRange(&pRangeComposition) == S_OK)
        {
            if (pRangeComposition->GetContext(&pCompositionContext) == S_OK)
            {
                fEqualContexts = IsEqualUnknown(pCompositionContext, _pContext);
                if (!fEqualContexts)
                {
                    // need an edit session in the composition context
                    _pMark->_TerminateCompositionInContext(pCompositionContext);
                }
                pCompositionContext->Release();
            }
            pRangeComposition->Release();
        }

        // if the composition is in pContext, we already have an edit cookie
        if (fEqualContexts)
        {
            _pMark->_TerminateComposition(ec);
        }
    }
    else
    {
        // let's start a new composition over the current selection
        // this is totally contrived, a real text service would have
        // some meaningful logic to trigger this

        // first, test where a keystroke would go in the document if we did an insert
        // we need a special interface to insert text at the selection
        if (_pContext->QueryInterface(IID_ITfInsertAtSelection, (void **)&pInsertAtSelection) != S_OK)
        {
            pInsertAtSelection = NULL;
            goto Exit;
        }

        if (pInsertAtSelection->InsertTextAtSelection(ec, TF_IAS_QUERYONLY, NULL, 0, &pRangeInsert) != S_OK)
            goto Exit;

        // start the composition
        if (pContextComposition->StartComposition(ec, pRangeInsert, _pMark, &pComposition) != S_OK)
        {
            pComposition = NULL;
        }

        pRangeInsert->Release();

        // _pComposition may be NULL even if StartComposition return S_OK, this mean the application
        // rejected the composition

        if (pComposition != NULL)
        {
            _pMark->_SetComposition(pComposition);
            // underline the composition text to give the user some feedback UI
            _pMark->_SetCompositionDisplayAttributes(ec);
        }
    }

    // if we make it here, we've succeeded
    hr = S_OK;

Exit:
    SafeRelease(pInsertAtSelection);
    pContextComposition->Release();

    return hr;
}