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.

1062 lines
26 KiB

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