⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tomrange.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// 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 TOM
 *
 *	@module	TOMRANGE.CPP - Implement the CTxtRange Class |
 *	
 *		This module contains the implementation of the TOM ITextRange
 *		interface on the CTxtRange object
 *
 *	History: <nl>
 *		5/24/95	- Alex Gounares: stubs created <nl>
 *		8/95	- MurrayS: main implementation <nl>
 *		11/95	- MurrayS: upgrade to TOM spec of 12/10/95 <nl>
 *		5/96	- MurrayS: added zombie protection
 *
 *	@comm
 *		All ITextRange methods return HRESULTs.  If the method can move a
 *		range cp, the HRESULT is NOERROR if movement occurs and S_FALSE if
 *		no movement occurs.  These methods usually take a <p pDelta> argument
 *		that returns the count of characters or Units actually moved.  If this
 *		parameter is NULL, E_INVALIDARG is returned.  Other return values
 *		include E_NOTIMPL, e.g., for Unit values not implemented, 
 *		E_OUTOFMEMORY, e.g., when allocations fail, and CO_E_RELEASED, when
 *		the CTxtEdit (_ped) to which the range is attached has been deleted.
 *
 *		For more complete documentation, please see tom.doc
 *
 *	@devnote
 *		All ptr parameters must be validated before use and all entry points
 *		need to check whether this range is a zombie.  These checks are
 *		done in one of three places: 1) immediately on entry to a function,
 *		2) immediately on entry to a helper function (e.g., private Mover()
 *		for the	move methods), or 3) before storing the out value.
 *		Alternative 3) is used for optional return values, such as pDelta
 *		and pB. 
 *
 *		To achieve a simple, efficient inheritance model, CTxtSelection
 *		inherits ITextSelection through CTxtRange.  Otherwise we'd have a
 *		diamond inheritance, since ITextSelection itself inherits from
 *		ITextRange. Diamond inheritance creates two copies of the multiply
 *		inherited class unless that class is inherited virtually. Virtual
 *		inheritance uses run-time base-offset tables and is slower and
 *		bigger.  To avoid such a mess, we include the extra ITextSelection
 *		methods in CTxtRange, with the intention that they'll never be called
 *		and therefore they return E_NOTIMPL. This is overridden for
 *		ITextSelection objects
 *
 *	@future
 *		1) Finder match ^p, etc.
 *		2) Fast GetEffects() method. Would speed up the myriad IsProtected()
 *		   calls and be useful for getting other effects as well.
 *		3) Fast copies/pastes of RichEdit binary format. This can be done by
 *		   creating a method to copy a range to a new CTxtStory and a method
 *		   to insert a CTxtStory.
 *		4) Delayed rendering
 *
 */

#include "_common.h"
#include "_select.h"
#include "_edit.h"
#include "_line.h"
#include "_frunptr.h"
#include "_tomfmt.h"
#include "_disp.h"
#include "_objmgr.h"
#include "_callmgr.h"

ASSERTDATA

#define DEBUG_CLASSNAME CTxtRange
#include "_invar.h"

HRESULT QueryInterface (REFIID riid, REFIID riid1, IUnknown *punk,
						void **ppv, BOOL fZombie);
BOOL	SameVtables(IUnknown *punk1, IUnknown *punk2);



//----------------- CTxtRange (ITextRange) PUBLIC methods ----------------------------------

//----------------------- CTxtRange IUnknown Methods -------------------------------------

/*
 *	CTxtRange::QueryInterface (riid, ppv)
 *
 *	@mfunc
 *		IUnknown method
 *
 *	@rdesc
 *		HRESULT = (!ppv) ? E_INVALIDARG :
 *				  (interface found) ? NOERROR : E_NOINTERFACE
 */
STDMETHODIMP CTxtRange::QueryInterface (
	REFIID	riid,			// @parm Reference to requested interface ID
	void ** ppv)			// @parm Out parm to receive interface ptr
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::QueryInterface");

	REFIID riid1 = _fSel && IsEqualIID(riid, IID_ITextSelection)
				 ? IID_ITextSelection : IID_ITextRange;
