Exemplo n.º 1
0
/* Update Composition */
void WeaselTSF::_UpdateComposition(ITfContext *pContext)
{
	// get commit string from server
	std::wstring commit;
	weasel::Status status;
	weasel::Config config;

	auto context = std::make_shared<weasel::Context>();

	weasel::ResponseParser parser(&commit, context.get(), &status, &config);

	bool ok = m_client.GetResponseData(std::ref(parser));

	if (ok)
	{
		bool composing = _IsComposing();
		if (!commit.empty())
		{
			// 修复顶字上屏的吞字问题:
			// 顶字上屏(如五笔 4 码上屏时),当候选词数 > 1 时,
			// 第 5 码输入时会将首选项顶屏。
			// 此时由于第五码的输入,composition 应是开启的,同时也要在输入处插入顶字。
			// 这里先关闭上一个字的 composition,然后为后续输入开启一个新 composition。
			// 有点 dirty 但是 it works ...
			if (composing) {
				_EndComposition(pContext);
				composing = false;
			}
			_InsertText(pContext, commit);
		}
		if (status.composing && !composing)
		{
			if (!_fCUASWorkaroundTested)
			{
				/* Test if we need to apply the workaround */
				_UpdateCompositionWindow(pContext);
			}
			else if (!_fCUASWorkaroundEnabled || config.inline_preedit)
			{
				/* Workaround not applied, update candidate window position at this point. */
				_UpdateCompositionWindow(pContext);
			}
			_StartComposition(pContext, _fCUASWorkaroundEnabled && !config.inline_preedit);
		}
		else if (!status.composing && composing) {
			_EndComposition(pContext);
			composing = false;
		}
		if (composing && config.inline_preedit)
			_ShowInlinePreedit(pContext, context);
	}
}
Exemplo n.º 2
0
STDAPI CDIME::OnCompositionTerminated(TfEditCookie ecWrite, _In_ ITfComposition *pComposition)
{
	debugPrint(L"CDIME::OnCompositionTerminated()");
	HRESULT hr = S_OK;
    ITfContext* pContext = _pContext;
   
	// Clear dummy composition
	_RemoveDummyCompositionForComposing(ecWrite, pComposition);
	
    // Clear display attribute and end composition, _EndComposition will release composition for us
     if (pContext)
    {
        pContext->AddRef();
	}
	

	_EndComposition(pContext);
	_DeleteCandidateList(TRUE, pContext);
	
	if (pContext)
	{
		pContext->Release();
        pContext = nullptr;
    }
    return hr;
}
STDAPI CTextService::OnEndEdit(ITfContext *pContext, TfEditCookie ecReadOnly, ITfEditRecord *pEditRecord)
{
    BOOL fSelectionChanged;
    IEnumTfRanges *pEnumTextChanges;
    ITfRange *pRange;

    //
    // 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->GetSelectionStatus(&fSelectionChanged) == S_OK &&
        fSelectionChanged)
    {
        // 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 cFetched;

            if (pContext->GetSelection(ecReadOnly, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) == S_OK && cFetched == 1)
            {
                ITfRange *pRangeComposition;
                // is the insertion point covered by a composition?
                if (_pComposition->GetRange(&pRangeComposition) == S_OK)
                {
                    if (!IsRangeCovered(ecReadOnly, tfSelection.range, pRangeComposition))
                    {
                       _EndComposition(pContext);
                    }

                    pRangeComposition->Release();
                }
            }
        }
    }

    // text modification?
    if (pEditRecord->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, NULL, 0, &pEnumTextChanges) == S_OK)
    {
        if (pEnumTextChanges->Next(1, &pRange, NULL) == S_OK)
        {
            //
            // pRange is the updated range.
            //

            pRange->Release();
        }

        pEnumTextChanges->Release();
    }

    return S_OK;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
