Пример #1
0
HRESULT CTextService::_HandleCharacterKey(TfEditCookie ec, ITfContext *pContext, WPARAM wParam)
{
    ITfRange *pRangeComposition;
    TF_SELECTION tfSelection;
    ULONG cFetched;
    WCHAR ch;
    BOOL fCovered;

    // Start the new compositon if there is no composition.
    OutputDebugString("test compositing");
    if (!_IsComposing())
        _StartComposition(pContext);

    OutputDebugString("after test compositing");
    //
    // Assign VK_ value to the char. So the inserted the character is always
    // uppercase.
    //
    ch = (WCHAR)wParam;

    // first, test where a keystroke would go in the document if an insert is done
    if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) != S_OK || cFetched != 1)
        return S_FALSE;

    // is the insertion point covered by a composition?
    if (_pComposition->GetRange(&pRangeComposition) == S_OK)
    {
        fCovered = IsRangeCovered(ec, tfSelection.range, pRangeComposition);

        pRangeComposition->Release();

        if (!fCovered)
        {
            goto Exit;
        }
    }

    // insert the text
    // use SetText here instead of InsertTextAtSelection because a composition was already started
    //Don't allow to the app to adjust the insertion point inside the composition
    if (tfSelection.range->SetText(ec, 0, &ch, 1) != S_OK)
        goto Exit;

    // update the selection, make it an insertion point just past
    // the inserted text.
    tfSelection.range->Collapse(ec, TF_ANCHOR_END);
    pContext->SetSelection(ec, 1, &tfSelection);

    //
    // set the display attribute to the composition range.
    //
    _SetCompositionDisplayAttributes(ec, pContext, _gaDisplayAttributeInput);

Exit:
    tfSelection.range->Release();
    return S_OK;
}
HRESULT CTextService::_HandleSpaceKey(TfEditCookie ec, ITfContext *pContext)
{
    //
    // set the display attribute to the composition range.
    //
    // The real text service may have linguistic logic here and set 
    // the specific range to apply the display attribute rather than 
    // applying the display attribute to the entire composition range.
    //
    _SetCompositionDisplayAttributes(ec, pContext, _gaDisplayAttributeConverted);

    return S_OK;
}
Пример #3
0
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;
}
Пример #4
0
HRESULT CTextService::_HandleKey(TfEditCookie ec, ITfContext *pContext, WPARAM wParam)
{

    /*
     * FIXME: the following keys are not handled:
     * shift left		VK_LSHIFT
     * shift right		VK_RSHIFT
     * caps lock		VK_CAPITAL
     * page up			VK_PRIOR
     * page down		VK_NEXT
     * ctrl num
     * shift space
     * numlock num		VK_NUMLOCK
	 */

    if (('A' <= wParam && wParam <= 'Z')) {
            chewing_handle_Default(mChewingContext, wParam - 'A' + 'a');
    } else if ('0' <= wParam && wParam <= '9') {
            chewing_handle_Default(mChewingContext, wParam);
    } else {
        switch(wParam) {
            case VK_OEM_COMMA:
                chewing_handle_Default(mChewingContext, ',');
                break;

            case VK_OEM_MINUS:
                chewing_handle_Default(mChewingContext, '-');
                break;

            case VK_OEM_PERIOD:
                chewing_handle_Default(mChewingContext, '.');
                break;

            case VK_OEM_1:
                chewing_handle_Default(mChewingContext, ';');
                break;

            case VK_OEM_2:
                chewing_handle_Default(mChewingContext, '/');
                break;

            case VK_OEM_3:
                chewing_handle_Default(mChewingContext, '`');
                break;

            case VK_SPACE:
                chewing_handle_Space(mChewingContext);
                break;

            case VK_ESCAPE:
                chewing_handle_Esc(mChewingContext);
                break;

            case VK_RETURN:
                chewing_handle_Enter(mChewingContext);
                break;

            case VK_DELETE:
                chewing_handle_Del(mChewingContext);
                break;

            case VK_BACK:
                chewing_handle_Backspace(mChewingContext);
                break;

            case VK_UP:
                chewing_handle_Up(mChewingContext);
                break;

            case VK_DOWN:
                chewing_handle_Down(mChewingContext);

            case VK_LEFT:
                chewing_handle_Left(mChewingContext);
                break;

            case VK_RIGHT:
                chewing_handle_Right(mChewingContext);
                break;

            case VK_HOME:
                chewing_handle_Home(mChewingContext);
                break;

            case VK_END:
                chewing_handle_End(mChewingContext);
                break;

            default:
                return S_OK;
        }
    }

    // Remove old candidate list. We will create a new one if necessary.
    _pCandidateList->_EndCandidateList();

    ChewingCandidates candidate(mChewingContext);
    if (!candidate.IsEmpty()) {
        _SetCompositionDisplayAttributes(ec, pContext, _gaDisplayAttributeConverted);

        //
        // The document manager object is not cached. Get it from pContext.
        //
        ITfDocumentMgr *pDocumentMgr;
        if (pContext->GetDocumentMgr(&pDocumentMgr) == S_OK)
        {
            //
            // get the composition range.
            //
            ITfRange *pRange;
            if (_pComposition->GetRange(&pRange) == S_OK)
            {
                _pCandidateList->_StartCandidateList(_tfClientId, pDocumentMgr, pContext, ec, pRange, candidate);
                pRange->Release();
            }
            pDocumentMgr->Release();
        }
        return S_OK;
    }

    ChewingString commit(mChewingContext, CHEWING_STRING_COMMIT);
    if (!commit.IsEmpty()) {
        // FIXME: Need a better way to submit a string
        if (!_IsComposing())
            _StartComposition(pContext);

        ULONG cFetched;
        BOOL fCovered;
        TF_SELECTION tfSelection;

        // FIXME: Why we need this here?
        // first, test where a keystroke would go in the document if an insert is done
        if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) != S_OK || cFetched != 1)
            return S_FALSE;

        // FIXME: Why we need this here?
        // is the insertion point covered by a composition?
        ITfRange *pRangeComposition;
        if (_pComposition->GetRange(&pRangeComposition) == S_OK)
        {
            fCovered = IsRangeCovered(ec, tfSelection.range, pRangeComposition);

            pRangeComposition->Release();

            if (!fCovered)
            {
                goto End3;
            }
        }

        if (tfSelection.range->SetText(ec, 0, commit.GetString(), commit.GetLength()) != S_OK)
            goto End3;

        _TerminateComposition(ec, pContext);
