Leaked source code of windows server 2003
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.
 
 
 
 
 
 

939 lines
26 KiB

//
// tsi.cpp
//
// CTextStoreImpl
//
#include "private.h"
#include "tsi.h"
#include "immxutil.h"
#include "tsdo.h"
#include "tsattrs.h"
#include "ic.h"
#include "rprop.h"
#define TSI_TOKEN 0x01010101
DBG_ID_INSTANCE(CTextStoreImpl);
/* 012313d4-b1e7-476a-bf88-173a316572fb */
extern const IID IID_PRIV_CTSI = { 0x012313d4, 0xb1e7, 0x476a, {0xbf, 0x88, 0x17, 0x3a, 0x31, 0x65, 0x72, 0xfb} };
//+---------------------------------------------------------------------------
//
// ctor
//
//----------------------------------------------------------------------------
CTextStoreImpl::CTextStoreImpl(CInputContext *pic)
{
Dbg_MemSetThisNameID(TEXT("CTextStoreImpl"));
Assert(_fPendingWriteReq == FALSE);
Assert(_dwlt == 0);
_pic = pic;
}
//+---------------------------------------------------------------------------
//
// dtor
//
//----------------------------------------------------------------------------
CTextStoreImpl::~CTextStoreImpl()
{
cicMemFree(_pch);
}
//+---------------------------------------------------------------------------
//
// AdviseSink
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::AdviseSink(REFIID riid, IUnknown *punk, DWORD dwMask)
{
if (_ptss != NULL)
{
Assert(0); // cicero shouldn't do this
return CONNECT_E_ADVISELIMIT;
}
if (FAILED(punk->QueryInterface(IID_ITextStoreACPSink, (void **)&_ptss)))
return E_UNEXPECTED;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// UnadviseSink
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::UnadviseSink(IUnknown *punk)
{
Assert(_ptss == punk); // we're dealing with cicero, this should always hold
SafeReleaseClear(_ptss);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetSelection
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetSelection(ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched)
{
if (pcFetched == NULL)
return E_INVALIDARG;
*pcFetched = 0;
if (ulIndex > 1 && ulIndex != TS_DEFAULT_SELECTION)
return E_INVALIDARG; // index too high
if (ulCount == 0 || ulIndex == 1)
return S_OK;
if (pSelection == NULL)
return E_INVALIDARG;
pSelection[0] = _Sel;
*pcFetched = 1;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// SetSelection
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::SetSelection(ULONG ulCount, const TS_SELECTION_ACP *pSelection)
{
Assert(ulCount > 0); // should have been caught by caller
Assert(pSelection != NULL); // should have been caught by caller
Assert(pSelection[0].acpStart >= 0);
Assert(pSelection[0].acpEnd >= pSelection[0].acpStart);
if (ulCount > 1)
return E_FAIL; // don't support disjoint sel
if (pSelection[0].acpEnd > _cch)
return TS_E_INVALIDPOS;
_Sel = pSelection[0];
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetText
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetText(LONG acpStart, LONG acpEnd,
WCHAR *pchPlain, ULONG cchPlainReq, ULONG *pcchPlainOut,
TS_RUNINFO *prgRunInfo, ULONG ulRunInfoReq, ULONG *pulRunInfoOut,
LONG *pacpNext)
{
ULONG cch;
*pcchPlainOut = 0;
*pulRunInfoOut = 0;
*pacpNext = acpStart;
if (acpStart < 0 || acpStart > _cch)
return TS_E_INVALIDPOS;
// get a count of acp chars requested
cch = (acpEnd >= acpStart) ? acpEnd - acpStart : _cch - acpStart;
// since we're plain text, we can also simply clip by the plaintext buffer len
if (cchPlainReq > 0) // if they don't want plain text we won't clip!
{
cch = min(cch, cchPlainReq);
}
// check for eod
if (acpStart + cch > (ULONG)_cch)
{
cch = _cch - acpStart;
}
if (ulRunInfoReq > 0 && cch > 0)
{
*pulRunInfoOut = 1;
prgRunInfo[0].uCount = cch;
prgRunInfo[0].type = TS_RT_PLAIN;
}
if (cchPlainReq > 0)
{
// we're a plain text buffer, so we always copy all the requested chars
*pcchPlainOut = cch;
memcpy(pchPlain, _pch + acpStart, cch*sizeof(WCHAR));
}
*pacpNext = acpStart + cch;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// SetText
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::SetText(DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, ULONG cch, TS_TEXTCHANGE *pChange)
{
int iSizeRange;
int cchAdjust;
TS_STATUS tss;
WCHAR *pch = NULL;
// Since we know our only caller will be cicero, we can assert rather than
// returning failure codes.
Assert(acpStart >= 0);
Assert(acpStart <= acpEnd);
if (acpEnd > _cch)
return TS_E_INVALIDPOS;
if (_owner != NULL &&
_owner->GetStatus(&tss) == S_OK &&
(tss.dwDynamicFlags & TS_SD_READONLY))
{
return TS_E_READONLY;
}
//
// Check mapped app property for TSATTRID_Text_ReadOnly.
//
CProperty *pProp;
BOOL fReadOnly = FALSE;
if (SUCCEEDED(_pic->GetMappedAppProperty(TSATTRID_Text_ReadOnly, &pProp)))
{
ITfRangeACP *range;
if (SUCCEEDED(_pic->CreateRange(acpStart, acpEnd, &range)))
{
IEnumTfRanges *pEnumRanges;
if (SUCCEEDED(pProp->EnumRanges(BACKDOOR_EDIT_COOKIE,
&pEnumRanges,
range)))
{
ITfRange *rangeTmp;
while (pEnumRanges->Next(1, &rangeTmp, NULL) == S_OK)
{
VARIANT var;
if (pProp->GetValue(BACKDOOR_EDIT_COOKIE, rangeTmp, &var) == S_OK)
{
if (var.lVal != 0)
{
fReadOnly = TRUE;
break;
}
}
rangeTmp->Release();
}
pEnumRanges->Release();
}
range->Release();
}
pProp->Release();
}
if (fReadOnly)
{
return TS_E_READONLY;
}
// this will all be rewritten for the gap buffer, so keep it simple for now.
// delete the ranage, then insert the new text.
iSizeRange = acpEnd - acpStart;
cchAdjust = (LONG)cch - iSizeRange;
if (cchAdjust > 0)
{
// if we need to alloc more memory, try now, to handle failure gracefully
if ((pch = (_pch == NULL) ? (WCHAR *)cicMemAlloc((_cch + cchAdjust)*sizeof(WCHAR)) :
(WCHAR *)cicMemReAlloc(_pch, (_cch + cchAdjust)*sizeof(WCHAR))) == NULL)
{
return E_OUTOFMEMORY;
}
// we're all set
_pch = pch;
}
//
// shift existing text to the right of the range
//
memmove(_pch + acpStart + cch, _pch + acpStart + iSizeRange, (_cch - iSizeRange - acpStart)*sizeof(WCHAR));
//
// now fill in the gap
//
if (pchText != NULL)
{
memcpy(_pch + acpStart, pchText, cch*sizeof(WCHAR));
}
//
// update our buffer size
//
_cch += cchAdjust;
Assert(_cch >= 0);
// if we shrank, try to realloc a smaller buffer (otherwise we alloc'd above)
if (cchAdjust < 0)
{
if (_cch == 0)
{
cicMemFree(_pch);
_pch = NULL;
}
else if (pch = (WCHAR *)cicMemReAlloc(_pch, _cch*sizeof(WCHAR)))
{
_pch = pch;
}
}
// handle the out params
pChange->acpStart = acpStart;
pChange->acpOldEnd = acpEnd;
pChange->acpNewEnd = acpEnd + cchAdjust;
//
// update the selection
//
_Sel.acpStart = AdjustAnchor(acpStart, acpEnd, cch, _Sel.acpStart, FALSE);
_Sel.acpEnd = AdjustAnchor(acpStart, acpEnd, cch, _Sel.acpEnd, TRUE);
Assert(_Sel.acpStart >= 0);
Assert(_Sel.acpStart <= _Sel.acpEnd);
Assert(_Sel.acpEnd <= _cch);
// never need to call OnTextChange because we have only one adaptor
// and this class never calls SetText internally
// do the OnDelta
//_ptss->OnTextChange(acpStart, acpEnd, acpStart + cch);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetFormattedText
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetFormattedText(LONG acpStart, LONG acpEnd, IDataObject **ppDataObject)
{
CTFDataObject *pcdo;
Assert(acpStart >= 0 && acpEnd <= _cch);
Assert(acpStart <= acpEnd);
Assert(ppDataObject != NULL);
*ppDataObject = NULL;
pcdo = new CTFDataObject;
if (pcdo == NULL)
return E_OUTOFMEMORY;
if (FAILED(pcdo->_SetData(&_pch[acpStart], acpEnd - acpStart)))
{
Assert(0);
pcdo->Release();
return E_FAIL;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetEmbedded
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetEmbedded(LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk)
{
return E_NOTIMPL;
}
//+---------------------------------------------------------------------------
//
// InsertEmbedded
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::InsertEmbedded(DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, TS_TEXTCHANGE *pChange)
{
ULONG cch;
FORMATETC fe;
STGMEDIUM sm;
WCHAR *pch;
HRESULT hr;
Assert(acpStart <= acpEnd);
Assert((dwFlags & ~TS_IE_CORRECTION) == 0);
Assert(pDataObject != NULL);
Assert(pChange != NULL);
memset(pChange, 0, sizeof(*pChange));
fe.cfFormat = CF_UNICODETEXT;
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
if (FAILED(pDataObject->GetData(&fe, &sm)))
return TS_E_FORMAT;
if (sm.hGlobal == NULL)
return E_FAIL;
pch = (WCHAR *)GlobalLock(sm.hGlobal);
cch = wcslen(pch);
hr = SetText(dwFlags, acpStart, acpEnd, pch, cch, pChange);
GlobalUnlock(sm.hGlobal);
ReleaseStgMedium(&sm);
return hr;
}
//+---------------------------------------------------------------------------
//
// RequestLock
//
//----------------------------------------------------------------------------
#define TS_LF_WRITE (TS_LF_READWRITE & ~TS_LF_READ)
STDAPI CTextStoreImpl::RequestLock(DWORD dwLockFlags, HRESULT *phrSession)
{
Assert(phrSession != NULL); // caller should have caught this
if (_dwlt != 0)
{
*phrSession = E_UNEXPECTED;
// this is a reentrant call
// only one case is legal
if ((_dwlt & TS_LF_WRITE) ||
!(dwLockFlags & TS_LF_WRITE) ||
(dwLockFlags & TS_LF_SYNC))
{
Assert(0); // bogus reentrant lock req!
return E_UNEXPECTED;
}
_fPendingWriteReq = TRUE;
*phrSession = TS_S_ASYNC;
return S_OK;
}
_dwlt = dwLockFlags;
*phrSession = _ptss->OnLockGranted(dwLockFlags);
if (_fPendingWriteReq)
{
_dwlt = TS_LF_READWRITE;
_fPendingWriteReq = FALSE;
if (_ptss != NULL) // might be NULL if we're disconnected during the OnLockGranted above
{
_ptss->OnLockGranted(TS_LF_READWRITE);
}
}
_dwlt = 0;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetStatus
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetStatus(TS_STATUS *pdcs)
{
HRESULT hr;
if (_owner != NULL)
{
hr = _owner->GetStatus(pdcs);
// only let the owner ctl certain bits
if (hr == S_OK)
{
pdcs->dwDynamicFlags &= (TF_SD_READONLY | TF_SD_LOADING);
pdcs->dwStaticFlags &= (TF_SS_TRANSITORY);
}
else
{
memset(pdcs, 0, sizeof(*pdcs));
}
}
else
{
hr = S_OK;
memset(pdcs, 0, sizeof(*pdcs));
}
return hr;
}
//+---------------------------------------------------------------------------
//
// QueryInsert
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::QueryInsert(LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, LONG *pacpResultEnd)
{
Assert(acpTestStart >= 0);
Assert(acpTestStart <= acpTestEnd);
Assert(acpTestEnd <= _cch);
// default text store does not support overtype, and the selection is always replaced
*pacpResultStart = acpTestStart;
*pacpResultEnd = acpTestEnd;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Unlock
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetEndACP(LONG *pacp)
{
*pacp = _cch;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetACPFromPoint
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetACPFromPoint(TsViewCookie vcView, const POINT *pt, DWORD dwFlags, LONG *pacp)
{
Assert(vcView == TSI_ACTIVE_VIEW_COOKIE); // default tsi only has a single view
if (_owner == NULL)
return E_FAIL; // who ever owns the ic hasn't bothered to give us a callback....
return _owner->GetACPFromPoint(pt, dwFlags, pacp);
}
//+---------------------------------------------------------------------------
//
// GetScreenExt
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetScreenExt(TsViewCookie vcView, RECT *prc)
{
Assert(vcView == TSI_ACTIVE_VIEW_COOKIE); // default tsi only has a single view
if (_owner == NULL)
return E_FAIL; // who ever owns the ic hasn't bothered to give us a callback....
return _owner->GetScreenExt(prc);
}
//+---------------------------------------------------------------------------
//
// GetTextExt
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetTextExt(TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, BOOL *pfClipped)
{
Assert(vcView == TSI_ACTIVE_VIEW_COOKIE); // default tsi only has a single view
if (_owner == NULL)
return E_FAIL; // who ever owns the ic hasn't bothered to give us a callback....
return _owner->GetTextExt(acpStart, acpEnd, prc, pfClipped);
}
//+---------------------------------------------------------------------------
//
// GetWnd
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetWnd(TsViewCookie vcView, HWND *phwnd)
{
Assert(vcView == TSI_ACTIVE_VIEW_COOKIE); // default tsi only has a single view
Assert(phwnd != NULL); // should have caught this in the ic
*phwnd = NULL;
if (_owner == NULL)
return E_FAIL; // who ever owns the ic hasn't bothered to give us a callback....
return _owner->GetWnd(phwnd);
}
//+---------------------------------------------------------------------------
//
// _LoadAttr
//
//----------------------------------------------------------------------------
HRESULT CTextStoreImpl::_LoadAttr(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs)
{
ULONG i;
HRESULT hr;
ClearAttrStore();
if (dwFlags & TS_ATTR_FIND_WANT_VALUE)
{
if (_owner == NULL)
return E_FAIL;
}
for (i=0; i<cFilterAttrs; i++)
{
VARIANT var;
QuickVariantInit(&var);
if (dwFlags & TS_ATTR_FIND_WANT_VALUE)
{
if (_owner->GetAttribute(paFilterAttrs[i], &var) != S_OK)
{
ClearAttrStore();
return E_FAIL;
}
}
else
{
// Issue: benwest: I think these should be init'd to VT_EMPTY if caller doesn't specify TS_ATTR_FIND_WANT_VALUE
if (IsEqualGUID(paFilterAttrs[i], GUID_PROP_MODEBIAS))
{
var.vt = VT_I4;
var.lVal = TF_INVALID_GUIDATOM;
}
else if (IsEqualGUID(paFilterAttrs[i], TSATTRID_Text_Orientation))
{
var.vt = VT_I4;
var.lVal = 0;
}
else if (IsEqualGUID(paFilterAttrs[i], TSATTRID_Text_VerticalWriting))
{
var.vt = VT_BOOL;
var.lVal = 0;
}
}
if (var.vt != VT_EMPTY)
{
TSI_ATTRSTORE *pas = _rgAttrStore.Append(1);
if (!pas)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
pas->attrid = paFilterAttrs[i];
pas->var = var;
}
}
hr = S_OK;
Exit:
return hr;
}
//+---------------------------------------------------------------------------
//
// RequestSupportedAttrs
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::RequestSupportedAttrs(DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs)
{
// note the return value is technically a default value, but since we have a value for every location
// this will never need to be used
return _LoadAttr(dwFlags, cFilterAttrs, paFilterAttrs);
}
//+---------------------------------------------------------------------------
//
// RequestAttrsAtPosition
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::RequestAttrsAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
{
return _LoadAttr(TS_ATTR_FIND_WANT_VALUE, cFilterAttrs, paFilterAttrs);
}
//+---------------------------------------------------------------------------
//
// RequestAttrsTransitioningAtPosition
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::RequestAttrsTransitioningAtPosition(LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags)
{
ClearAttrStore();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// FindNextAttrTransition
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::FindNextAttrTransition(LONG acpStart, LONG acpHaltPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset)
{
// our attrs never transition
*pacpNext = acpStart;
*pfFound = FALSE;
plFoundOffset = 0;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// RetrieveRequestedAttrs
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::RetrieveRequestedAttrs(ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched)
{
ULONG i = 0;
while((i < ulCount) && ((int)i < _rgAttrStore.Count()))
{
TSI_ATTRSTORE *pas = _rgAttrStore.GetPtr(i);
paAttrVals->idAttr = pas->attrid;
paAttrVals->dwOverlapId = 0;
QuickVariantInit(&paAttrVals->varValue);
paAttrVals->varValue = pas->var;
paAttrVals++;
i++;
}
*pcFetched = i;
ClearAttrStore();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// QueryService
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::QueryService(REFGUID guidService, REFIID riid, void **ppv)
{
if (ppv == NULL)
return E_INVALIDARG;
*ppv = NULL;
if (!IsEqualGUID(guidService, GUID_SERVICE_TF) ||
!IsEqualIID(riid, IID_PRIV_CTSI))
{
// SVC_E_NOSERVICE is proper return code for wrong service....
// but it's not defined anywhere. So use E_NOINTERFACE for both
// cases as trident is rumored to do
return E_NOINTERFACE;
}
*ppv = this;
AddRef();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetActiveView
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::GetActiveView(TsViewCookie *pvcView)
{
// each CEditWnd has only a single view, so this can be constant.
*pvcView = TSI_ACTIVE_VIEW_COOKIE;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// AdviseMouseSink
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::AdviseMouseSink(ITfRangeACP *range, ITfMouseSink *pSink, DWORD *pdwCookie)
{
ITfMouseTrackerACP *pTracker;
HRESULT hr;
Assert(range != NULL);
Assert(pSink != NULL);
Assert(pdwCookie != NULL);
*pdwCookie = 0;
if (_owner == NULL)
return E_FAIL;
if (_owner->QueryInterface(IID_ITfMouseTrackerACP, (void **)&pTracker) != S_OK)
return E_NOTIMPL;
hr = pTracker->AdviseMouseSink(range, pSink, pdwCookie);
pTracker->Release();
return hr;
}
//+---------------------------------------------------------------------------
//
// UnadviseMouseSink
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::UnadviseMouseSink(DWORD dwCookie)
{
ITfMouseTrackerACP *pTracker;
HRESULT hr;
if (_owner == NULL)
return E_FAIL;
if (_owner->QueryInterface(IID_ITfMouseTrackerACP, (void **)&pTracker) != S_OK)
return E_NOTIMPL;
hr = pTracker->UnadviseMouseSink(dwCookie);
pTracker->Release();
return hr;
}
//+---------------------------------------------------------------------------
//
// QueryInsertEmbedded
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::QueryInsertEmbedded(const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable)
{
Assert(pfInsertable != NULL); // cicero should have caught this
*pfInsertable = FALSE;
// only accept unicode text
if (pguidService == NULL &&
pFormatEtc != NULL &&
pFormatEtc->cfFormat == CF_UNICODETEXT &&
pFormatEtc->dwAspect == DVASPECT_CONTENT &&
pFormatEtc->lindex == -1 &&
pFormatEtc->tymed == TYMED_HGLOBAL)
{
*pfInsertable = TRUE;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// InsertTextAtSelection
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::InsertTextAtSelection(DWORD dwFlags, const WCHAR *pchText,
ULONG cch, LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange)
{
HRESULT hr;
Assert((dwFlags & TS_IAS_QUERYONLY) || pchText != NULL); // caller should have already caught this
Assert((dwFlags & TS_IAS_QUERYONLY) || cch > 0); // caller should have already caught this
Assert(pacpStart != NULL && pacpEnd != NULL); // caller should have already caught this
Assert((dwFlags & (TS_IAS_NOQUERY | TS_IAS_QUERYONLY)) != (TS_IAS_NOQUERY | TS_IAS_QUERYONLY)); // caller should have already caught this
if (dwFlags & TS_IAS_QUERYONLY)
goto Exit;
*pacpStart = -1;
*pacpEnd = -1;
hr = SetText(0, _Sel.acpStart, _Sel.acpEnd, pchText, cch, pChange);
if (hr != S_OK)
return hr;
Exit:
// since this is cheap, always set the insert span even if caller sets TS_IAS_NOQUERY
*pacpStart = _Sel.acpStart;
*pacpEnd = _Sel.acpEnd;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// InsertEmbeddedAtSelection
//
//----------------------------------------------------------------------------
STDAPI CTextStoreImpl::InsertEmbeddedAtSelection(DWORD dwFlags, IDataObject *pDataObject,
LONG *pacpStart, LONG *pacpEnd, TS_TEXTCHANGE *pChange)
{
HRESULT hr;
Assert((dwFlags & TS_IAS_QUERYONLY) || pDataObject != NULL); // caller should have already caught this
Assert(pacpStart != NULL && pacpEnd != NULL); // caller should have already caught this
Assert((dwFlags & (TS_IAS_NOQUERY | TS_IAS_QUERYONLY)) != (TS_IAS_NOQUERY | TS_IAS_QUERYONLY)); // caller should have already caught this
if (dwFlags & TS_IAS_QUERYONLY)
goto Exit;
*pacpStart = -1;
*pacpEnd = -1;
hr = InsertEmbedded(0, _Sel.acpStart, _Sel.acpEnd, pDataObject, pChange);
if (hr != S_OK)
return hr;
Exit:
// since this is cheap, always set the insert span even if caller sets TS_IAS_QUERYONLY
*pacpStart = _Sel.acpStart;
*pacpEnd = _Sel.acpEnd;
return S_OK;
}