// // erfa.cpp // // CEnumRangesFromAnchorsBase // // Base class for range enumerators. // #include "private.h" #include "erfa.h" #include "saa.h" #include "ic.h" #include "range.h" #include "immxutil.h" //+--------------------------------------------------------------------------- // // dtor // //---------------------------------------------------------------------------- CEnumRangesFromAnchorsBase::~CEnumRangesFromAnchorsBase() { SafeRelease(_pic); if (_prgAnchors != NULL) { _prgAnchors->_Release(); } } //+--------------------------------------------------------------------------- // // Clone // //---------------------------------------------------------------------------- STDAPI CEnumRangesFromAnchorsBase::Clone(IEnumTfRanges **ppEnum) { CEnumRangesFromAnchorsBase *pClone; if (ppEnum == NULL) return E_INVALIDARG; *ppEnum = NULL; if ((pClone = new CEnumRangesFromAnchorsBase) == NULL) return E_OUTOFMEMORY; pClone->_iCur = _iCur; pClone->_prgAnchors = _prgAnchors; pClone->_prgAnchors->_AddRef(); pClone->_pic = _pic; pClone->_pic->AddRef(); *ppEnum = pClone; return S_OK; } //+--------------------------------------------------------------------------- // // Next // //---------------------------------------------------------------------------- STDAPI CEnumRangesFromAnchorsBase::Next(ULONG ulCount, ITfRange **ppRange, ULONG *pcFetched) { ULONG cFetched; CRange *range; IAnchor *paPrev; IAnchor *pa; int iCurOld; if (pcFetched == NULL) { pcFetched = &cFetched; } *pcFetched = 0; iCurOld = _iCur; if (ulCount > 0 && ppRange == NULL) return E_INVALIDARG; // special case empty enum, or 1 anchor enum if (_prgAnchors->Count() < 2) { if (_prgAnchors->Count() == 0 || _iCur > 0) { return S_FALSE; } // when we have a single anchor in the enum, need to handle it carefully if ((range = new CRange) == NULL) return E_OUTOFMEMORY; if (!range->_InitWithDefaultGravity(_pic, COPY_ANCHORS, _prgAnchors->Get(0), _prgAnchors->Get(0))) { range->Release(); return E_FAIL; } *ppRange = (ITfRangeAnchor *)range; *pcFetched = 1; _iCur = 1; goto Exit; } paPrev = _prgAnchors->Get(_iCur); while (_iCur < _prgAnchors->Count()-1 && *pcFetched < ulCount) { pa = _prgAnchors->Get(_iCur+1); if ((range = new CRange) == NULL) goto ErrorExit; if (!range->_InitWithDefaultGravity(_pic, COPY_ANCHORS, paPrev, pa)) { range->Release(); goto ErrorExit; } // we should never be returning empty ranges, since currently this base // class is only used for property enums and property spans are never // empty. // Similarly, paPrev should always precede pa. Assert(CompareAnchors(paPrev, pa) < 0); *ppRange++ = (ITfRangeAnchor *)range; *pcFetched = *pcFetched + 1; _iCur++; paPrev = pa; } Exit: return *pcFetched == ulCount ? S_OK : S_FALSE; ErrorExit: while (--_iCur > iCurOld) // Issue: just return what we have, rather than freeing everything { (*--ppRange)->Release(); } return E_OUTOFMEMORY; } //+--------------------------------------------------------------------------- // // Reset // //---------------------------------------------------------------------------- STDAPI CEnumRangesFromAnchorsBase::Reset() { _iCur = 0; return S_OK; } //+--------------------------------------------------------------------------- // // Skip // //---------------------------------------------------------------------------- STDAPI CEnumRangesFromAnchorsBase::Skip(ULONG ulCount) { _iCur += ulCount; return (_iCur > _prgAnchors->Count()-1) ? S_FALSE : S_OK; }