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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
STDAPI CMarkTextService::OnEndEdit(ITfContext *pContext, TfEditCookie ecReadOnly, ITfEditRecord *pEditRecord)
{
    ITfRange *pRangeComposition;
    IEnumTfRanges *pEnumRanges;
    ITfRange *pRange;
    ITfContext *pCompositionContext;
    TF_SELECTION tfSelection;
    BOOL fResult;
    BOOL fCancelComposition;
    ULONG cFetched;

    if (_pComposition == NULL)
        return S_OK;

    // are we responsible for the edit?
    if (pContext->InWriteSession(_tfClientId, &fResult) == S_OK && fResult)
        return S_OK;

    // is this the context our composition lives in?
    if (_pComposition->GetRange(&pRangeComposition) != S_OK)
        return S_OK;

    if (pRangeComposition->GetContext(&pCompositionContext) != S_OK)
        goto Exit;

    fResult = IsEqualUnknown(pCompositionContext, pContext);

    pCompositionContext->Release();

    if (!fResult)
        goto Exit; // different context

    fCancelComposition = FALSE;

    // we're composing in this context, cancel the composition if anything suspicious happened

    // did the selection move outside the composition?
    if (pEditRecord->GetSelectionStatus(&fResult) == S_OK && fResult)
    {
        if (pContext->GetSelection(ecReadOnly, TF_DEFAULT_SELECTION, 1, &tfSelection, &cFetched) == S_OK &&
            cFetched == 1)
        {
            if (_pComposition->GetRange(&pRangeComposition) == S_OK)
            {
                fResult = IsRangeCovered(ecReadOnly, tfSelection.range, pRangeComposition);

                pRangeComposition->Release();

                if (!fResult)
                {
                    fCancelComposition = TRUE;
                }
            }
            tfSelection.range->Release();
        }
    }

    if (fCancelComposition)
        goto CancelComposition;

    // did someone else edit the document text?
    if (pEditRecord->GetTextAndPropertyUpdates(TF_GTP_INCL_TEXT, NULL, 0, &pEnumRanges) == S_OK)
    {
        // is the enumerator empty?
        if (pEnumRanges->Next(1, &pRange, NULL) == S_OK)
        {
            pRange->Release();
            fCancelComposition = TRUE;
        }
        pEnumRanges->Release();
    }

    if (fCancelComposition)
    {
CancelComposition:
        // we need a write edit session to cancel the composition
        _TerminateCompositionInContext(pContext);
    }

Exit:
    pRangeComposition->Release();
    return S_OK;
}