objmgr.cpp

来自「Windows CE 6.0 Word Application 源码」· C++ 代码 · 共 1,028 行 · 第 1/2 页

CPP
1,028
字号
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*
 *  @doc    INTERNAL
 *
 *  @module objmgr.cpp.  Object manager implementation | manages a
 *          collection of OLE embedded objects 
 *
 *  Author: alexgo 11/5/95
 *
 */

#include "_common.h"
#include "_objmgr.h"
#include "_edit.h"
#include "_disp.h"
#include "_select.h"

ASSERTDATA

//
//	PUBLIC methods
//

/*
 *	CObjectMgr::GetObjectCount
 *
 *	@mfunc	returns the number of embedded objects currently in
 *			the document.
 *
 *	@rdesc	LONG, the count.  A LONG is used instead of a DWORD for
 *			compatibility with Richedit1.0's IRicheditOle interface.
 */
LONG CObjectMgr::GetObjectCount(void)
{
	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::GetObjectCount");

	return (LONG)_objarray.Count();
}

/*
 *	CObjectMgr::GetLinkCount
 *
 *	@mfunc	returns the number of embedded objects which are links
 *
 *	@rdesc	LONG, the count.  A LONG is used instead of a DWORD for
 *			compatibility with Richedit1.0's IRichEditOle interface.
 *
 */
LONG CObjectMgr::GetLinkCount(void)
{
	LONG count = 0;
	COleObject *pobj;
	DWORD i;

	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::GetLinkCount");
		
	for( i = 0; i < _objarray.Count(); i++ )
	{
		pobj = *_objarray.Elem(i);
		if( pobj && pobj->IsLink() )
		{
			count++;
		}
	}
	
	return count;
}

/*
 *	CObjectMgr::GetObjectFromCp()
 *
 *	@mfunc	fetches an object corresponding to the given cp
 *
 *	@rdesc	the object @ a cp; NULL if nothing found
 *
 *	@comm	the algorithm is a modified binary search.  Since the
 *			"typical" access pattern will be to linearly access the
 *			objects, we used the cached index to guess first.  If
 *			that doesn't work, we resort to a binary search.
 */
COleObject *CObjectMgr::GetObjectFromCp(
	DWORD cp)		//@parm the cp for the object
{
	COleObject *pobj = NULL;
	DWORD i = 0;
	
	// no tracing on this method as it's too noisy.
		
	if( _objarray.Count() > 0 )
	{
		if( _lastindex < _objarray.Count() )
		{
			pobj = *_objarray.Elem(_lastindex);
			
			if( pobj && pobj->GetCp() == cp )
			{
				return pobj;
			}
		}
		
		// the quick lookup failed; try a binary search.

		i = FindIndexForCp(cp);

		// because of the insert at end case, i may be equal 
		// to the count of objects().
		if( i < _objarray.Count() )
		{
			pobj = *_objarray.Elem(i);
		}
		else
		{
			pobj = NULL;
		}
	}

	// FindIndex will return a matching or _near_ index.
	// In this case, we only want a matching index
	if( pobj )
	{
		if( pobj->GetCp() != cp )
		{
			pobj = NULL;
		}
		else
		{
			// set the cached index to be the next one,
			// so that somebody walking through objects in
			// cp order will always get immediate hits.
			_lastindex = i + 1;
		}
	}
	
#ifdef DEBUG
	// make sure the binary search found the right thing

	for( i = 0 ; i < _objarray.Count();  i++ )
	{
		COleObject *pobj2 = *_objarray.Elem(i);
	
		if( pobj2 )
		{
			if( *_objarray.Elem(i) == pobj )
			{
				Assert((*_objarray.Elem(i))->GetCp() == cp);
			}
			else
			{
				Assert((*_objarray.Elem(i))->GetCp() != cp);
			}
		}
	}
#endif //DEBUG

	return pobj;
}

/*
 *	CObjectMgr::CountObjects (rcObject, cp)
 *
 *	@mfunc	Count char counts upto <p rcObject> objects away The direction of
 *			counting is determined by the sign of <p rcObject>. 
 *
 *	@rdesc	Return the signed cch counted and set <p rcObject> to count of
 *			objects actually counted.  If <p cobject> <gt> 0 and cp is at
 *			the last object, no change is made and 0 is returned.
 *
 *	@devnote This is called from TOM, which uses LONGs for cp's (because VB
 *			can't use unsigned quantities)
 */