End3: // FIXME: RAII?
        tfSelection.range->Release();
    }

    /*
     * Composition is mapped to preedit buffer + zuin buffer
     */
    ChewingString preedit_zuin(mChewingContext, CHEWING_STRING_PREEDIT_ZUIN);
    if (preedit_zuin.IsEmpty()) {
        // Remove composition
        if (_IsComposing())
        {
            ULONG cFetched;
            BOOL fCovered;
            TF_SELECTION tfSelection;

            // FIXME: Why we need this here?
            // first, test where a keystroke would go in the document if an insert is done
            if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) != S_OK || cFetched != 1)
                return S_FALSE;

            // FIXME: Why we need this here?
            // is the insertion point covered by a composition?
            ITfRange *pRangeComposition;
            if (_pComposition->GetRange(&pRangeComposition) == S_OK)
            {
                fCovered = IsRangeCovered(ec, tfSelection.range, pRangeComposition);

                pRangeComposition->Release();

                if (!fCovered)
                {
                    goto End;
                }
            }

            // Empties the composition
            tfSelection.range->SetText(ec, 0, L"", 0);

            _TerminateComposition(ec, pContext);
End: // FIXME: RAII?
            tfSelection.range->Release();
        }
    } else {
        if (!_IsComposing())
            _StartComposition(pContext);

        ULONG cFetched;
        BOOL fCovered;
        TF_SELECTION tfSelection;
        // FIXME: Why we need this here?
        // first, test where a keystroke would go in the document if an insert is done
        if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) != S_OK || cFetched != 1)
            return S_FALSE;

        // FIXME: Why we need this here?
        // is the insertion point covered by a composition?
        ITfRange *pRangeComposition;
        if (_pComposition->GetRange(&pRangeComposition) == S_OK)
        {
            fCovered = IsRangeCovered(ec, tfSelection.range, pRangeComposition);

            pRangeComposition->Release();

            if (!fCovered)
            {
                goto End2;
            }
        }
        if (tfSelection.range->SetText(ec, 0, preedit_zuin.GetString(), preedit_zuin.GetLength()) != S_OK)
            goto End2;

        _SetCompositionDisplayAttributes(ec, pContext, _gaDisplayAttributeInput);
End2: // FIXME: RAII?
        tfSelection.range->Release();
    }

    return S_OK;
}
Пример #5
0
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;
}
Пример #6
0
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;
}