#ifndef PEGASUS
	return ::QueryInterface(riid, riid1, this, ppv, IsZombie());
#else
	return 0;
#endif
}

/*
 *	CTxtRange::AddRef()
 *
 *	@mfunc
 *		IUnknown method
 *
 *	@rdesc
 *		ULONG - incremented reference count
 */
STDMETHODIMP_(ULONG) CTxtRange::AddRef()
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::AddRef");

 	return ++_cRefs;
}

/*
 *	CTxtRange::Release()
 *
 *	@mfunc
 *		IUnknown method
 *
 *	@rdesc
 *		ULONG - decremented reference count
 */
STDMETHODIMP_(ULONG) CTxtRange::Release()
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Release");

	_cRefs--;

	if(!_cRefs)
	{
		delete this;
		return 0;
	}

	Assert(_cRefs > 0);
	return _cRefs;
}


//------------------------ CTxtRange IDispatch Methods -------------------------------------

/*
 *	CTxtRange::GetTypeInfoCount(pcTypeInfo)
 *
 *	@mfunc
 *		Get the number of TYPEINFO elements (1)
 *
 *	@rdesc
 *		HRESULT
 */
STDMETHODIMP CTxtRange::GetTypeInfoCount (
	UINT * pcTypeInfo)			//@parm Out parm to receive type-info count
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::GetTypeInfoCount");

	if(!pcTypeInfo)
		return E_INVALIDARG;

	*pcTypeInfo = 1;
	return NOERROR;
}

/*
 *	CTxtRange::GetTypeInfo(iTypeInfo, lcid, ppTypeInfo)
 *
 *	@mfunc
 *		Return ptr to type information object for ITextSelection interface
 *
 *	@rdesc
 *		HRESULT
 */
STDMETHODIMP CTxtRange::GetTypeInfo (
	UINT		iTypeInfo,		//@parm Index of type info to return
	LCID		lcid,			//@parm Local ID of type info
	ITypeInfo **ppTypeInfo)		//@parm Out parm to receive type info
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::GetTypeInfo");

	return ::GetTypeInfo(iTypeInfo, g_pTypeInfoSel, ppTypeInfo);
}

/*
 *	CTxtRange::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid)
 *
 *	@mfunc
 *		Get DISPIDs for methods in the ITextSelection, ITextRange, ITextFont,
 *		and ITextPara interfaces
 *
 *	@rdesc
 *		HRESULT
 *
 *	@devnote
 *		If the ITextFont and ITextPara ever offer more methods than exposed
 *		in their type libraries, the code should delegate to the corresponding
 *		GetIDsOfNames. The current code only gets DISPIDs for the methods in
 *		type libraries, thereby not having to instantiate the objects.
 */
STDMETHODIMP CTxtRange::GetIDsOfNames (
	REFIID		riid,			//@parm Interface ID to interpret names for
	OLECHAR **	rgszNames,		//@parm Array of names to be mapped
	UINT		cNames,			//@parm Count of names to be mapped
	LCID		lcid,			//@parm Local ID to use for interpretation
	DISPID *	rgdispid)		//@parm Out parm to receive name mappings
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::GetIDsOfNames");

	HRESULT hr = GetTypeInfoPtrs();				// Ensure TypeInfo ptrs are OK
	if(hr != NOERROR)
		return hr;
		
	if(g_pTypeInfoSel->GetIDsOfNames(rgszNames, cNames, rgdispid) == NOERROR)
		return NOERROR;

	if(g_pTypeInfoFont->GetIDsOfNames(rgszNames, cNames, rgdispid) == NOERROR)
		return NOERROR;

	return g_pTypeInfoPara->GetIDsOfNames(rgszNames, cNames, rgdispid);
}