LONG CObjectMgr::CountObjects (
	LONG&	rcObject,		//@parm Count of objects to get cch for
	LONG	cp)				//@parm cp to start counting from
{
	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::CountObjects");

	LONG		iStart, iEnd;
	LONG		iMaxEnd = (LONG)_objarray.Count() - 1;

	if( !rcObject || !_objarray.Count() )
	{
		rcObject = 0;
		return 0;
	}

	iStart = (LONG)FindIndexForCp(cp);

	// if we are looking past either end, return 0

	if( iStart > iMaxEnd && rcObject > 0 )
	{
		rcObject = 0;
		return 0;
	}
	else if( iStart == 0 && rcObject < 0 )
	{
		rcObject = 0;
		return 0;
	}

	// If the index that we found is on an object and
	// we are looking forward, it should be skipped.

	if( iStart < (LONG)_objarray.Count() && 
		(LONG)(*_objarray.Elem(iStart))->GetCp() == cp &&
		rcObject > 0)
	{
		iStart++;
	}

	// Calculate where the end would be.  Note that we use
	// explicit if's to avoid 32 integer arithmetic round
	// off errors in boundary cases.

	if( rcObject < 0 )
	{
		if( (-rcObject) > iStart )
		{
			// subtracting would make us negative, set us to
			// the floor (0).
			iEnd = 0;
			rcObject = -iStart;
		}
		else
		{
			iEnd = iStart + rcObject + 1;
		}
	}
	else
	{
		if( rcObject > iMaxEnd - iStart )
		{
			// adding could make us overflow, set us to the
			// ceiling.
			iEnd = iMaxEnd;
			rcObject = iMaxEnd - iStart + 1;
		}
		else
		{
			iEnd = iStart + rcObject - 1;
		}
	}

	Assert(iEnd >= 0 && iEnd < (LONG)_objarray.Count() );

	return (*_objarray.Elem(iEnd))->GetCp() - cp;
}

			
/*
 *	CObjectMgr::CountObjectsInRange (cpMin, cpMost)
 *
 *	@mfunc	Count the number of objects in the given range.
 *
 *	@rdesc	Return the number of objects.
 *
 */
DWORD CObjectMgr::CountObjectsInRange (
	DWORD	cpMin,	//@parm Beginning of range
	DWORD	cpMost)	//@parm End of range
{
	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::CountObjectsInRange");

	DWORD	iMin, iMost;

	//Get the indexs for the objects at or after cpMin and cpMost
	//respectively.
	iMin = FindIndexForCp(cpMin);
	iMost = FindIndexForCp(cpMost);
	return (LONG)(iMost - iMin);
}


/*
 *	CObjectMgr::GetFirstObjectInRange (cpMin, cpMost)
 *
 *	@mfunc	Get the first object in the given range. 
 *
 *	@rdesc	Pointer to first object in range, or NULL if none.
 *
 */
COleObject * CObjectMgr::GetFirstObjectInRange (
	DWORD	cpMin,	//@parm Beginning of range
	DWORD	cpMost)	//@parm End of range
{
	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::GetFirstObjectInRange");

	COleObject * pObj = NULL;
	LONG	iObj;
	LONG	iLast = (LONG)_objarray.Count() - 1;

	//Get the index for next object at or after cpMin.
	iObj = FindIndexForCp(cpMin);

	//Make sure this is an existing object.
	if( iObj <= iLast )
	{
		//Make sure it is within the range.
		pObj = *_objarray.Elem(iObj);

		if( pObj && pObj->GetCp() <= cpMost )
		{
			return pObj;
		}
	}

	return NULL;
}


/*
 *	CObjectMgr::GetObjectFromIndex
 *
 *	@mfunc	retrieves the object at the indicated index
 *
 *	@rdesc	a pointer to the object, if found, NULL otherwise
 */
