Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1000 lines
25 KiB

  1. /*
  2. * @doc INTERNAL
  3. *
  4. * @module ANTIEVT.C |
  5. *
  6. * Purpose:
  7. * implemenation of common antievents and a caching mechanism
  8. *
  9. * Author:
  10. * alexgo 3/25/95
  11. *
  12. * Copyright (c) 1995-2000, Microsoft Corporation. All rights reserved.
  13. */
  14. #include "_common.h"
  15. #include "_m_undo.h"
  16. #include "_edit.h"
  17. #include "_antievt.h"
  18. #include "_range.h"
  19. #include "_select.h"
  20. #include "_format.h"
  21. #include "_coleobj.h"
  22. #include "_objmgr.h"
  23. #ifdef DEBUG
  24. #include "_uspi.h"
  25. #endif
  26. ASSERTDATA
  27. //
  28. // CAntiEventDispenser global instance
  29. //
  30. CAntiEventDispenser gAEDispenser;
  31. //
  32. // CBaseAE PUBLIC methods
  33. //
  34. /*
  35. * CBaseAE::Destroy ()
  36. *
  37. * @mfunc
  38. * sends the Destroy notification to the next antievent in the list
  39. */
  40. void CBaseAE::Destroy()
  41. {
  42. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::Destroy");
  43. }
  44. /*
  45. * CBaseAE::Undo (ped, publdr)
  46. *
  47. * @mfunc
  48. * sends the Undo notification to the next antievent in the list
  49. *
  50. * @rdesc HRESULT
  51. */
  52. HRESULT CBaseAE::Undo(
  53. CTxtEdit * ped, //@parm Edit context for this undo operation
  54. IUndoBuilder *publdr) //@parm Undo context.
  55. {
  56. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::Undo");
  57. return NOERROR;
  58. }
  59. /*
  60. * CBaseAE::OnCommit (ped)
  61. *
  62. * @mfunc called after the antievent is added to the undo stack
  63. *
  64. * @rdesc void
  65. */
  66. void CBaseAE::OnCommit(
  67. CTxtEdit *ped) //@parm Edit context
  68. {
  69. }
  70. /*
  71. * CBaseAE::MergeData (dwDataType, pdata)
  72. *
  73. * @mfunc simply forwards the merge data request to the next antievent
  74. * (if one exists)
  75. *
  76. * @rdesc HRESULT. If S_FALSE, indicates that nothing could be done
  77. * with the merge data.
  78. */
  79. HRESULT CBaseAE::MergeData(
  80. DWORD dwDataType, //@parm Type of data in <p pdata>
  81. void *pdata) //@parm Merge data
  82. {
  83. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::MergeData");
  84. return S_FALSE;
  85. }
  86. /*
  87. * CBaseAE::SetNext(pNext)
  88. *
  89. * @mfunc
  90. * informs this antievent of the antievent which should follow it
  91. */
  92. void CBaseAE::SetNext(
  93. IAntiEvent *pNext) //@parm the AntiEvent to link to
  94. {
  95. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::SetNext");
  96. _pnext = pNext;
  97. }
  98. /*
  99. * CBaseAE::GetNext()
  100. *
  101. * @mfunc
  102. * retrieves the next element (if any)
  103. *
  104. * @rdesc a pointer to the next AntiEvent
  105. */
  106. IAntiEvent *CBaseAE::GetNext()
  107. {
  108. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::GetNext");
  109. return _pnext;
  110. }
  111. //
  112. // CBaseAE PROTECTED methods
  113. //
  114. /*
  115. * CBaseAE::CBaseAE()
  116. *
  117. * @mfunc Constructor
  118. */
  119. CBaseAE::CBaseAE()
  120. {
  121. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CBaseAE::CBaseAE");
  122. _pnext = NULL;
  123. }
  124. /*
  125. * CReplaceRangeAE::Destroy ()
  126. *
  127. * @mfunc
  128. * deletes this instance
  129. */
  130. void CReplaceRangeAE::Destroy()
  131. {
  132. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::Destroy");
  133. if(_paeCF)
  134. {
  135. _paeCF->Destroy();
  136. _paeCF = NULL;
  137. }
  138. if(_paePF)
  139. {
  140. _paePF->Destroy();
  141. _paePF = NULL;
  142. }
  143. CBaseAE::Destroy();
  144. delete this;
  145. }
  146. /*
  147. * CReplaceRangeAE::Undo (ped, publdr)
  148. *
  149. * @mfunc
  150. * undoes a CTxtPtr::ReplaceRange operation
  151. *
  152. * @rdesc
  153. * HRESULT
  154. *
  155. * @comm
  156. * Algorithm:
  157. *
  158. * A replace range works as follows: delete n characters and in their
  159. * place, put m characters.
  160. *
  161. * To undo this, we delete m characters and restore the n that were
  162. * originally deleted. Note that we restore the n characters with
  163. * default formatting. If there was any other formatting to those
  164. * characters, a separate antievent (CReplaceFormattingAE) will
  165. * apply the correct formatting.
  166. */
  167. HRESULT CReplaceRangeAE::Undo(
  168. CTxtEdit * ped, //@parm Context for this undo operation
  169. IUndoBuilder *publdr) //@parm Undo context
  170. {
  171. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::Undo");
  172. CRchTxtPtr rtp(ped, _cpMin);
  173. LONG cchMove = 0;
  174. rtp.ReplaceRange(_cpMax - _cpMin, _cchDel, _pchDel,
  175. publdr, -1, &cchMove,
  176. RR_ITMZ_NONE | RR_NO_TRD_CHECK); // RAID 6554
  177. // Passing NULL for the publdr is *extremely* important
  178. // below. The rich text pointer ReplaceRange call will
  179. // already generate the appropriate antievents for any
  180. // deleted formatting, so we do not need to repeat that here.
  181. if(_paeCF)
  182. _paeCF->Undo(ped, NULL);
  183. if(_paePF)
  184. _paePF->Undo(ped, NULL);
  185. if (ped->IsComplexScript())
  186. {
  187. // For complex script doc, we need itemization at the end of the range undo.
  188. // Since the formattings were rolled back, the rtp's runptrs are no longer
  189. // reliable.
  190. if (_paeCF && rtp._rpCF.IsValid())
  191. rtp._rpCF.BindToCp(_cpMin + _cchDel);
  192. if (_paePF && rtp._rpPF.IsValid())
  193. rtp._rpPF.BindToCp(_cpMin + _cchDel);
  194. rtp.ItemizeReplaceRange(_cchDel, cchMove, NULL, FALSE);
  195. }
  196. return CBaseAE::Undo(ped, publdr);
  197. }
  198. /*
  199. * CReplaceRangeAE::MergeData (dwDataType, pdata)
  200. *
  201. * @mfunc gives the caller a chance to extend the current antievent
  202. * if we're in merge typing mode
  203. *
  204. * @rdesc
  205. * HRESULT
  206. *
  207. * @comm if the requested data can be trivially merged into this
  208. * antievent, then do so; otherwise, return S_FALSE.
  209. *
  210. * There are two cases of interest: <nl>
  211. * 1. typing another character
  212. * 2. backspacing over a character in this merge
  213. * typing session.
  214. */
  215. HRESULT CReplaceRangeAE::MergeData(
  216. DWORD dwDataType, //@parm Type of <p pdata>
  217. void *pdata) //@parm Merge data
  218. {
  219. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::MergeData");
  220. if(dwDataType == MD_SIMPLE_REPLACERANGE)
  221. {
  222. SimpleReplaceRange *psr = (SimpleReplaceRange *)pdata;
  223. // Test for first case: just typing another character
  224. if(psr->cpMin == _cpMax && psr->cchDel == 0)
  225. {
  226. _cpMax = psr->cpMax;
  227. return NOERROR;
  228. }
  229. // Second case: deleting text stored in this antievent
  230. if (psr->cpMax == psr->cpMin &&
  231. psr->cpMin + psr->cchDel == _cpMax &&
  232. psr->cpMin >= _cpMin)
  233. {
  234. _cpMax = psr->cpMax;
  235. return NOERROR;
  236. }
  237. }
  238. return S_FALSE;
  239. }
  240. /*
  241. * CReplaceRangeAE::CReplaceRangeAE (cpMin, cpMax, cchDel, pchDel, paeCF, paePF)
  242. *
  243. * @mfunc Constructor for a text replace range antievent
  244. */
  245. CReplaceRangeAE::CReplaceRangeAE(
  246. LONG cpMin, //@parm cp starting the *final* range
  247. LONG cpMax, //@parm cp ending the *final* range
  248. LONG cchDel, //@parm # of chars deleted during ReplaceRange
  249. WCHAR *pchDel, //@parm Deleted characters. Ownership xfers to this object
  250. IAntiEvent *paeCF, //@parm Antievent for any character formatting replacement
  251. IAntiEvent *paePF) //@parm Antievent for any paragraph formatting replacement
  252. {
  253. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::CReplaceRangeAE");
  254. _cpMin = cpMin;
  255. _cpMax = cpMax;
  256. _cchDel = cchDel;
  257. _pchDel = pchDel;
  258. _paeCF = paeCF;
  259. _paePF = paePF;
  260. }
  261. /*
  262. * CReplaceRangeAE::~CReplaceRangeAE ()
  263. *
  264. * @mfunc Destructor
  265. */
  266. CReplaceRangeAE::~CReplaceRangeAE()
  267. {
  268. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceRangeAE::~CReplaceRangeAE");
  269. if(_pchDel)
  270. delete _pchDel;
  271. }
  272. /*
  273. * CReplaceFormattingAE
  274. *
  275. * @mfunc Destroys this instance
  276. */
  277. void CReplaceFormattingAE::Destroy()
  278. {
  279. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::Destroy");
  280. CBaseAE::Destroy();
  281. delete this;
  282. }
  283. /*
  284. * CReplaceFormattingAE::Undo (ped, publdr)
  285. *
  286. * @mfunc Undoes a formatting operation
  287. *
  288. * @rdesc
  289. * HRESULT
  290. *
  291. * @devnote This antievent assumes that the text to which formatting
  292. * should be applied exists!!
  293. */
  294. HRESULT CReplaceFormattingAE::Undo(
  295. CTxtEdit * ped, //@parm CTxtEdit closure
  296. IUndoBuilder *publdr) //@parm Undo builder context
  297. {
  298. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::Undo");
  299. LONG cchEaten;
  300. LONG cchTotal = 0;
  301. LONG delta;
  302. LONG iRunMerge;
  303. IAntiEvent * pae;
  304. IFormatCache * pf = _fPara
  305. ? (IFormatCache *)GetParaFormatCache()
  306. : (IFormatCache *)GetCharFormatCache();
  307. CNotifyMgr * pnm = ped->GetNotifyMgr();
  308. CFormatRuns ** ppfmtruns;
  309. CTxtStory * pStory = ped->GetTxtStory();
  310. const CParaFormat * pDefPF = _fPara ? pStory->GetParaFormat(-1) : NULL;
  311. BYTE bDefPFLevel = pDefPF && pDefPF->IsRtl() ? 1 : 0;
  312. // First set things up correctly for whether we are paragraph
  313. // or character formatting
  314. CFormatRunPtr rp(_fPara ? pStory->GetPFRuns() :pStory->GetCFRuns());
  315. // Count up count of characters affected
  316. for(LONG i = 0 ; i < _cRuns; i++)
  317. cchTotal += _prgRuns[i]._cch;
  318. // We are going to be adding in some runs, so be sure the format
  319. // run array is allocated!
  320. if(!rp.IsValid())
  321. {
  322. ppfmtruns = _fPara ? &(pStory->_pPFRuns) : &(pStory->_pCFRuns);
  323. if(!rp.InitRuns(0, ped->GetTextLength(), ppfmtruns))
  324. return E_OUTOFMEMORY;
  325. // tell folks we allocated a new run
  326. if(pnm)
  327. pnm->NotifyPostReplaceRange(NULL, CP_INFINITE, 0, 0, CP_INFINITE, CP_INFINITE);
  328. }
  329. // Now do a pre-notification of the change we are about to make
  330. // This lets objects like a delayed render data object grab
  331. // any data *before* we change it.
  332. // Do a little more checking
  333. #ifdef DEBUG
  334. LONG cchText = ped->GetTextLength();
  335. LONG cp =
  336. #endif
  337. rp.BindToCp(_cp);
  338. AssertSz(_cp == cp && rp.CalcTextLength() == cchText && _cp <= cchText,
  339. "CReplaceFormattingAE::Undo: invalid cp");
  340. if(pnm)
  341. pnm->NotifyPreReplaceRange(NULL, CP_INFINITE, 0, 0, _cp, _cp + cchTotal);
  342. // We want to merge runs with where we start plus one behind
  343. iRunMerge = rp._iRun;
  344. if(iRunMerge > 0)
  345. iRunMerge--;
  346. // If we need to be able to undo this operation, go through and
  347. // save existing run information
  348. if(publdr)
  349. {
  350. LONG cchBackup = 0, cchMove = 0;
  351. if (ped->IsBiDi())
  352. {
  353. // For redo'ing purpose, we expand the range to keep in the antievent
  354. // to make sure that BiDi levels are recorded adequately.
  355. CRchTxtPtr rtp(ped, _cp);
  356. cchBackup = rtp.ExpandRangeFormatting(cchTotal, 0, cchMove);
  357. Assert(cchBackup <= 0);
  358. rp.Move(cchBackup);
  359. }
  360. pae = gAEDispenser.CreateReplaceFormattingAE(ped, _cp + cchBackup, rp,
  361. cchTotal - cchBackup + cchMove, pf, _fPara);
  362. rp.Move(-cchBackup);
  363. if(pae)
  364. publdr->AddAntiEvent(pae);
  365. }
  366. // Now go through and apply the saved formatting.
  367. for(i = 0; i < _cRuns; i++)
  368. {
  369. cchEaten = 0;
  370. // Use a do-while, because we may have a zero-length
  371. // format run. We know we need to do "something" at
  372. // least once, because otherwise, we would not have
  373. // bothered creating a run!
  374. do
  375. {
  376. if (_fPara && _prgRuns[i]._iFormat == -1)
  377. // (#6768) The -1 format may have changed before undoing.
  378. _prgRuns[i]._level._value = bDefPFLevel;
  379. delta = rp.SetFormat(_prgRuns[i]._iFormat,
  380. _prgRuns[i]._cch - cchEaten, pf, &_prgRuns[i]._level);
  381. if(delta == -1)
  382. {
  383. ped->GetCallMgr()->SetOutOfMemory();
  384. break;
  385. }
  386. cchEaten += delta;
  387. } while(cchEaten < _prgRuns[i]._cch);
  388. }
  389. // Merge formatting runs in case there are duplicate formatting
  390. // runs side by side
  391. rp.NextRun();
  392. rp.MergeRuns(iRunMerge, pf);
  393. // Make sure the runs are still OK
  394. AssertNr(rp.CalcTextLength() == cchText);
  395. if(pnm)
  396. pnm->NotifyPostReplaceRange(NULL, CP_INFINITE, 0, 0, _cp, _cp + cchTotal);
  397. ped->GetCallMgr()->SetChangeEvent(CN_GENERIC);
  398. return CBaseAE::Undo(ped, publdr);
  399. }
  400. /*
  401. * CReplaceFormattingAE::CReplaceFormattingAE(ped, cp, &rpIn, cch, pf, fPara)
  402. *
  403. * @mfunc Constructor. During construction, we will loop through and
  404. * find all of the formats for the given text range
  405. */
  406. CReplaceFormattingAE::CReplaceFormattingAE(
  407. CTxtEdit * ped, //@parm CTxtEdit
  408. LONG cp, //@parm cp at start of replace
  409. CFormatRunPtr &rpIn, //@parm Run pointer to start with
  410. LONG cch, //@parm cch to find formatting info on
  411. IFormatCache * pf, //@parm Format cache (to AddRef/Release formats)
  412. BOOL fPara) //@parm If TRUE, formatting is for paras
  413. {
  414. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::CReplaceFormattingAE");
  415. LONG cchLeft;
  416. LONG cchTemp = cch;
  417. CFormatRunPtr rp(rpIn); // We use 2 format run pointers to avoid
  418. CFormatRunPtr rpTemp(rpIn); // backing up after counting the number of
  419. // format runs
  420. Assert(pf);
  421. _cp = cp;
  422. AssertSz(_cp == (cp = rpIn.CalculateCp()),
  423. "CReplaceFormattingAE::CReplaceFormattingAE: illegal cp");
  424. _fPara = fPara;
  425. // Count the number of formats needed. Recall that even if no characters
  426. // are to be deleted, we may still be "deleting" a zero length format run.
  427. _cRuns = 0;
  428. do
  429. {
  430. _cRuns++;
  431. cchLeft = rp.GetCchLeft();
  432. cchTemp -= min(cchLeft, cchTemp);
  433. } while(rp.NextRun() && cchTemp > 0);
  434. _prgRuns = new CFormatRun[_cRuns];
  435. if(!_prgRuns)
  436. {
  437. _cRuns = 0;
  438. return;
  439. }
  440. for(LONG i = 0; i < _cRuns; i++)
  441. {
  442. _prgRuns[i]._cch = min(cch, rpTemp.GetCchLeft());
  443. CFormatRun *pRun = rpTemp.GetRun(0);
  444. _prgRuns[i]._iFormat = pRun->_iFormat;
  445. _prgRuns[i]._level = pRun->_level;
  446. pf->AddRef(_prgRuns[i]._iFormat);
  447. rpTemp.NextRun();
  448. cch -= _prgRuns[i]._cch;
  449. }
  450. Assert(cch == 0);
  451. }
  452. /*
  453. * CReplaceFormattingAE::~CReplaceFormattingAE ()
  454. *
  455. * @mfunc Destructor
  456. */
  457. CReplaceFormattingAE::~CReplaceFormattingAE()
  458. {
  459. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceFormattingAE::~CReplaceFormattingAE");
  460. IFormatCache * pf = _fPara
  461. ? (IFormatCache *)GetParaFormatCache()
  462. : (IFormatCache *)GetCharFormatCache();
  463. if(_prgRuns)
  464. {
  465. if(pf)
  466. {
  467. for(LONG i = 0; i < _cRuns; i++)
  468. pf->Release(_prgRuns[i]._iFormat);
  469. }
  470. delete _prgRuns;
  471. }
  472. }
  473. //
  474. // CReplaceObjectAE PUBLIC methods
  475. //
  476. /*
  477. * CReplaceObjectAE::Destroy()
  478. *
  479. * @mfunc Destroy's this object
  480. */
  481. void CReplaceObjectAE::Destroy()
  482. {
  483. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::Destroy");
  484. COleObject *pobj = _pobj;
  485. _pobj = NULL;
  486. // We only need to zombie the object if it wasn't put back into
  487. // the document.
  488. if(!_fUndoInvoked)
  489. pobj->MakeZombie();
  490. pobj->Release();
  491. CBaseAE::Destroy();
  492. delete this;
  493. }
  494. /*
  495. * CReplaceObjectAE::Undo (ped, publdr)
  496. *
  497. * @mfunc
  498. * Undo'es the delete operation and restores the object
  499. * to its original state
  500. *
  501. * @rdesc HRESULT
  502. */
  503. HRESULT CReplaceObjectAE::Undo(
  504. CTxtEdit * ped, //@parm Edit context
  505. IUndoBuilder *publdr) //@parm Undo/redo context
  506. {
  507. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::Undo");
  508. CObjectMgr *pobjmgr = ped->GetObjectMgr();
  509. if(_pobj && pobjmgr)
  510. {
  511. _fUndoInvoked = TRUE;
  512. _pobj->Restore();
  513. pobjmgr->RestoreObject(_pobj);
  514. }
  515. return CBaseAE::Undo(ped, publdr);
  516. }
  517. /*
  518. * CReplaceObjectAE::OnCommit(ped)
  519. *
  520. * @mfunc called when the antievent chain is committed to the
  521. * undo stack. This gives us a chance to make 'dangerous'
  522. * calls that could cause us to be re-entered.
  523. */
  524. void CReplaceObjectAE::OnCommit(
  525. CTxtEdit *ped) //@parm Edit context
  526. {
  527. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::OnCommit");
  528. _pobj->Close(OLECLOSE_SAVEIFDIRTY);
  529. }
  530. //
  531. // CReplaceObjectAE PRIVATE methods
  532. //
  533. /*
  534. * CReplaceObjectAE::CReplaceObjectAE (pobj)
  535. *
  536. * @mfunc constructor
  537. */
  538. CReplaceObjectAE::CReplaceObjectAE(
  539. COleObject *pobj) //@parm Object that was deleted
  540. {
  541. _fUndoInvoked = FALSE;
  542. _pobj = pobj;
  543. _pobj->AddRef();
  544. }
  545. /*
  546. * CReplaceObjectAE::~CReplaceObjectAE
  547. *
  548. * @mfunc destructor
  549. */
  550. CReplaceObjectAE::~CReplaceObjectAE()
  551. {
  552. Assert(_pobj == NULL);
  553. }
  554. //
  555. // CResizeObjectAE PUBLIC methods
  556. //
  557. /*
  558. * CResizeObjectAE::Destroy ()
  559. *
  560. * @mfunc Destroy's this object
  561. */
  562. void CResizeObjectAE::Destroy()
  563. {
  564. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CResizeObjectAE::Destroy");
  565. _pobj = NULL;
  566. CBaseAE::Destroy();
  567. delete this;
  568. }
  569. /*
  570. * CResizeObjectAE::Undo(ped, publdr)
  571. *
  572. * @mfunc Undo'es the resize operation and restores the object
  573. * to it's original size/position
  574. *
  575. * @rdesc HRESULT
  576. */
  577. HRESULT CResizeObjectAE::Undo(
  578. CTxtEdit * ped, //@parm Edit context
  579. IUndoBuilder *publdr) //@parm Undo/redo context
  580. {
  581. CObjectMgr *pobjmgr;
  582. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::Undo");
  583. pobjmgr = ped->GetObjectMgr();
  584. if(_pobj && pobjmgr)
  585. {
  586. _fUndoInvoked = TRUE;
  587. _pobj->Resize(_size, FALSE);
  588. }
  589. return CBaseAE::Undo(ped, publdr);
  590. }
  591. /*
  592. * CResizeObjectAE::OnCommit(ped)
  593. *
  594. * @mfunc called when the antievent chain is committed to the
  595. * undo stack. This gives us a chance to make 'dangerous'
  596. * calls that could cause us to be re-entered.
  597. */
  598. void CResizeObjectAE::OnCommit(
  599. CTxtEdit *ped) //@parm Edit context
  600. {
  601. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CReplaceObjectAE::OnCommit");
  602. }
  603. //
  604. // CResizeObjectAE PRIVATE methods
  605. //
  606. /*
  607. * CResizeObjectAE::CResizeObjectAE (pobj, size)
  608. *
  609. * @mfunc constructor
  610. */
  611. CResizeObjectAE::CResizeObjectAE(
  612. COleObject *pobj, //@parm Object that was resized
  613. SIZEUV size) //@parm Old size
  614. {
  615. _fUndoInvoked = FALSE;
  616. _pobj = pobj;
  617. _size = size;
  618. }
  619. /*
  620. * CResizeObjectAE::~CResizeObjectAE
  621. *
  622. * @mfunc destructor
  623. */
  624. CResizeObjectAE::~CResizeObjectAE()
  625. {
  626. Assert(_pobj == NULL);
  627. }
  628. //
  629. // CSelectionAE PUBLIC methods
  630. //
  631. /*
  632. * CSelectionAE::Destroy ()
  633. *
  634. * @mfunc gets rid of this instance
  635. */
  636. void CSelectionAE::Destroy()
  637. {
  638. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CSelectionAE::Destroy");
  639. CBaseAE::Destroy();
  640. delete this;
  641. }
  642. /*
  643. * CSelectionAE::Undo (ped, publdr)
  644. *
  645. * @mfunc Restore selection to its former position
  646. *
  647. * @rdesc NOERROR
  648. */
  649. HRESULT CSelectionAE::Undo(
  650. CTxtEdit * ped, //@parm Edit context
  651. IUndoBuilder *publdr) //@parm Undo context
  652. {
  653. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CSelectionAE::Destroy");
  654. CTxtSelection *psel = ped->GetSel();
  655. if(psel)
  656. psel->SetDelayedSelectionRange(_cp, _cch);
  657. if(publdr)
  658. {
  659. IAntiEvent *pae;
  660. pae = gAEDispenser.CreateSelectionAE(ped, _cpNext, _cchNext,
  661. _cp, _cch);
  662. if(pae)
  663. publdr->AddAntiEvent(pae);
  664. }
  665. return CBaseAE::Undo(ped, publdr);
  666. }
  667. /*
  668. * CSelectionAE::MergeData(dwDataType, pdata)
  669. *
  670. * @mfunc merges new selection data
  671. *
  672. * @rdesc S_FALSE, NOERROR
  673. *
  674. * @comm The mergine algorithm is fairly tricky. There are basically two
  675. * cases of interest: group typing and drag-move.
  676. *
  677. * In the group typing case, the "start" of the typing becomes a
  678. * fixed reference from which characters are added or removed (i.e.
  679. * you type or hit the backspace key). "Undo" should return you to
  680. * that reference point; redo, on the other hand, should return the
  681. * selection to the last insertion point. Thus, we only update
  682. * _xxNext for the SELAE_MERGE action.
  683. *
  684. * Drag-Move is somewhat different; in this case, there are really
  685. * two actions--the "paste" on the drop, and the subsequent "cut"
  686. * operation. Thus, we need to be able to update the selection
  687. * antievent during the cut (since this only happens on move; not
  688. * copies). This is accomplished with teh FORCEREPLACE flag
  689. * and by setting fields to -1 to be ignored.
  690. *
  691. */
  692. HRESULT CSelectionAE::MergeData(
  693. DWORD dwDataType, //@parm Type of data in <p pdata>
  694. void *pdata) //@parm Merge data
  695. {
  696. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CSelectionAE::MergeData");
  697. SelRange *psrg = (SelRange *)pdata;
  698. if(dwDataType == MD_SELECTIONRANGE)
  699. {
  700. if(psrg->flags == SELAE_MERGE)
  701. {
  702. Assert(psrg->cpNext != -1);
  703. _cpNext = psrg->cpNext;
  704. _cchNext = psrg->cchNext;
  705. }
  706. else
  707. {
  708. // -1 is used a no-op, so we should ignore it
  709. if(psrg->cp != -1)
  710. {
  711. _cp = psrg->cp;
  712. _cch = psrg->cch;
  713. }
  714. if(psrg->cpNext != -1)
  715. {
  716. _cpNext = psrg->cpNext;
  717. _cchNext = psrg->cchNext;
  718. }
  719. }
  720. return NOERROR;
  721. }
  722. return S_FALSE;
  723. }
  724. //
  725. // CSelectionAE PRIVATE methods
  726. //
  727. /*
  728. * CSelectionAE::CSelectionAE (cp, cch, cpNext, cchNext)
  729. *
  730. * @mfunc Constructor
  731. */
  732. CSelectionAE::CSelectionAE(
  733. LONG cp, //@parm Active end cp
  734. LONG cch, //@parm Signed extension
  735. LONG cpNext, //@parm cp to use for the AE of this AE
  736. LONG cchNext) //@parm cch for the AE of this AE
  737. {
  738. _cp = cp;
  739. _cch = cch;
  740. _cpNext = cpNext;
  741. _cchNext = cchNext;
  742. }
  743. /*
  744. * CSelectionAE::~CSelectionAE()
  745. *
  746. * @mfunc desctructor
  747. */
  748. CSelectionAE::~CSelectionAE()
  749. {
  750. ;
  751. }
  752. /*
  753. * CAntiEventDispenser::CreateReplaceRangeAE(ped, cpMin, cpMax, cchDel,
  754. * pchDel, paeCF, paePF)
  755. * @mfunc
  756. * creates an antievent for a replace range operation
  757. *
  758. * @rdesc
  759. * IAntiEvent *
  760. */
  761. IAntiEvent * CAntiEventDispenser::CreateReplaceRangeAE(
  762. CTxtEdit * ped, //@parm edit context
  763. LONG cpMin, //@parm cp starting the *final* range
  764. LONG cpMax, //@parm cp ending the *final* range
  765. LONG cchDel, //@parm # of chars deleted during ReplaceRange
  766. WCHAR * pchDel, //@parm Deleted chars. Ownership transfers to this object
  767. IAntiEvent *paeCF, //@parm Antievent for any char formatting replacement
  768. IAntiEvent *paePF) //@parm Antievent for any para formatting replacement
  769. {
  770. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CAntiEventDispenser::CreateReplaceRangeAE");
  771. // FUTURE (alexgo): improve the efficiency of this routine!!
  772. IAntiEvent *pae = (IAntiEvent *)(new CReplaceRangeAE(cpMin, cpMax,
  773. cchDel, pchDel, paeCF, paePF));
  774. if(!pae)
  775. {
  776. // We don't need to do anything else; the callmgr will discard
  777. // undo for us.
  778. ped->GetCallMgr()->SetOutOfMemory();
  779. }
  780. return pae;
  781. }
  782. /*
  783. * CAntiEventDispenser::CreateReplaceFormattingAE(ped, cp, &rp, cch, pf, fPara)
  784. *
  785. * @mfunc
  786. * Creates an antievent for replacing formatting
  787. *
  788. * @rdesc
  789. * IAntiEvent *
  790. */
  791. IAntiEvent * CAntiEventDispenser::CreateReplaceFormattingAE(
  792. CTxtEdit * ped, //@parm Edit context
  793. LONG cp, //@parm Position at start of replace
  794. CFormatRunPtr & rp, //@parm Run pointer to start with
  795. LONG cch, //@parm Count of characters to find formatting info on
  796. IFormatCache * pf, //@parm Format cache (to AddRef/Release formats)
  797. BOOL fPara) //@parm If TRUE, formatting is paragraphs
  798. {
  799. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN, "CAntiEventDispenser::CreateReplaceFormattingAE");
  800. // FUTURE (alexgo): improve the efficiency of this routine!!!
  801. IAntiEvent *pae = (IAntiEvent *)(new CReplaceFormattingAE(ped, cp, rp, cch, pf, fPara));
  802. if(!pae)
  803. {
  804. // We don't need to do anything else; the callmgr will discard
  805. // undo for us.
  806. ped->GetCallMgr()->SetOutOfMemory();
  807. }
  808. return pae;
  809. }
  810. /*
  811. * CAntiEventDispenser::CreateReplaceObjectAE (ped, pobj)
  812. *
  813. * @mfunc Creates an antievent for replacing an object
  814. *
  815. * @rdesc
  816. * IAntiEvent * created
  817. */
  818. IAntiEvent * CAntiEventDispenser::CreateReplaceObjectAE(
  819. CTxtEdit * ped, //@parm Edit context.
  820. COleObject *pobj) //@parm Object that was deleted
  821. {
  822. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN,
  823. "CAntiEventDispenser::CreateReplaceObjectAE");
  824. // Always allocating is probably a reasonable strategy for objects;
  825. // they are not expected to be the bread & butter case.
  826. IAntiEvent *pae = (IAntiEvent *)(new CReplaceObjectAE(pobj));
  827. if(!pae)
  828. {
  829. // We don't need to do anything else; the callmgr will discard
  830. // undo for us.
  831. ped->GetCallMgr()->SetOutOfMemory();
  832. }
  833. return pae;
  834. }
  835. /*
  836. * CAntiEventDispenser::CreateResizeObjectAE (ped, pobj, size)
  837. *
  838. * @mfunc Creates an antievent for resizing an object
  839. *
  840. * @rdesc the created antievent
  841. */
  842. IAntiEvent * CAntiEventDispenser::CreateResizeObjectAE(
  843. CTxtEdit * ped, //@parm Edit context.
  844. COleObject *pobj, //@parm Object that was resized
  845. SIZEUV size) //@parm Old object position rectangle
  846. {
  847. TRACEBEGIN(TRCSUBSYSUNDO, TRCSCOPEINTERN,
  848. "CAntiEventDispenser::CreateResizeeObjectAE");
  849. // Always allocating is probably a reasonable strategy for objects;
  850. // they are not expected to be the bread & butter case.
  851. IAntiEvent *pae = (IAntiEvent *)(new CResizeObjectAE(pobj, size));
  852. if(!pae)
  853. {
  854. // We don't need to do anything else; the callmgr will discard
  855. // undo for us.
  856. ped->GetCallMgr()->SetOutOfMemory();
  857. }
  858. return pae;
  859. }
  860. /*
  861. * CAntiEventDispenser::CreateSelectionAE (ped, cp, cch, cpNext, cchNext)
  862. *
  863. * @mfunc Creates an antievent for restoring a non-degenerate selection
  864. *
  865. * @rdesc created antievent
  866. */
  867. IAntiEvent * CAntiEventDispenser::CreateSelectionAE(
  868. CTxtEdit *ped, //@parm Edit context
  869. LONG cp, //@parm Active end of selection
  870. LONG cch, //@parm Signed extension
  871. LONG cpNext, //@parm cp to use for AE of this AE
  872. LONG cchNext) //@parm cch to use for AE
  873. {
  874. // FUTURE (alexgo): improve the efficiency of this routine
  875. IAntiEvent *pae = (IAntiEvent *)(new CSelectionAE(cp, cch, cpNext, cchNext));
  876. if(!pae)
  877. {
  878. // We don't need to do anything else; the callmgr will discard
  879. // undo for us.
  880. ped->GetCallMgr()->SetOutOfMemory();
  881. }
  882. return pae;
  883. }