/*
 *	CTxtRange::Invoke(dispidMember, riid, lcid, wFlags, pdispparams,
 *					  pvarResult, pexcepinfo, puArgError)
 *	@mfunc
 *		Invoke methods for the ITextRange and ITextSelection objects, as
 *		well as for ITextFont and ITextPara	interfaces on those objects.
 *
 *	@rdesc
 *		HRESULT
 */
STDMETHODIMP CTxtRange::Invoke (
	DISPID		dispidMember,	//@parm Identifies member function
	REFIID		riid,			//@parm Pointer to interface ID
	LCID		lcid,			//@parm Locale ID for interpretation
	USHORT		wFlags,			//@parm Flags describing context of call
	DISPPARAMS *pdispparams,	//@parm Ptr to method arguments
	VARIANT *	pvarResult,		//@parm Out parm for result (if not NULL)
	EXCEPINFO * pexcepinfo,		//@parm Out parm for exception info
	UINT *		puArgError)		//@parm Out parm for error
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Invoke");

	HRESULT hr = GetTypeInfoPtrs();			// Ensure TypeInfo ptrs are OK
	if(hr != NOERROR)
		return hr;
		
	if(IsZombie())
		return CO_E_RELEASED;

	IDispatch *	pDispatch;
	ITypeInfo *	pTypeInfo;

	if((DWORD)dispidMember <= 0x2ff)		// Include default (0), selection,
	{										//  and range DISPIDs
		pTypeInfo = g_pTypeInfoSel;
		pDispatch = this;
		AddRef();							// Compensate for Release() below
	}
	else if((DWORD)dispidMember <= 0x3ff)	// 0x300 to 0x3ff: DISPIDs
	{										//  reserved for ITextFont
		pTypeInfo = g_pTypeInfoFont;
		hr = GetFont((ITextFont**)&pDispatch);
	}
	else if((DWORD)dispidMember <= 0x4ff)	// 0x400 to 0x4ff: DISPIDs
	{										//  reserved for ITextPara
		pTypeInfo = g_pTypeInfoPara;
		hr = GetPara((ITextPara **)&pDispatch);
	}
	else									// dispidMember is negative or
		return DISP_E_MEMBERNOTFOUND;		//  > 0x4ff, i.e., not TOM

	if(hr != NOERROR)						// Couldn't instantiate ITextFont
		return hr;							//  or ITextPara

	hr = pTypeInfo->Invoke(pDispatch, dispidMember, wFlags,
							 pdispparams, pvarResult, pexcepinfo, puArgError);
#ifndef PEGASUS
	pDispatch->Release();
#endif
	return hr;
}


//----------------------- ITextRange Methods/Properties ------------------------

/*
 *	CTxtRange::CanEdit (pB)
 *
 *	@mfunc
 *		Set *<p pB> = tomTrue iff this range can be edited and
 *		pB isn't NULL
 *
 *	@rdesc
 *		HRESULT = (can edit) ? NOERROR : S_FALSE
 */
STDMETHODIMP CTxtRange::CanEdit (
	long * pB) 			//@parm Out parm to receive boolean value
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::CanEdit");

	if(IsZombie())
		return CO_E_RELEASED;

	CCallMgr	callmgr(GetPed());
	return IsTrue(!WriteAccessDenied(), pB);
}

/*
 *	CTxtRange::CanPaste (pVar, long Format, pB)
 *
 *	@mfunc
 *		Set *<p pB> = tomTrue iff the data object <p pVar>->punkVal can be
 *		pasted into this range and pB isn't NULL.  If <p pVar> is NULL,
 *		use the clipboard instead.
 *
 *	@rdesc
 *		HRESULT = (can paste) ? NOERROR : S_FALSE
 */