COleObject *CObjectMgr::GetObjectFromIndex(
	DWORD index)		//@parm	the index to use
{
	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::GetObjectFromIndex");

	if( index < _objarray.Count() )
	{
		return *_objarray.Elem(index);
	}
	return NULL;
}

/*
 *	CObjectMgr::InsertObject
 *
 *	@mfunc	inserts an object at the indicated index.  It is the
 *			caller's responsibility to handle inserting any data
 *			(such as WCH_EMBEDDING) into the text stream.
 *
 *	@rdesc	HRESULT
 */
HRESULT CObjectMgr::InsertObject(
	DWORD cp,				//@parm the cp to use
	REOBJECT *preobj,		//@parm the object to insert
	IUndoBuilder *publdr)	//@parm the undo context
{
	COleObject *pobj;
	HRESULT hr;
	pobj = (COleObject *)(preobj->polesite);


 	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::InsertObject");

	// Let the client know what we're up to.
	if (_precall)
	{
		hr = _precall->QueryInsertObject(&preobj->clsid, preobj->pstg,
			REO_CP_SELECTION);

		if( hr != NOERROR )
		{
			return hr;
		}
	}

	// set some stuff up first; since we may make outgoing calls, don't
	// change our internal state yet.
	hr = pobj->InitFromREOBJECT(cp, preobj);
	if( hr != NOERROR )
	{
		return hr;
	}

	return RestoreObject(pobj);
}

/*
 *	CObjectMgr::RestoreObject
 *
 *	@mfunc	[re-]inserts the given object into the list of objects
 *			in the backing store
 *
 *	@rdesc	HRESULT
 */
HRESULT CObjectMgr::RestoreObject(
	COleObject *pobj)		//@parm the object to insert
{
	DWORD i;
	COleObject **ppobj;

	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::RestoreObject");

	i = FindIndexForCp(pobj->GetCp());

	ppobj = _objarray.Insert(i, 1);

	if( ppobj == NULL )
	{
		return E_OUTOFMEMORY;
	}

	*ppobj = pobj;
	pobj->AddRef();

	return NOERROR;
}

/*
 *	CObjectMgr::SetRECallback
 *
 *	@mfunc	sets the callback interface
 *
 *	@rdesc	void
 */
void CObjectMgr::SetRECallback(
	IRichEditOleCallback *precall) //@parm the callback interface pointer
{
 	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::SetRECallback");

	if( _precall )
	{
        SafeReleaseAndNULL((IUnknown**)&_precall);
	}

	_precall = precall;

	if( _precall )
	{
		_precall->AddRef();
	}
}

/*
 *	CObjectMgr::SetHostNames
 *
 *	@mfunc	set the host names for this edit instance
 *
 *	@rdesc	NOERROR or E_OUTOFMEMORY
 */
HRESULT CObjectMgr::SetHostNames(
	LPWSTR	pszApp,	//@parm the app name
	LPWSTR  pszDoc)	//@parm the doc name
{
 	TRACEBEGIN(TRCSUBSYSOLE, TRCSCOPEINTERN, "CObjectMgr::SetHostNames");
	HRESULT hr = NOERROR;

	if( _pszApp )
	{
		delete _pszApp;
		_pszApp = NULL;
	}

	if( _pszDoc )
	{
		delete _pszDoc;
		_pszDoc = NULL;
	}

	if( pszApp )
	{
		_pszApp = new WCHAR[wcslen(pszApp) + 1];
		if( _pszApp )
		{
			wcscpy(_pszApp, pszApp);
		}
		else
		{
			hr = E_OUTOFMEMORY;
		}
	}

	if( pszDoc )
	{
		_pszDoc = new WCHAR[wcslen(pszDoc) + 1];
		if( _pszDoc )
		{
			wcscpy(_pszDoc, pszDoc);
		}
		else
		{
			hr = E_OUTOFMEMORY;
		}
	}
	
	return hr;
}



/*
 *	CObjectMgr::CObjectMgr
 *
 *	@mfunc constructor
 */
CObjectMgr::CObjectMgr()
{
	_pobjselect = NULL;
	_pobjactive = NULL;
}

/*
 *	CObjectMgr::~CObjectMgr
 *
 *	@mfunc	destructor
 */
CObjectMgr::~CObjectMgr()

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?