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 + -
显示快捷键?