STDMETHODIMP CTxtRange::CanPaste (
	VARIANT *	pVar,		//@parm Data object to paste 
	long		Format,		//@parm Desired clipboard format
	long *		pB)  		//@parm Out parm to receive boolean value
{
#ifndef PEGASUS
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::CanPaste");

	if(IsZombie())
		return CO_E_RELEASED;

	CCallMgr		callmgr(GetPed());
	HRESULT			hr; 
	IDataObject *	pdo = NULL;				// Default clipboard

	if(pVar && pVar->vt == VT_UNKNOWN)
		pVar->punkVal->QueryInterface(IID_IDataObject, (void **)&pdo);

	hr = IsTrue(!WriteAccessDenied() &&
				(GetPed()->GetDTE()->CanPaste(pdo, (CLIPFORMAT)Format, 
				 RECO_PASTE)), pB);
	
	if( pdo )
	{
		pdo->Release();
	}

	return hr;
#else
	return 0;
#endif
}

/*
 *	ITextRange::ChangeCase (long Type) 
 *
 *	@mfunc
 *		Change the case of letters in this range according to Type:
 *
 *		tomSentenceCase	= 0: capitalize first letter of each sentence
 *		tomLowerCase	= 1: change all letters to lower case
 *		tomUpperCase	= 2: change all letters to upper case
 *		tomTitleCase	= 3: capitalize the first letter of each word
 *		tomToggleCase	= 4: toggle the case of each letter
 *	
 *	@rdesc
 *		HRESULT = (WriteAccessDenied) ? E_ACCESSDENIED :
 *				  (if change) ? NOERROR : S_FALSE
 */
STDMETHODIMP CTxtRange::ChangeCase (
	long Type)		//@parm Type of case change. Default value: tomLower
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::ChangeCase");

	if(IsZombie())
		return CO_E_RELEASED;

	CCallMgr callmgr(GetPed());

	if( WriteAccessDenied())
		return E_ACCESSDENIED;

	CGenUndoBuilder	 undobldr(GetPed(), UB_AUTOCOMMIT );
	LONG			 cpMin, cpMax;
	LONG			 cch = GetRange(cpMin, cpMax);
	CRchTxtPtr		 rtp(*this);

	undobldr.StopGroupTyping();

	rtp.SetCp(cpMin);
	return (rtp.ChangeCase(cch, Type, &undobldr)) ? NOERROR : S_FALSE;
}

/*
 *	CTxtRange::Collapse (bStart)
 *
 *	@mfunc
 *		Collapse this range into a degenerate point either at the
 *		the start (<p bStart> is nonzero or the end (<p bStart> = 0)
 *
 *	@rdesc
 *		HRESULT = (if change) ? NOERROR : S_FALSE
 */
STDMETHODIMP CTxtRange::Collapse (
	long bStart) 			//@parm Flag specifying end to collapse at
{
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Collapse");

	if(IsZombie())
		return CO_E_RELEASED;

	CCallMgr callmgr(GetPed());
 
	if(!_cch)							// Already collapsed
		return S_FALSE;					// Signal that no change occurred
		
	Collapser(bStart);
	Update(TRUE);						// Update selection
	return NOERROR;						// Signal that change occurred
}

/*
 *	CTxtRange::Copy (pVar)
 *
 *	@mfunc
 *		Copy the plain and/or rich text to a data object and return the
 *		object ptr in <p pVar>.  If <p pVar> is null, copy to the clipboard. 
 *
 *	@rdesc
 *		HRESULT = (if success) ? NOERROR : E_OUTOFMEMORY
 */
STDMETHODIMP CTxtRange::Copy (
	VARIANT * pVar)				//@parm Out parm for data object 
{
#ifndef PEGASUS
	TRACEBEGIN(TRCSUBSYSTOM, TRCSCOPEEXTERN, "CTxtRange::Copy");

	if(IsZombie())
		return CO_E_RELEASED;

	CLightDTEngine * pldte = &GetPed()->_ldte;

	if(pVar && pVar->vt == (VT_UNKNOWN | VT_BYREF))
	{
		return pldte->RangeToDataObject(this, SF_TEXT | SF_RTF,
									(IDataObject **)pVar->ppunkVal);
	}
	return pldte->CopyRangeToClipboard(this);
#else
	return 0;

⌨️ 快捷键说明

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