windows-nt/Source/XPSP1/NT/windows/richedit/re41/antievt.cpp
2020-09-26 16:20:57 +08:00

1001 lines
24 KiB
C++

/*
* @doc INTERNAL
*
* @module ANTIEVT.C |
*
* Purpose:
* implemenation of common antievents and a caching mechanism
*
* Author:
* alexgo 3/25/95
*
* Copyright (c) 1995-2000, Microsoft Corporation. All rights reserved.
*/
#include "_common.h"
#include "_m_undo.h"
#include "_edit.h"
#include "_antievt.h"
#include "_range.h"
#include "_select.h"
#include "_format.h"
#include "_coleobj.h"
#include "_objmgr.h"
#ifdef DEBUG
#include "_uspi.h"
#endif
ASSERTDATA
//
// CAntiEventDispenser global instance
//
CAntiEventDispenser gAEDispenser;
//
// CBaseAE PUBLIC methods
//
/*
* CBaseAE::Destroy ()
*
* @mfunc
* sends the Destroy notification to the next antievent in the list
*/
void CBaseAE::Destroy()
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::Destroy");
}
/*
* CBaseAE::Undo (ped, publdr)
*
* @mfunc
* sends the Undo notification to the next antievent in the list
*
* @rdesc HRESULT
*/
HRESULT CBaseAE::Undo(
CTxtEdit * ped, //@parm Edit context for this undo operation
IUndoBuilder *publdr) //@parm Undo context.
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::Undo");
return NOERROR;
}
/*
* CBaseAE::OnCommit (ped)
*
* @mfunc called after the antievent is added to the undo stack
*
* @rdesc void
*/
void CBaseAE::OnCommit(
CTxtEdit *ped) //@parm Edit context
{
}
/*
* CBaseAE::MergeData (dwDataType, pdata)
*
* @mfunc simply forwards the merge data request to the next antievent
* (if one exists)
*
* @rdesc HRESULT. If S_FALSE, indicates that nothing could be done
* with the merge data.
*/
HRESULT CBaseAE::MergeData(
DWORD dwDataType, //@parm Type of data in <p pdata>
void *pdata) //@parm Merge data
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::MergeData");
return S_FALSE;
}
/*
* CBaseAE::SetNext(pNext)
*
* @mfunc
* informs this antievent of the antievent 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()
{
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()
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::Destroy");
if(_paeCF)
{
_paeCF->Destroy();
_paeCF = NULL;
}
if(_paePF)
{
_paePF->Destroy();
_paePF = NULL;
}
CBaseAE::Destroy();
delete this;
}
/*
* CReplaceRangeAE::Undo (ped, publdr)
*
* @mfunc
* undoes a CTxtPtr::ReplaceRange operation
*
* @rdesc
* HRESULT
*
* @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 antievent (CReplaceFormattingAE) will
* apply the correct formatting.
*/
HRESULT CReplaceRangeAE::Undo(
CTxtEdit * ped, //@parm Context for this undo operation
IUndoBuilder *publdr) //@parm Undo context
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::Undo");
CRchTxtPtr rtp(ped, _cpMin);
LONG cchMove = 0;
rtp.ReplaceRange(_cpMax - _cpMin, _cchDel, _pchDel,
publdr, -1, &cchMove,
RR_ITMZ_NONE | RR_NO_TRD_CHECK); // RAID 6554
// Passing NULL for the publdr is *extremely* important
// below. The rich text pointer ReplaceRange call will
// already generate the appropriate antievents 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);
if (ped->IsComplexScript())
{
// For complex script doc, we need itemization at the end of the range undo.
// Since the formattings were rolled back, the rtp's runptrs are no longer
// reliable.
if (_paeCF && rtp._rpCF.IsValid())
rtp._rpCF.BindToCp(_cpMin + _cchDel);
if (_paePF && rtp._rpPF.IsValid())
rtp._rpPF.BindToCp(_cpMin + _cchDel);
rtp.ItemizeReplaceRange(_cchDel, cchMove, NULL, FALSE);
}
return CBaseAE::Undo(ped, publdr);
}
/*
* CReplaceRangeAE::MergeData (dwDataType, pdata)
*
* @mfunc gives the caller a chance to extend the current antievent
* if we're in merge typing mode
*
* @rdesc
* HRESULT
*
* @comm if the requested data can be trivially merged into this
* antievent, 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 Type of <p pdata>
void *pdata) //@parm Merge data
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::MergeData");
if(dwDataType == MD_SIMPLE_REPLACERANGE)
{
SimpleReplaceRange *psr = (SimpleReplaceRange *)pdata;
// Test for first case: just typing another character
if(psr->cpMin == _cpMax && psr->cchDel == 0)
{
_cpMax = psr->cpMax;
return NOERROR;
}
// Second case: deleting text stored in this antievent
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, cchDel, pchDel, paeCF, paePF)
*
* @mfunc Constructor for a text replace range antievent
*/
CReplaceRangeAE::CReplaceRangeAE(
LONG cpMin, //@parm cp starting the *final* range
LONG cpMax, //@parm cp ending the *final* range
LONG cchDel, //@parm # of chars deleted during ReplaceRange
WCHAR *pchDel, //@parm Deleted characters. Ownership xfers to this object
IAntiEvent *paeCF, //@parm Antievent for any character formatting replacement
IAntiEvent *paePF) //@parm Antievent 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 (ped, publdr)
*
* @mfunc Undoes a formatting operation
*
* @rdesc
* HRESULT
*
* @devnote This antievent assumes that the text to which formatting
* should be applied exists!!
*/
HRESULT CReplaceFormattingAE::Undo(
CTxtEdit * ped, //@parm CTxtEdit closure
IUndoBuilder *publdr) //@parm Undo builder context
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::Undo");
LONG cchEaten;
LONG cchTotal = 0;
LONG delta;
LONG iRunMerge;
IAntiEvent * pae;
IFormatCache * pf = _fPara
? (IFormatCache *)GetParaFormatCache()
: (IFormatCache *)GetCharFormatCache();
CNotifyMgr * pnm = ped->GetNotifyMgr();
CFormatRuns ** ppfmtruns;
CTxtStory * pStory = ped->GetTxtStory();
const CParaFormat * pDefPF = _fPara ? pStory->GetParaFormat(-1) : NULL;
BYTE bDefPFLevel = pDefPF && pDefPF->IsRtl() ? 1 : 0;
// First set things up correctly for whether we are paragraph
// or character formatting
CFormatRunPtr rp(_fPara ? pStory->GetPFRuns() :pStory->GetCFRuns());
// Count up count of characters affected
for(LONG i = 0 ; i < _cRuns; i++)
cchTotal += _prgRuns[i]._cch;
// We are going to be adding in some runs, so be sure the format
// run array is allocated!
if(!rp.IsValid())
{
ppfmtruns = _fPara ? &(pStory->_pPFRuns) : &(pStory->_pCFRuns);
if(!rp.InitRuns(0, ped->GetTextLength(), ppfmtruns))
return E_OUTOFMEMORY;
// tell folks we allocated a new run
if(pnm)
pnm->NotifyPostReplaceRange(NULL, CP_INFINITE, 0, 0, CP_INFINITE, CP_INFINITE);
}
// Now do a pre-notification of the change we are about to make
// This lets objects like a delayed render data object grab
// any data *before* we change it.
// Do a little more checking
#ifdef DEBUG
LONG cchText = ped->GetTextLength();
LONG cp =
#endif
rp.BindToCp(_cp);
AssertSz(_cp == cp && rp.CalcTextLength() == cchText && _cp <= cchText,
"CReplaceFormattingAE::Undo: invalid cp");
if(pnm)
pnm->NotifyPreReplaceRange(NULL, CP_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 operation, go through and
// save existing run information
if(publdr)
{
LONG cchBackup = 0, cchMove = 0;
if (ped->IsBiDi())
{
// For redo'ing purpose, we expand the range to keep in the antievent
// to make sure that BiDi levels are recorded adequately.
CRchTxtPtr rtp(ped, _cp);
cchBackup = rtp.ExpandRangeFormatting(cchTotal, 0, cchMove);
Assert(cchBackup <= 0);
rp.Move(cchBackup);
}
pae = gAEDispenser.CreateReplaceFormattingAE(ped, _cp + cchBackup, rp,
cchTotal - cchBackup + cchMove, pf, _fPara);
rp.Move(-cchBackup);
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
{
if (_fPara && _prgRuns[i]._iFormat == -1)
// (#6768) The -1 format may have changed before undoing.
_prgRuns[i]._level._value = bDefPFLevel;
delta = rp.SetFormat(_prgRuns[i]._iFormat,
_prgRuns[i]._cch - cchEaten, pf, &_prgRuns[i]._level);
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
AssertNr(rp.CalcTextLength() == cchText);
if(pnm)
pnm->NotifyPostReplaceRange(NULL, CP_INFINITE, 0, 0, _cp, _cp + cchTotal);
ped->GetCallMgr()->SetChangeEvent(CN_GENERIC);
return CBaseAE::Undo(ped, publdr);
}
/*
* CReplaceFormattingAE::CReplaceFormattingAE(ped, cp, &rpIn, cch, pf, fPara)
*
* @mfunc Constructor. During construction, we will loop through and
* find all of the formats for the given text range
*/
CReplaceFormattingAE::CReplaceFormattingAE(
CTxtEdit * ped, //@parm CTxtEdit
LONG cp, //@parm cp at start of replace
CFormatRunPtr &rpIn, //@parm Run pointer to start with
LONG cch, //@parm cch to find formatting info on
IFormatCache * pf, //@parm Format cache (to AddRef/Release formats)
BOOL fPara) //@parm If TRUE, formatting is for paras
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::CReplaceFormattingAE");
LONG cchLeft;
LONG cchTemp = cch;
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 = cp;
AssertSz(_cp == (cp = rpIn.CalculateCp()),
"CReplaceFormattingAE::CReplaceFormattingAE: illegal cp");
_fPara = fPara;
// Count the number of formats needed. Recall that even if no characters
// are to be deleted, we may still be "deleting" a zero length format run.
_cRuns = 0;
do
{
_cRuns++;
cchLeft = rp.GetCchLeft();
cchTemp -= min(cchLeft, cchTemp);
} while(rp.NextRun() && cchTemp > 0);
_prgRuns = new CFormatRun[_cRuns];
if(!_prgRuns)
{
_cRuns = 0;
return;
}
for(LONG i = 0; i < _cRuns; i++)
{
_prgRuns[i]._cch = min(cch, rpTemp.GetCchLeft());
CFormatRun *pRun = rpTemp.GetRun(0);
_prgRuns[i]._iFormat = pRun->_iFormat;
_prgRuns[i]._level = pRun->_level;
pf->AddRef(_prgRuns[i]._iFormat);
rpTemp.NextRun();
cch -= _prgRuns[i]._cch;
}
Assert(cch == 0);
}
/*
* CReplaceFormattingAE::~CReplaceFormattingAE ()
*
* @mfunc Destructor
*/
CReplaceFormattingAE::~CReplaceFormattingAE()
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::~CReplaceFormattingAE");
IFormatCache * pf = _fPara
? (IFormatCache *)GetParaFormatCache()
: (IFormatCache *)GetCharFormatCache();
if(_prgRuns)
{
if(pf)
{
for(LONG i = 0; i < _cRuns; i++)
pf->Release(_prgRuns[i]._iFormat);
}
delete _prgRuns;
}
}
//
// CReplaceObjectAE PUBLIC methods
//
/*
* CReplaceObjectAE::Destroy()
*
* @mfunc Destroy's this object
*/
void CReplaceObjectAE::Destroy()
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::Destroy");
COleObject *pobj = _pobj;
_pobj = NULL;
// We only need to zombie the object if it wasn't put back into
// the document.
if(!_fUndoInvoked)
pobj->MakeZombie();
pobj->Release();
CBaseAE::Destroy();
delete this;
}
/*
* CReplaceObjectAE::Undo (ped, publdr)
*
* @mfunc
* Undo'es the delete operation and restores the object
* to its original state
*
* @rdesc HRESULT
*/
HRESULT CReplaceObjectAE::Undo(
CTxtEdit * ped, //@parm Edit context
IUndoBuilder *publdr) //@parm Undo/redo context
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::Undo");
CObjectMgr *pobjmgr = ped->GetObjectMgr();
if(_pobj && pobjmgr)
{
_fUndoInvoked = TRUE;
_pobj->Restore();
pobjmgr->RestoreObject(_pobj);
}
return CBaseAE::Undo(ped, publdr);
}
/*
* CReplaceObjectAE::OnCommit(ped)
*
* @mfunc called when the antievent chain is committed to the
* undo stack. This gives us a chance to make 'dangerous'
* calls that could cause us to be re-entered.
*/
void CReplaceObjectAE::OnCommit(
CTxtEdit *ped) //@parm Edit context
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::OnCommit");
_pobj->Close(OLECLOSE_SAVEIFDIRTY);
}
//
// CReplaceObjectAE PRIVATE methods
//
/*
* CReplaceObjectAE::CReplaceObjectAE (pobj)
*
* @mfunc constructor
*/
CReplaceObjectAE::CReplaceObjectAE(
COleObject *pobj) //@parm Object that was deleted
{
_fUndoInvoked = FALSE;
_pobj = pobj;
_pobj->AddRef();
}
/*
* CReplaceObjectAE::~CReplaceObjectAE
*
* @mfunc destructor
*/
CReplaceObjectAE::~CReplaceObjectAE()
{
Assert(_pobj == NULL);
}
//
// CResizeObjectAE PUBLIC methods
//
/*
* CResizeObjectAE::Destroy ()
*
* @mfunc Destroy's this object
*/
void CResizeObjectAE::Destroy()
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CResizeObjectAE::Destroy");
_pobj = NULL;
CBaseAE::Destroy();
delete this;
}
/*
* CResizeObjectAE::Undo(ped, publdr)
*
* @mfunc Undo'es the resize operation and restores the object
* to it's original size/position
*
* @rdesc HRESULT
*/
HRESULT CResizeObjectAE::Undo(
CTxtEdit * ped, //@parm Edit context
IUndoBuilder *publdr) //@parm Undo/redo context
{
CObjectMgr *pobjmgr;
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::Undo");
pobjmgr = ped->GetObjectMgr();
if(_pobj && pobjmgr)
{
_fUndoInvoked = TRUE;
_pobj->Resize(_size, FALSE);
}
return CBaseAE::Undo(ped, publdr);
}
/*
* CResizeObjectAE::OnCommit(ped)
*
* @mfunc called when the antievent chain is committed to the
* undo stack. This gives us a chance to make 'dangerous'
* calls that could cause us to be re-entered.
*/
void CResizeObjectAE::OnCommit(
CTxtEdit *ped) //@parm Edit context
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::OnCommit");
}
//
// CResizeObjectAE PRIVATE methods
//
/*
* CResizeObjectAE::CResizeObjectAE (pobj, size)
*
* @mfunc constructor
*/
CResizeObjectAE::CResizeObjectAE(
COleObject *pobj, //@parm Object that was resized
SIZEUV size) //@parm Old size
{
_fUndoInvoked = FALSE;
_pobj = pobj;
_size = size;
}
/*
* CResizeObjectAE::~CResizeObjectAE
*
* @mfunc destructor
*/
CResizeObjectAE::~CResizeObjectAE()
{
Assert(_pobj == NULL);
}
//
// CSelectionAE PUBLIC methods
//
/*
* CSelectionAE::Destroy ()
*
* @mfunc gets rid of this instance
*/
void CSelectionAE::Destroy()
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CSelectionAE::Destroy");
CBaseAE::Destroy();
delete this;
}
/*
* CSelectionAE::Undo (ped, publdr)
*
* @mfunc Restore selection to its former position
*
* @rdesc NOERROR
*/
HRESULT CSelectionAE::Undo(
CTxtEdit * ped, //@parm Edit context
IUndoBuilder *publdr) //@parm Undo context
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CSelectionAE::Destroy");
CTxtSelection *psel = ped->GetSel();
if(psel)
psel->SetDelayedSelectionRange(_cp, _cch);
if(publdr)
{
IAntiEvent *pae;
pae = gAEDispenser.CreateSelectionAE(ped, _cpNext, _cchNext,
_cp, _cch);
if(pae)
publdr->AddAntiEvent(pae);
}
return CBaseAE::Undo(ped, publdr);
}
/*
* CSelectionAE::MergeData(dwDataType, pdata)
*
* @mfunc merges new selection data
*
* @rdesc S_FALSE, NOERROR
*
* @comm The mergine algorithm is fairly tricky. There are basically two
* cases of interest: group typing and drag-move.
*
* In the group typing case, the "start" of the typing becomes a
* fixed reference from which characters are added or removed (i.e.
* you type or hit the backspace key). "Undo" should return you to
* that reference point; redo, on the other hand, should return the
* selection to the last insertion point. Thus, we only update
* _xxNext for the SELAE_MERGE action.
*
* Drag-Move is somewhat different; in this case, there are really
* two actions--the "paste" on the drop, and the subsequent "cut"
* operation. Thus, we need to be able to update the selection
* antievent during the cut (since this only happens on move; not
* copies). This is accomplished with teh FORCEREPLACE flag
* and by setting fields to -1 to be ignored.
*
*/
HRESULT CSelectionAE::MergeData(
DWORD dwDataType, //@parm Type of data in <p pdata>
void *pdata) //@parm Merge data
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CSelectionAE::MergeData");
SelRange *psrg = (SelRange *)pdata;
if(dwDataType == MD_SELECTIONRANGE)
{
if(psrg->flags == SELAE_MERGE)
{
Assert(psrg->cpNext != -1);
_cpNext = psrg->cpNext;
_cchNext = psrg->cchNext;
}
else
{
// -1 is used a no-op, so we should ignore it
if(psrg->cp != -1)
{
_cp = psrg->cp;
_cch = psrg->cch;
}
if(psrg->cpNext != -1)
{
_cpNext = psrg->cpNext;
_cchNext = psrg->cchNext;
}
}
return NOERROR;
}
return S_FALSE;
}
//
// CSelectionAE PRIVATE methods
//
/*
* CSelectionAE::CSelectionAE (cp, cch, cpNext, cchNext)
*
* @mfunc Constructor
*/
CSelectionAE::CSelectionAE(
LONG cp, //@parm Active end cp
LONG cch, //@parm Signed extension
LONG cpNext, //@parm cp to use for the AE of this AE
LONG cchNext) //@parm cch for the AE of this AE
{
_cp = cp;
_cch = cch;
_cpNext = cpNext;
_cchNext = cchNext;
}
/*
* CSelectionAE::~CSelectionAE()
*
* @mfunc desctructor
*/
CSelectionAE::~CSelectionAE()
{
;
}
/*
* CAntiEventDispenser::CreateReplaceRangeAE(ped, cpMin, cpMax, cchDel,
* pchDel, paeCF, paePF)
* @mfunc
* creates an antievent for a replace range operation
*
* @rdesc
* IAntiEvent *
*/
IAntiEvent * CAntiEventDispenser::CreateReplaceRangeAE(
CTxtEdit * ped, //@parm edit context
LONG cpMin, //@parm cp starting the *final* range
LONG cpMax, //@parm cp ending the *final* range
LONG cchDel, //@parm # of chars deleted during ReplaceRange
WCHAR * pchDel, //@parm Deleted chars. Ownership transfers to this object
IAntiEvent *paeCF, //@parm Antievent for any char formatting replacement
IAntiEvent *paePF) //@parm Antievent for any para formatting replacement
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CAntiEventDispenser::CreateReplaceRangeAE");
// FUTURE (alexgo): improve the efficiency of this routine!!
IAntiEvent *pae = (IAntiEvent *)(new CReplaceRangeAE(cpMin, cpMax,
cchDel, pchDel, paeCF, paePF));
if(!pae)
{
// We don't need to do anything else; the callmgr will discard
// undo for us.
ped->GetCallMgr()->SetOutOfMemory();
}
return pae;
}
/*
* CAntiEventDispenser::CreateReplaceFormattingAE(ped, cp, &rp, cch, pf, fPara)
*
* @mfunc
* Creates an antievent for replacing formatting
*
* @rdesc
* IAntiEvent *
*/
IAntiEvent * CAntiEventDispenser::CreateReplaceFormattingAE(
CTxtEdit * ped, //@parm Edit context
LONG cp, //@parm Position at start of replace
CFormatRunPtr & rp, //@parm Run pointer to start with
LONG cch, //@parm Count of characters to find formatting info on
IFormatCache * pf, //@parm Format cache (to AddRef/Release formats)
BOOL fPara) //@parm If TRUE, formatting is paragraphs
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CAntiEventDispenser::CreateReplaceFormattingAE");
// FUTURE (alexgo): improve the efficiency of this routine!!!
IAntiEvent *pae = (IAntiEvent *)(new CReplaceFormattingAE(ped, cp, rp, cch, pf, fPara));
if(!pae)
{
// We don't need to do anything else; the callmgr will discard
// undo for us.
ped->GetCallMgr()->SetOutOfMemory();
}
return pae;
}
/*
* CAntiEventDispenser::CreateReplaceObjectAE (ped, pobj)
*
* @mfunc Creates an antievent for replacing an object
*
* @rdesc
* IAntiEvent * created
*/
IAntiEvent * CAntiEventDispenser::CreateReplaceObjectAE(
CTxtEdit * ped, //@parm Edit context.
COleObject *pobj) //@parm Object that was deleted
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN,
"CAntiEventDispenser::CreateReplaceObjectAE");
// Always allocating is probably a reasonable strategy for objects;
// they are not expected to be the bread & butter case.
IAntiEvent *pae = (IAntiEvent *)(new CReplaceObjectAE(pobj));
if(!pae)
{
// We don't need to do anything else; the callmgr will discard
// undo for us.
ped->GetCallMgr()->SetOutOfMemory();
}
return pae;
}
/*
* CAntiEventDispenser::CreateResizeObjectAE (ped, pobj, size)
*
* @mfunc Creates an antievent for resizing an object
*
* @rdesc the created antievent
*/
IAntiEvent * CAntiEventDispenser::CreateResizeObjectAE(
CTxtEdit * ped, //@parm Edit context.
COleObject *pobj, //@parm Object that was resized
SIZEUV size) //@parm Old object position rectangle
{
TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN,
"CAntiEventDispenser::CreateResizeeObjectAE");
// Always allocating is probably a reasonable strategy for objects;
// they are not expected to be the bread & butter case.
IAntiEvent *pae = (IAntiEvent *)(new CResizeObjectAE(pobj, size));
if(!pae)
{
// We don't need to do anything else; the callmgr will discard
// undo for us.
ped->GetCallMgr()->SetOutOfMemory();
}
return pae;
}
/*
* CAntiEventDispenser::CreateSelectionAE (ped, cp, cch, cpNext, cchNext)
*
* @mfunc Creates an antievent for restoring a non-degenerate selection
*
* @rdesc created antievent
*/
IAntiEvent * CAntiEventDispenser::CreateSelectionAE(
CTxtEdit *ped, //@parm Edit context
LONG cp, //@parm Active end of selection
LONG cch, //@parm Signed extension
LONG cpNext, //@parm cp to use for AE of this AE
LONG cchNext) //@parm cch to use for AE
{
// FUTURE (alexgo): improve the efficiency of this routine
IAntiEvent *pae = (IAntiEvent *)(new CSelectionAE(cp, cch, cpNext, cchNext));
if(!pae)
{
// We don't need to do anything else; the callmgr will discard
// undo for us.
ped->GetCallMgr()->SetOutOfMemory();
}
return pae;
}