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

📄 antievt.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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	ANTIEVT.C |
 *
 *	Purpose:
 *		implemenation of common anti-events and a caching mechanism
 *
 *	Author:
 *		alexgo 3/25/95
 */

#include "_common.h"
#include "_m_undo.h"
#include "_antievt.h"
#include "_edit.h"
#include "_range.h"
#include "_select.h"
#include "_format.h"
#include "_coleobj.h"
#include "_objmgr.h"

ASSERTDATA


//
// CAntiEventDispenser global instance
//
CAntiEventDispenser gAEDispenser;


//
//	CBaseAE PUBLIC methods
//

/*
 *	CBaseAE::Destroy (void)
 *
 *	@mfunc
 *		sends the Destroy notification to the next anti-event in the list
 */

void CBaseAE::Destroy( void )
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::Destroy");
	;
}

/*
 *	CBaseAE::Undo (ped)
 *
 *	@mfunc
 *		sends the Undo notification to the next anti-event in the list
 *
 *	@rdesc	HRESULT
 */
HRESULT CBaseAE::Undo( 
	CTxtEdit *ped,			//@parm	the context for this undo operation
	IUndoBuilder *publdr)	//@parm the undo context.
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::Undo");
	return NOERROR;
}

/*
 *	CBaseAE::OnCommit
 *
 *	@mfunc	called after the anti-event is added to the undo stack
 *
 *	@rdesc	void
 */
void CBaseAE::OnCommit(
	CTxtEdit *ped)			//@parm the edit context
{
	;
}

/*
 *	CBaseAE::MergeData
 *
 *	@mfunc	simply forwards the merge data request to the next anti-evt
 *			(if one exists)
 *
 *	@rdesc	HRESULT.  If S_FALSE, indicates that nothing could be done
 *			with the merge data.
 */
HRESULT	CBaseAE::MergeData(
	DWORD dwDataType, 		//@parm the type of data in <p pdata>
	void *pdata)			//@parm the merge data
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::MergeData");

	return S_FALSE;
}

/*
 *	CBaseAE::SetNext
 *
 *	@mfunc
 *		informs this anti-event of the anti-event which should follow it
 */
void CBaseAE::SetNext( 
	IAntiEvent *pNext )		//@parm	the AntiEvent to link to
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::SetNext");

	_pnext  = pNext;
}

/*
 *	CBaseAE::GetNext
 *
 *	@mfunc
 *		retrieves the next element (if any)
 *
 *	@rdesc	a pointer to the next AntiEvent
 */
IAntiEvent *CBaseAE::GetNext( void )
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::GetNext");

	return _pnext;
}

//
// CBaseAE PROTECTED methods
//

/*
 *	CBaseAE::CBaseAE
 *
 *	@mfunc	Constructor
 */
CBaseAE::CBaseAE()
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::CBaseAE");

	_pnext = NULL;
}


/* 
 *	CReplaceRangeAE::Destroy
 *
 *	@mfunc
 *		deletes this instance
 */

void CReplaceRangeAE::Destroy( void )
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::Destroy");

	if( _paeCF )
	{
		_paeCF->Destroy();
		_paeCF = NULL;
	}
	if( _paePF )
	{
		_paePF->Destroy();
		_paePF = NULL;
	}

	CBaseAE::Destroy();
	delete this;
}
	
/*
 *	CReplaceRangeAE::Undo (ped)
 *
 *	@mfunc
 *		undoes a CTxtPtr::ReplaceRange operation
 *
 *	@comm	
 *	Algorithm:
 *
 *		A replace range works as follows:  delete n characters and in their
 *		place, put m characters.
 *
 *		To undo this, we delete m characters and restore the n that were
 *		originally deleted.  Note that we restore the n characters with
 *		default formatting.  If there was any other formatting to those
 *		characters, a separate anti-event (CReplaceFormattingAE) will
 *		apply the correct formatting.
 */
HRESULT CReplaceRangeAE::Undo( 
	CTxtEdit *ped,			//@parm	the context for this undo operation
	IUndoBuilder *publdr)	//@parm the undo context	
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::Undo");

	CRchTxtPtr rtp(ped, _cpMin);
	CTxtSelection *psel = ped->GetSel();

#ifdef PWD_JUPITER // GuyBark Jupiter 18411: Don't attempt to merge events during an undo
	publdr->_bNoAttemptToMerge = TRUE;
#endif //  PWD_JUPITER

	rtp.ReplaceRange(_cpMax - _cpMin, _cchDel, _pchDel, 
			publdr, -1);

#ifdef PWD_JUPITER // GuyBark Jupiter 18411: Don't attempt to merge events during an undo
	publdr->_bNoAttemptToMerge = FALSE;
