Exemple #1
0
//+------------------------------------------------------------------------
//
//  Member:     GetDisp
//
//  Synopsis:   Get a dispatch ptr on an element from the cache.
//      Return the nth element that mathces the name
//
//-------------------------------------------------------------------------
HRESULT CCollectionCache::GetDisp(
          long          lIndex,
          LPCTSTR       Name,
          long          lNthElement,
          IDispatch**   ppdisp,
          BOOL          fCaseSensitive)
{
    long                    lSize,l;
    HRESULT                 hr = DISP_E_MEMBERNOTFOUND;
    CCollectionCacheItem*   pItem;
    CElement*               pElem;

    Assert((lIndex>=0) && (lIndex<_aryItems.Size()));
    Assert(ppdisp);

    pItem = _aryItems[lIndex]._pCacheItem;

    *ppdisp = NULL;

    // if lIndexElement is too large, just pretend we
    //  didn't find it rather then erroring out
    if(lNthElement < 0)
    {
        hr = E_INVALIDARG;
        goto Cleanup;
    }

    lSize = pItem->Length();

    if(lNthElement >= lSize)
    {
        goto Cleanup;
    }

    for(l=0; l<lSize; ++l)
    {
        pElem = pItem->GetAt(l);
        Assert(pElem);
        if(CompareName(pElem, Name, FALSE, fCaseSensitive) && !lNthElement--)
        {
            RRETURN(pElem->QueryInterface(IID_IDispatch, (void**)ppdisp));
        }
    }

Cleanup:
    RRETURN(hr);
}
Exemple #2
0
//+------------------------------------------------------------------------
//
//  Member:     GetDisp
//
//  Synopsis:   Get a dispatch ptr on an element from the cache.
//
//-------------------------------------------------------------------------
HRESULT CCollectionCache::GetDisp(long lIndex, long lIndexElement, IDispatch** ppdisp)
{
    CElement* pElem;

    Assert((lIndex>=0) && (lIndex<_aryItems.Size()));

    *ppdisp = NULL;

    if(lIndexElement >= _aryItems[lIndex]._pCacheItem->Length())
    {
        RRETURN(DISP_E_MEMBERNOTFOUND);
    }

    if(lIndexElement < 0)
    {
        RRETURN(E_INVALIDARG);
    }

    pElem = _aryItems[lIndex]._pCacheItem->GetAt(lIndexElement);
    Assert(pElem);

    RRETURN(pElem->QueryInterface(IID_IDispatch, (void**)ppdisp));
}
Exemple #3
0
//+------------------------------------------------------------------------
//
//  Member:     GetDisp
//
//  Synopsis:   Get a dispatch ptr from the NON-RESERVED part of the cache.
//              N.B. non-reserved can never be identity collecitons,
//
//-------------------------------------------------------------------------
HRESULT CCollectionCache::GetDisp(
          long          lIndex,
          LPCTSTR       Name,
          CollCacheType CacheType,
          IDispatch**   ppdisp,
          BOOL          fCaseSensitive/*=FALSE*/,
          RECT*         pRect/*=NULL*/,
          BOOL          fAlwaysCollection/*=FALSE*/)
{
    long        lSize = _aryItems.Size();
    long        l;
    HRESULT     hr = S_OK;
    CacheItem*  pce;
    CRect       rectCellRange(CRect::CRECT_EMPTY);

    // named arrays are always built into an AryCacheItem
    CElementAryCacheItem aryItem;

    Assert(CacheType==CacheType_Tag || CacheType==CacheType_Named || 
        CacheType==CacheType_CellRange || CacheType==CacheType_Urn);

    typedef int (*COMPAREFN)(LPCTSTR, LPCTSTR);
    COMPAREFN CompareFn = fCaseSensitive ? FormsStringCmp : FormsStringICmp;

    *ppdisp = NULL;

    pce = &_aryItems[_lReservedSize];

    // Return this named collection if it already exists.
    for(l=_lReservedSize; l<lSize; ++l,++pce)
    {
        if(pce->Type==CacheType && lIndex==pce->sIndex && 
            pce->fIsCaseSensitive==(unsigned)fCaseSensitive &&
            !CompareFn(Name, (BSTR)pce->cstrName))
        {
            pce->pdisp->AddRef();
            *ppdisp = pce->pdisp;
            goto Cleanup;
        }
    }

    // Build the list
    if(CacheType != CacheType_CellRange)
    {
        hr=BuildNamedArray(lIndex, Name, CacheType==CacheType_Tag, 
            &aryItem, 0, fCaseSensitive, CacheType==CacheType_Urn);
    }
    else
    {           
        if(!pRect)
        {
            // Mark the rect as empty
            rectCellRange.right = -1;
        }
        else
        {
            // Use the passed in rect
            rectCellRange = *pRect;
        }
        hr = BuildCellRangeArray(lIndex, Name, &rectCellRange, &aryItem);
    }

    if(hr)
    {
        goto Cleanup;
    }

    // Return based on what the list of named elements looks like.
    if(!aryItem.Length() && !((CacheType==CacheType_Tag) || (CacheType==CacheType_Urn) || fAlwaysCollection))
    {
        hr = DISP_E_MEMBERNOTFOUND;
        goto Error;
    }
    // The tags method ALWAYS should return a collection (else case)
    else if(aryItem.Length()==1 && !((CacheType==CacheType_Tag) || (CacheType==CacheType_Urn) || fAlwaysCollection))
    {
        CElement* pElem = aryItem.GetAt(0);
        hr = pElem->QueryInterface(IID_IDispatch, (void**)ppdisp);
        // Keep the ppdisp around we'll return that and just release the array.
        goto Cleanup2;
    }
    else
    {
        CElementAryCacheItem* pAryItem;

        hr = GetFreeIndex(&l); // always returns Idx from non-reserved part of cache
        if(hr)
        {
            goto Error;
        }

        hr = CreateCollectionHelper(ppdisp, l);
        if(hr)
        {
            goto Error;
        }

        pce = &_aryItems[l];
        pce->Init();

        hr = pce->cstrName.Set(Name);
        if(hr)
        {
            goto Error;
        }

        Assert(!pce->_pCacheItem);
        pce->_pCacheItem = new CElementAryCacheItem();
        if(!pce->_pCacheItem)
        {
            hr = E_OUTOFMEMORY;
            goto Cleanup;
        }

        // Copy the array. 
        // For perf reasons assume that the destination collection is a 
        // ary cache - which it is for now, by design
        pAryItem = DYNCAST(CElementAryCacheItem, pce->_pCacheItem);
        pAryItem->CopyAry(&aryItem); // this just copies the ptrarray _pv across

        pce->pdisp = *ppdisp;
        pce->sIndex = lIndex; // Remember the index we depend on.
        pce->Type = CacheType;
        pce->fIsCaseSensitive = fCaseSensitive;

        // Save the range for the cell range type cache so we do not need to parse
        // the name later
        if(CacheType == CacheType_CellRange)
        {
            pce->rectCellRange = rectCellRange;
        }

        // The collection this named collection was built from is now
        // used to rebuild (ensure) this collection. so we need to
        // put a reference on it so that it will not go away and its
        // location re-assigned by another call to GetFreeIndex.
        // The matching Release() will be done in the dtor
        // although it is not necessary to addref the reserved collections
        //  it is done anyhow, simply for consistency.  This addref
        // only needs to be done for non-reserved collections
        if(lIndex >= _lReservedSize)
        {
            _aryItems[lIndex].pdisp->AddRef();
        }
    }

Cleanup:
    RRETURN(hr);

Error:
    ClearInterface(ppdisp);

Cleanup2:
    goto Cleanup;
}