You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.5 KiB
162 lines
4.5 KiB
//
|
|
// editsink.cpp
|
|
//
|
|
// ITfTextEditSink implementation.
|
|
//
|
|
|
|
#include "globals.h"
|
|
#include "mark.h"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnEndEdit
|
|
//
|
|
// Called by the system whenever anyone releases a write-access document lock.
|
|
//----------------------------------------------------------------------------
|
|
|
|
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;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _InitTextEditSink
|
|
//
|
|
// Init a text edit sink on the topmost context of the document.
|
|
// Always release any previous sink.
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CMarkTextService::_InitTextEditSink(ITfDocumentMgr *pDocMgr)
|
|
{
|
|
ITfSource *pSource;
|
|
BOOL fRet;
|
|
|
|
// clear out any previous sink first
|
|
|
|
if (_dwTextEditSinkCookie != TF_INVALID_COOKIE)
|
|
{
|
|
if (_pTextEditSinkContext->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK)
|
|
{
|
|
pSource->UnadviseSink(_dwTextEditSinkCookie);
|
|
pSource->Release();
|
|
}
|
|
|
|
_pTextEditSinkContext->Release();
|
|
_pTextEditSinkContext = NULL;
|
|
_dwTextEditSinkCookie = TF_INVALID_COOKIE;
|
|
}
|
|
|
|
if (pDocMgr == NULL)
|
|
return TRUE; // caller just wanted to clear the previous sink
|
|
|
|
// setup a new sink advised to the topmost context of the document
|
|
|
|
if (pDocMgr->GetTop(&_pTextEditSinkContext) != S_OK)
|
|
return FALSE;
|
|
|
|
if (_pTextEditSinkContext == NULL)
|
|
return TRUE; // empty document, no sink possible
|
|
|
|
fRet = FALSE;
|
|
|
|
if (_pTextEditSinkContext->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK)
|
|
{
|
|
if (pSource->AdviseSink(IID_ITfTextEditSink, (ITfTextEditSink *)this, &_dwTextEditSinkCookie) == S_OK)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
_dwTextEditSinkCookie = TF_INVALID_COOKIE;
|
|
}
|
|
pSource->Release();
|
|
}
|
|
|
|
if (fRet == FALSE)
|
|
{
|
|
_pTextEditSinkContext->Release();
|
|
_pTextEditSinkContext = NULL;
|
|
}
|
|
|
|
return fRet;
|
|
}
|