BOOL WeaselIME::ProcessKeyEvent(UINT vKey, KeyInfo kinfo, const LPBYTE lpbKeyState)
{
	EZDBGONLYLOGGERPRINT("Process key event: vKey = 0x%x, kinfo = 0x%x, HIMC = 0x%x", vKey, UINT32(kinfo), m_hIMC);  
	bool accepted = false;

	if (!m_client.Echo())
	{
		m_client.Connect(launch_server);
		m_client.StartSession();
	}

	weasel::KeyEvent ke;
	if (!ConvertKeyEvent(vKey, kinfo, lpbKeyState, ke))
	{
		// unknown key event
		return FALSE;
	}

	accepted = m_client.ProcessKeyEvent(ke);

	// get commit string from server
	wstring commit;
	weasel::Status status;
	weasel::ResponseParser parser(&commit, NULL, &status);
	bool ok = m_client.GetResponseData(boost::ref(parser));

	if (ok)
	{
		if (!commit.empty())
		{
			_EndComposition(commit.c_str());
		}
		else if (status.composing != m_composing)
		{
			if (m_composing)
				_EndComposition(NULL);
			else
				_StartComposition();
		}
	}

	return (BOOL)accepted;
}
Exemplo n.º 6
0
void CDIME::OnKeyboardClosed()
{
	debugPrint(L"CDIME::OnKeyboardClosed()\n");
	// switching to English (native) mode delete the phrase candidate window before exting.
	_isChinese = FALSE;
	if(_IsComposing()) 
	{
		_EndComposition(_pContext);
	}
	_DeleteCandidateList(TRUE,_pContext);
}
Exemplo n.º 7
0
void CDIME::OnSwitchedToHalfShape()
{
	debugPrint(L"CDIME::OnSwitchedToHalfShape()\n");
	_isFullShape = FALSE;
	if(_IsComposing()) 
	{
		_EndComposition(_pContext);
	}
	_DeleteCandidateList(TRUE,_pContext);
	if (CConfig::GetDoubleSingleByteMode() != DOUBLE_SINGLE_BYTE_SHIFT_SPACE)
		CConfig::SetDoubleSingleByteMode(DOUBLE_SINGLE_BYTE_ALWAYS_SINGLE);
}
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;
}
Exemplo n.º 9
0
STDAPI CTextService::OnEndEdit(ITfContext *pic, TfEditCookie ecReadOnly, ITfEditRecord *pEditRecord)
{
	if(_IsComposing() && pic != nullptr)
	{
		ITfRange *pRange = nullptr;
		if(SUCCEEDED(_pComposition->GetRange(&pRange)) && (pRange != nullptr))
		{
			// clear when auto completion
			BOOL fEmpty = FALSE;
			if(SUCCEEDED(pRange->IsEmpty(ecReadOnly, &fEmpty)) && fEmpty)
			{
				if(!roman.empty() || !kana.empty())
				{
					_ResetStatus();
					_EndComposition(pic);
				}
			}

			// reposition candidate window
			if(_pCandidateList != nullptr)
			{
				ITfContextView *pContextView = nullptr;
				if(SUCCEEDED(pic->GetActiveView(&pContextView)) && (pContextView != nullptr))
				{
					RECT rc = {};
					BOOL fClipped;
					if(SUCCEEDED(pContextView->GetTextExt(ecReadOnly, pRange, &rc, &fClipped)))
					{
						_pCandidateList->_Move(&rc, ecReadOnly, pic);
					}

					SafeRelease(&pContextView);
				}
			}

			SafeRelease(&pRange);
		}
	}

	return S_OK;
}
Exemplo n.º 10
0
STDAPI CSampleIME::OnCompositionTerminated(TfEditCookie ecWrite, _In_ ITfComposition *pComposition)
{
    // Clear dummy composition
    _RemoveDummyCompositionForComposing(ecWrite, pComposition);

    // Clear display attribute and end composition, _EndComposition will release composition for us
    ITfContext* pContext = _pContext;
    if (pContext)
    {
        pContext->AddRef();
    }

    _EndComposition(_pContext);

    _DeleteCandidateList(FALSE, pContext);

    if (pContext)
    {
        pContext->Release();
        pContext = nullptr;
    }

    return S_OK;
}