#endif //  PWD_JUPITER

	// passing NULL for the publdr is *extremely* important
	// below.  The rich text pointer ReplaceRange call will
	// already generate the appropriate anti-events for any 
	// deleted formatting, so we do not need to repeat that here.

	if( _paeCF )
	{
		_paeCF->Undo(ped, NULL);
	}

	if( _paePF )
	{
		_paePF->Undo(ped, NULL);
	}

	return CBaseAE::Undo(ped, publdr);
}

/*
 *	CReplaceRangeAE::MergeData (dwDataType, pdata)	
 *
 *	@mfunc	gives the caller a chance to extend the current anti-event
 *			if we're in merge typing mode
 *
 *	@comm	if the requested data can be trivially merged into this
 *			anti-event, then do so; otherwise, return S_FALSE.
 *
 *			There are two cases of interest:  <nl>
 *				1. typing another character
 *				2. backspacing over a character in this merge
 *				   typing session.
 */
HRESULT CReplaceRangeAE::MergeData( 
	DWORD dwDataType, 		//@parm	the type of <p pdata>
	void *pdata )			//@parm the merge data
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::MergeData");

	if( dwDataType == MD_SIMPLE_REPLACERANGE )
	{
		SimpleReplaceRange *psr = (SimpleReplaceRange *)pdata;

		// test for the first case, just typing another character
		if( psr->cpMin == _cpMax && psr->cchDel == 0 )
		{
			_cpMax = psr->cpMax;
			return NOERROR;
		}
		// the second case, deleting text stored in this antievent
		else if( psr->cpMax == psr->cpMin &&
			psr->cpMin + psr->cchDel == _cpMax &&
			psr->cpMin >= _cpMin )
		{
			_cpMax = psr->cpMax;
			return NOERROR;
		}
	}
	return S_FALSE;
}	

/* 
 *	CReplaceRangeAE::CReplaceRangeAE (cpMin, cpMax)
 *
 *	@mfunc	Constructor for a text replace range anti-event
 *
 */
CReplaceRangeAE::CReplaceRangeAE( 
	DWORD cpMin, 			//@parm the cp starting the *final* range
	DWORD cpMax, 			//@parm the cp ending the *final* range
	DWORD cchDel, 			//@parm # of chars deleted during ReplaceRange
	TCHAR *pchDel, 			//@parm the deleted characters.  Ownership of
							// the memory is transferred to this object.
	IAntiEvent *paeCF,		//@parm the anti-event for any character formatting
							// replacement
	IAntiEvent *paePF)		//@parm the anti-event for any paragraph formatting
							// replacement
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::CReplaceRangeAE");

	_cpMin 	= cpMin;
	_cpMax 	= cpMax;
	_cchDel = cchDel;
	_pchDel	= pchDel;
	_paeCF  = paeCF;
	_paePF  = paePF;
}

/*
 *	CReplaceRangeAE::~CReplaceRangeAE
 *
 *	@mfunc	Destructor
 */
CReplaceRangeAE::~CReplaceRangeAE()
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::~CReplaceRangeAE");
		
	if( _pchDel )
	{
		delete _pchDel;
	}
}

/*
 *	CReplaceFormattingAE
 *
 *	@mfunc	Destroys this instance
 */
void CReplaceFormattingAE::Destroy()
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::Destroy");

	CBaseAE::Destroy();
	delete this;
}

/*
 *	CReplaceFormattingAE::Undo
 *
 *	@mfunc		Undoes a formatting operation
 *
 *	@devnote	This anti-event assumes that the text to which formatting
 *				should be applied exists!!
 */			
HRESULT CReplaceFormattingAE::Undo( 
	CTxtEdit *ped,		//@parm The CTxtEdit closure
	IUndoBuilder *publdr)	//@parm the undo builder context
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::Undo");

	HRESULT hr;
	DWORD i;
	IFormatCache *pf;
	DWORD cchEaten;
	DWORD iRunMerge;
	CNotifyMgr *pnm;
	DWORD cchTotal = 0;
	CFormatRuns **ppfmtruns;
	CTxtStory *pStory = ped->GetTxtStory();
	IAntiEvent *pae;
	LONG delta;

	// first, set things up correctly for whether we are paragraph
	// or character formatting
	CFormatRunPtr rp(_fPara ? pStory->GetPFRuns() :pStory->GetCFRuns());


	if( _fPara )
	{
		hr = GetParaFormatCache((IParaFormatCache **)&pf);
	}
	else
	{
		hr = GetCharFormatCache((ICharFormatCache **)&pf);
	}

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

	// first, count up the total number of characters affected
	for( i = 0 ; i < _cRuns; i++ )
	{
		cchTotal += _prgRuns[i]._cch;
	}

	pnm = ped->GetNotifyMgr();

	// we are going to be adding in some runs, so be sure the format
	// run array is allocated!

	if( !rp.IsValid() )
	{
		if( _fPara )
		{
			ppfmtruns = &(pStory->_pPFRuns);
		}
		else
		{
			ppfmtruns = &(pStory->_pCFRuns);
		}
		if( !rp.InitRuns(0, ped->GetTextLength(), ppfmtruns) )
		{
			return E_OUTOFMEMORY;
		}

		// tell folks we allocated a new run
		if( pnm )
		{
			pnm->NotifyPostReplaceRange(NULL, INFINITE, 0, 0, INFINITE, INFINITE);
		}
	} 
	// now do a pre-notification of the change we are about to make
	// This let's objects like a delayed render data object grab
	// any data *before* we change it.

	rp.BindToCp(_cp);

	// do a little more checking
	Assert(rp.GetCch() == ped->GetTextLength());


	if( pnm )
	{
		pnm->NotifyPreReplaceRange(NULL, INFINITE, 0, 0, _cp, _cp + cchTotal );
	}
		

	// we want to merge runs with where we start plus one behind.
	iRunMerge = rp._iRun;
	if( iRunMerge > 0 )
		iRunMerge--;

	// if we need to be able to undo this opertion, go through and
	// save existing run information
	if( publdr )
	{
		pae = gAEDispenser.CreateReplaceFormattingAE(ped, rp, cchTotal, 
				pf, _fPara);

		if( pae )
		{
			publdr->AddAntiEvent(pae);
		}
	}	
		
	// now go through and apply the saved formatting.
	for( i = 0; i < _cRuns; i++ )
	{
		cchEaten = 0;

        // use a do-while, because we may have a zero-length
        // format run.  We know we need to do "something" at
        // least once, because otherwise, we would not have
        // bothered creating a run!
		do 
		{
			delta = rp.SetFormat(_prgRuns[i]._iFormat, 
							_prgRuns[i]._cch - cchEaten, pf);

			if( delta == -1 )
			{
				ped->GetCallMgr()->SetOutOfMemory();
				break;
			}
			cchEaten += delta;
		} while( cchEaten < _prgRuns[i]._cch );
	}

	// merge formatting runs in case there are duplicate formatting
	// runs side by side
    rp.NextRun();
	rp.MergeRuns(iRunMerge, pf);

	// make sure the runs are still OK.  
	Assert(rp.GetCch() == ped->GetTextLength());

	if( pnm )
	{
		pnm->NotifyPostReplaceRange(NULL, INFINITE, 0, 0, _cp, _cp + cchTotal);
	}

	ped->GetCallMgr()->SetChangeEvent(CN_GENERIC);



	return CBaseAE::Undo(ped, publdr);
}

/*
 *	CReplaceFormattingAE::CReplaceFormattingAE
 *
 *	@mfunc	Constructor.  During construction, we will loop through and
 *			find all of the formats for the given text range
 */
CReplaceFormattingAE::CReplaceFormattingAE(
	CFormatRunPtr &rpIn, 			//@parm	the run pointer to start with
	DWORD cch,						//@parm the number of characters to 
									//find formatting info on
	IFormatCache *pf,				//@parm the format cache (to AddRef/
									//Release formats) 
	BOOL fPara)						//@parm If TRUE, the the formatting is
									//for paragraphs
{
	TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::CReplaceFormattingAE");

	LONG cchtemp = (LONG)cch;
	DWORD i;
    DWORD cchLeft;
    

	CFormatRunPtr rp(rpIn);			//we use 2 format run pointers to avoid
	CFormatRunPtr rpTemp(rpIn);		//backing up after counting the number of
									//format runs
	
	Assert(pf);

	_cp = rpIn.GetCp();
	_fPara = fPara;

	// count the number of formats needed.  Recall that even
    // if 0 characters are to be deleted, we may still be 
    // "deleting" a zero length format run.
	_cRuns = 0;
    do
	{
		_cRuns++;
        cchLeft = rp.GetCchLeft();
		cchtemp -= min((LONG)cchLeft, cchtemp);
        rp.NextRun();
	} while( cchtemp > 0 );

	_prgRuns = new CFormatRun[_cRuns];

	if( !_prgRuns )
	{
		_cRuns = 0;
		return;
	}

	for( i = 0; i < _cRuns; i++ )
	{
		_prgRuns[i]._cch = min( cch, rpTemp.GetCchLeft());
		_prgRuns[i]._iFormat = rpTemp.GetRun(0)->_iFormat;
		pf->AddRefFormat(_prgRuns[i]._iFormat);
		rpTemp.NextRun();
		cch -= _prgRuns[i]._cch;
	}

	Assert(cch == 0);

	return;

⌨️ 快捷键说明

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