LibreOffice Module sw (master)  1
undobj.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <libxml/xmlwriter.h>
21 
22 #include <IShellCursorSupplier.hxx>
23 #include <txtftn.hxx>
24 #include <fmtanchr.hxx>
25 #include <ftnidx.hxx>
26 #include <frmfmt.hxx>
27 #include <doc.hxx>
28 #include <UndoManager.hxx>
30 #include <docary.hxx>
31 #include <swcrsr.hxx>
32 #include <swundo.hxx>
33 #include <pam.hxx>
34 #include <ndtxt.hxx>
35 #include <UndoCore.hxx>
36 #include <rolbck.hxx>
37 #include <ndnotxt.hxx>
38 #include <IMark.hxx>
39 #include <mvsave.hxx>
40 #include <redline.hxx>
41 #include <crossrefbookmark.hxx>
42 #include <strings.hrc>
43 #include <docsh.hxx>
44 #include <view.hxx>
45 #include <frameformats.hxx>
46 #include <o3tl/deleter.hxx>
47 #include <sal/log.hxx>
48 
49 // This class saves the Pam as integers and can recompose those into a PaM
51  : m_nSttNode( 0 ), m_nEndNode( 0 ), m_nSttContent( 0 ), m_nEndContent( 0 )
52 {
53 }
54 
55 SwUndRng::SwUndRng( const SwPaM& rPam )
56 {
57  SetValues( rPam );
58 }
59 
60 void SwUndRng::SetValues( const SwPaM& rPam )
61 {
62  const SwPosition *pStt = rPam.Start();
63  if( rPam.HasMark() )
64  {
65  const SwPosition *pEnd = rPam.End();
66  m_nEndNode = pEnd->nNode.GetIndex();
68  }
69  else
70  {
71  // no selection !!
74  }
75 
76  m_nSttNode = pStt->nNode.GetIndex();
78 }
79 
80 void SwUndRng::SetPaM( SwPaM & rPam, bool bCorrToContent ) const
81 {
82  rPam.DeleteMark();
83  rPam.GetPoint()->nNode = m_nSttNode;
84  SwNode& rNd = rPam.GetNode();
85  if( rNd.IsContentNode() )
87  else if( bCorrToContent )
89  else
90  rPam.GetPoint()->nContent.Assign( nullptr, 0 );
91 
92  if( !m_nEndNode && COMPLETE_STRING == m_nEndContent ) // no selection
93  return ;
94 
95  rPam.SetMark();
97  return; // nothing left to do
98 
99  rPam.GetPoint()->nNode = m_nEndNode;
100  if( rPam.GetNode().IsContentNode() )
102  else if( bCorrToContent )
104  else
105  rPam.GetPoint()->nContent.Assign( nullptr, 0 );
106 }
107 
109  ::sw::UndoRedoContext & rContext, bool const bCorrToContent) const
110 {
111  SwCursor & rPaM( rContext.GetCursorSupplier().CreateNewShellCursor() );
112  SetPaM( rPaM, bCorrToContent );
113  return rPaM;
114 }
115 
117  const SwNodeOffset* pEndIdx )
118 {
119  SwNodeIndex aIdx( rDoc.GetNodes(), nSttIdx );
120  SwNodeIndex aEndIdx( rDoc.GetNodes(), pEndIdx ? *pEndIdx
121  : aIdx.GetNode().EndOfSectionIndex() );
122  SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
123  SwDoc::CorrAbs( aIdx, aEndIdx, aPos, true );
124 }
125 
126 void SwUndo::RemoveIdxFromRange( SwPaM& rPam, bool bMoveNext )
127 {
128  const SwPosition* pEnd = rPam.End();
129  if( bMoveNext )
130  {
131  if( pEnd != rPam.GetPoint() )
132  rPam.Exchange();
133 
134  SwNodeIndex aStt( rPam.GetMark()->nNode );
135  SwNodeIndex aEnd( rPam.GetPoint()->nNode );
136 
137  if( !rPam.Move( fnMoveForward ) )
138  {
139  rPam.Exchange();
140  if( !rPam.Move( fnMoveBackward ) )
141  {
142  rPam.GetPoint()->nNode = rPam.GetDoc().GetNodes().GetEndOfPostIts();
143  rPam.GetPoint()->nContent.Assign( nullptr, 0 );
144  }
145  }
146 
147  SwDoc::CorrAbs( aStt, aEnd, *rPam.GetPoint(), true );
148  }
149  else
150  SwDoc::CorrAbs( rPam, *pEnd, true );
151 }
152 
154 {
155  // Move only the Cursor. Bookmarks/TOXMarks/etc. are done by the corresponding
156  // JoinNext/JoinPrev
157  SwNodeIndex aIdx( rPos.nNode.GetNode().GetNodes(), nIdx );
158  ::PaMCorrRel( aIdx, rPos );
159 }
160 
161 SwUndo::SwUndo(SwUndoId const nId, const SwDoc* pDoc)
162  : m_nId(nId), m_nOrigRedlineFlags(RedlineFlags::NONE)
163  , m_nViewShellId(CreateViewShellId(pDoc))
164  , m_isRepeatIgnored(false)
165  , m_bCacheComment(true)
166 {
167 }
168 
170 {
171  ViewShellId nRet(-1);
172 
173  if (const SwDocShell* pDocShell = pDoc->GetDocShell())
174  {
175  if (const SwView* pView = pDocShell->GetView())
176  nRet = pView->GetViewShellId();
177  }
178 
179  return nRet;
180 }
181 
182 bool SwUndo::IsDelBox() const
183 {
186 }
187 
189 {
190 }
191 
192 namespace {
193 
194 class UndoRedoRedlineGuard
195 {
196 public:
197  UndoRedoRedlineGuard(::sw::UndoRedoContext const & rContext, SwUndo const & rUndo)
198  : m_rRedlineAccess(rContext.GetDoc().getIDocumentRedlineAccess())
199  , m_eMode(m_rRedlineAccess.GetRedlineFlags())
200  {
201  RedlineFlags const eTmpMode = rUndo.GetRedlineFlags();
202  if ((RedlineFlags::ShowMask & eTmpMode) != (RedlineFlags::ShowMask & m_eMode))
203  {
204  m_rRedlineAccess.SetRedlineFlags( eTmpMode );
205  }
206  m_rRedlineAccess.SetRedlineFlags_intern( eTmpMode | RedlineFlags::Ignore );
207  }
208  ~UndoRedoRedlineGuard()
209  {
210  m_rRedlineAccess.SetRedlineFlags(m_eMode);
211  }
212 private:
213  IDocumentRedlineAccess & m_rRedlineAccess;
214  RedlineFlags const m_eMode;
215 };
216 
217 }
218 
220 {
221  assert(false); // SwUndo::Undo(): ERROR: must call UndoWithContext instead
222 }
223 
225 {
226  assert(false); // SwUndo::Redo(): ERROR: must call RedoWithContext instead
227 }
228 
230 {
231  ::sw::UndoRedoContext *const pContext(
232  dynamic_cast< ::sw::UndoRedoContext * >(& rContext));
233  assert(pContext);
234  const UndoRedoRedlineGuard aUndoRedoRedlineGuard(*pContext, *this);
235  UndoImpl(*pContext);
236 }
237 
239 {
240  ::sw::UndoRedoContext *const pContext(
241  dynamic_cast< ::sw::UndoRedoContext * >(& rContext));
242  assert(pContext);
243  const UndoRedoRedlineGuard aUndoRedoRedlineGuard(*pContext, *this);
244  RedoImpl(*pContext);
245 }
246 
248 {
249  if (m_isRepeatIgnored)
250  {
251  return; // ignore Repeat for multi-selections
252  }
253  ::sw::RepeatContext *const pRepeatContext(
254  dynamic_cast< ::sw::RepeatContext * >(& rContext));
255  assert(pRepeatContext);
256  RepeatImpl(*pRepeatContext);
257 }
258 
259 bool SwUndo::CanRepeat(SfxRepeatTarget & rContext) const
260 {
261  assert(dynamic_cast< ::sw::RepeatContext * >(& rContext));
262  (void)rContext;
263  // a MultiSelection action that doesn't do anything must still return true
265 }
266 
268 {
269 }
270 
272 {
273  TranslateId pId;
274  switch (eId)
275  {
276  case SwUndoId::EMPTY:
277  pId = STR_CANT_UNDO;
278  break;
279  case SwUndoId::START:
280  case SwUndoId::END:
281  break;
282  case SwUndoId::DELETE:
283  pId = STR_DELETE_UNDO;
284  break;
285  case SwUndoId::INSERT:
286  pId = STR_INSERT_UNDO;
287  break;
288  case SwUndoId::OVERWRITE:
289  pId = STR_OVR_UNDO;
290  break;
291  case SwUndoId::SPLITNODE:
292  pId = STR_SPLITNODE_UNDO;
293  break;
294  case SwUndoId::INSATTR:
295  pId = STR_INSATTR_UNDO;
296  break;
298  pId = STR_SETFMTCOLL_UNDO;
299  break;
300  case SwUndoId::RESETATTR:
301  pId = STR_RESET_ATTR_UNDO;
302  break;
304  pId = STR_INSFMT_ATTR_UNDO;
305  break;
307  pId = STR_INSERT_DOC_UNDO;
308  break;
309  case SwUndoId::COPY:
310  pId = STR_COPY_UNDO;
311  break;
312  case SwUndoId::INSTABLE:
313  pId = STR_INSTABLE_UNDO;
314  break;
316  pId = STR_TABLETOTEXT_UNDO;
317  break;
319  pId = STR_TEXTTOTABLE_UNDO;
320  break;
321  case SwUndoId::SORT_TXT:
322  pId = STR_SORT_TXT;
323  break;
324  case SwUndoId::INSLAYFMT:
325  pId = STR_INSERTFLY;
326  break;
328  pId = STR_TABLEHEADLINE;
329  break;
331  pId = STR_INSERTSECTION;
332  break;
334  pId = STR_OUTLINE_LR;
335  break;
337  pId = STR_OUTLINE_UD;
338  break;
340  pId = STR_OUTLINE_EDIT;
341  break;
342  case SwUndoId::INSNUM:
343  pId = STR_INSNUM;
344  break;
345  case SwUndoId::NUMUP:
346  pId = STR_NUMUP;
347  break;
348  case SwUndoId::MOVENUM:
349  pId = STR_MOVENUM;
350  break;
352  pId = STR_INSERTDRAW;
353  break;
355  pId = STR_NUMORNONUM;
356  break;
358  pId = STR_INC_LEFTMARGIN;
359  break;
361  pId = STR_DEC_LEFTMARGIN;
362  break;
364  pId = STR_INSERTLABEL;
365  break;
367  pId = STR_SETNUMRULESTART;
368  break;
369  case SwUndoId::CHGFTN:
370  pId = STR_CHANGEFTN;
371  break;
372  case SwUndoId::REDLINE:
373  SAL_INFO("sw.core", "Should NEVER be used/translated");
374  return "$1";
376  pId = STR_ACCEPT_REDLINE;
377  break;
379  pId = STR_REJECT_REDLINE;
380  break;
382  pId = STR_SPLIT_TABLE;
383  break;
385  pId = STR_DONTEXPAND;
386  break;
388  pId = STR_AUTOCORRECT;
389  break;
391  pId = STR_MERGE_TABLE;
392  break;
394  pId = STR_TRANSLITERATE;
395  break;
397  pId = STR_PASTE_CLIPBOARD_UNDO;
398  break;
399  case SwUndoId::TYPING:
400  pId = STR_TYPING_UNDO;
401  break;
402  case SwUndoId::MOVE:
403  pId = STR_MOVE_UNDO;
404  break;
406  pId = STR_INSERT_GLOSSARY;
407  break;
409  pId = STR_DELBOOKMARK;
410  break;
412  pId = STR_INSBOOKMARK;
413  break;
414  case SwUndoId::SORT_TBL:
415  pId = STR_SORT_TBL;
416  break;
417  case SwUndoId::DELLAYFMT:
418  pId = STR_DELETEFLY;
419  break;
421  pId = STR_AUTOFORMAT;
422  break;
423  case SwUndoId::REPLACE:
424  pId = STR_REPLACE;
425  break;
427  pId = STR_DELETESECTION;
428  break;
430  pId = STR_CHANGESECTION;
431  break;
433  pId = STR_CHANGEDEFATTR;
434  break;
435  case SwUndoId::DELNUM:
436  pId = STR_DELNUM;
437  break;
438  case SwUndoId::DRAWUNDO:
439  pId = STR_DRAWUNDO;
440  break;
441  case SwUndoId::DRAWGROUP:
442  pId = STR_DRAWGROUP;
443  break;
445  pId = STR_DRAWUNGROUP;
446  break;
448  pId = STR_DRAWDELETE;
449  break;
450  case SwUndoId::REREAD:
451  pId = STR_REREAD;
452  break;
453  case SwUndoId::DELGRF:
454  pId = STR_DELGRF;
455  break;
457  pId = STR_TABLE_ATTR;
458  break;
460  pId = STR_UNDO_TABLE_AUTOFMT;
461  break;
463  pId = STR_UNDO_TABLE_INSCOL;
464  break;
466  pId = STR_UNDO_TABLE_INSROW;
467  break;
469  pId = STR_UNDO_TABLE_DELBOX;
470  break;
472  pId = STR_UNDO_TABLE_SPLIT;
473  break;
475  pId = STR_UNDO_TABLE_MERGE;
476  break;
477  case SwUndoId::TBLNUMFMT:
478  pId = STR_TABLE_NUMFORMAT;
479  break;
480  case SwUndoId::INSTOX:
481  pId = STR_INSERT_TOX;
482  break;
484  pId = STR_CLEAR_TOX_RANGE;
485  break;
486  case SwUndoId::TBLCPYTBL:
487  pId = STR_TABLE_TBLCPYTBL;
488  break;
489  case SwUndoId::CPYTBL:
490  pId = STR_TABLE_CPYTBL;
491  break;
493  pId = STR_INS_FROM_SHADOWCRSR;
494  break;
495  case SwUndoId::CHAINE:
496  pId = STR_UNDO_CHAIN;
497  break;
498  case SwUndoId::UNCHAIN:
499  pId = STR_UNDO_UNCHAIN;
500  break;
501  case SwUndoId::FTNINFO:
502  pId = STR_UNDO_FTNINFO;
503  break;
505  pId = STR_UNDO_COMPAREDOC;
506  break;
508  pId = STR_UNDO_SETFLYFRMFMT;
509  break;
511  pId = STR_UNDO_SETRUBYATTR;
512  break;
513  case SwUndoId::TOXCHANGE:
514  pId = STR_TOXCHANGE;
515  break;
517  pId = STR_UNDO_PAGEDESC_CREATE;
518  break;
520  pId = STR_UNDO_PAGEDESC;
521  break;
523  pId = STR_UNDO_PAGEDESC_DELETE;
524  break;
526  pId = STR_UNDO_HEADER_FOOTER;
527  break;
528  case SwUndoId::FIELD:
529  pId = STR_UNDO_FIELD;
530  break;
532  pId = STR_UNDO_TXTFMTCOL_CREATE;
533  break;
535  pId = STR_UNDO_TXTFMTCOL_DELETE;
536  break;
538  pId = STR_UNDO_TXTFMTCOL_RENAME;
539  break;
541  pId = STR_UNDO_CHARFMT_CREATE;
542  break;
544  pId = STR_UNDO_CHARFMT_DELETE;
545  break;
547  pId = STR_UNDO_CHARFMT_RENAME;
548  break;
550  pId = STR_UNDO_FRMFMT_CREATE;
551  break;
553  pId = STR_UNDO_FRMFMT_DELETE;
554  break;
556  pId = STR_UNDO_FRMFMT_RENAME;
557  break;
559  pId = STR_UNDO_NUMRULE_CREATE;
560  break;
562  pId = STR_UNDO_NUMRULE_DELETE;
563  break;
565  pId = STR_UNDO_NUMRULE_RENAME;
566  break;
568  pId = STR_UNDO_BOOKMARK_RENAME;
569  break;
571  pId = STR_UNDO_INDEX_ENTRY_INSERT;
572  break;
574  pId = STR_UNDO_INDEX_ENTRY_DELETE;
575  break;
577  pId = STR_UNDO_COL_DELETE;
578  break;
580  pId = STR_UNDO_ROW_DELETE;
581  break;
583  pId = STR_UNDO_PAGEDESC_RENAME;
584  break;
585  case SwUndoId::NUMDOWN:
586  pId = STR_NUMDOWN;
587  break;
589  pId = STR_UNDO_FLYFRMFMT_TITLE;
590  break;
592  pId = STR_UNDO_FLYFRMFMT_DESCRIPTION;
593  break;
595  pId = STR_UNDO_TBLSTYLE_CREATE;
596  break;
598  pId = STR_UNDO_TBLSTYLE_DELETE;
599  break;
601  pId = STR_UNDO_TBLSTYLE_UPDATE;
602  break;
604  pId = STR_REPLACE_UNDO;
605  break;
607  pId = STR_INSERT_PAGE_BREAK_UNDO;
608  break;
610  pId = STR_INSERT_COLUMN_BREAK_UNDO;
611  break;
613  pId = STR_INSERT_ENV_UNDO;
614  break;
616  pId = STR_DRAG_AND_COPY;
617  break;
619  pId = STR_DRAG_AND_MOVE;
620  break;
622  pId = STR_INSERT_CHART;
623  break;
625  pId = STR_INSERT_FOOTNOTE;
626  break;
628  pId = STR_INSERT_URLBTN;
629  break;
631  pId = STR_INSERT_URLTXT;
632  break;
634  pId = STR_DELETE_INVISIBLECNTNT;
635  break;
637  pId = STR_REPLACE_STYLE;
638  break;
640  pId = STR_DELETE_PAGE_BREAK;
641  break;
643  pId = STR_TEXT_CORRECTION;
644  break;
646  pId = STR_UNDO_TABLE_DELETE;
647  break;
648  case SwUndoId::CONFLICT:
649  break;
651  pId = STR_PARAGRAPH_SIGN_UNDO;
652  break;
654  pId = STR_UNDO_INSERT_FORM_FIELD;
655  break;
656  }
657 
658  assert(pId);
659  return SwResId(pId);
660 }
661 
662 OUString SwUndo::GetComment() const
663 {
664  OUString aResult;
665 
666  if (m_bCacheComment)
667  {
668  if (! maComment)
669  {
671 
672  SwRewriter aRewriter = GetRewriter();
673 
674  maComment = aRewriter.Apply(*maComment);
675  }
676 
677  aResult = *maComment;
678  }
679  else
680  {
681  aResult = GetUndoComment(GetId());
682 
683  SwRewriter aRewriter = GetRewriter();
684 
685  aResult = aRewriter.Apply(aResult);
686  }
687 
688  return aResult;
689 }
690 
692 {
693  return m_nViewShellId;
694 }
695 
697 {
698  SwRewriter aResult;
699 
700  return aResult;
701 }
702 
704 {}
705 
706 SwUndoSaveContent::~SwUndoSaveContent() COVERITY_NOEXCEPT_FALSE
707 {
708 }
709 
711 {
712  (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwUndoSaveContent"));
713  (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
714 
715  if (m_pHistory)
716  {
717  m_pHistory->dumpAsXml(pWriter);
718  }
719 
720  (void)xmlTextWriterEndElement(pWriter);
721 }
722 
723 // This is needed when deleting content. For REDO all contents will be moved
724 // into the UndoNodesArray. These methods always create a new node to insert
725 // content. As a result, the attributes will not be expanded.
726 // - MoveTo moves from NodesArray into UndoNodesArray
727 // - MoveFrom moves from UndoNodesArray into NodesArray
728 
729 // If pEndNdIdx is given, Undo/Redo calls -Ins/DelFly. In that case the whole
730 // section should be moved.
732  SwNodeOffset* pEndNdIdx )
733 {
734  SwDoc& rDoc = rPaM.GetDoc();
735  ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
736 
737  SwNoTextNode* pCpyNd = rPaM.GetNode().GetNoTextNode();
738 
739  // here comes the actual delete (move)
740  SwNodes & rNds = rDoc.GetUndoManager().GetUndoNodes();
741  SwPosition aPos( pEndNdIdx ? rNds.GetEndOfPostIts()
742  : rNds.GetEndOfExtras() );
743 
744  const SwPosition* pStt = rPaM.Start(), *pEnd = rPaM.End();
745 
746  SwNodeOffset nTmpMvNode = aPos.nNode.GetIndex();
747 
748  if( pCpyNd || pEndNdIdx )
749  {
750  SwNodeRange aRg( pStt->nNode, SwNodeOffset(0), pEnd->nNode, SwNodeOffset(1) );
751  rDoc.GetNodes().MoveNodes( aRg, rNds, aPos.nNode, true );
752  aPos.nContent = 0;
753  --aPos.nNode;
754  }
755  else
756  {
757  rDoc.GetNodes().MoveRange( rPaM, aPos, rNds );
758  }
759  if( pEndNdIdx )
760  *pEndNdIdx = aPos.nNode.GetIndex();
761 
762  // old position
763  aPos.nNode = nTmpMvNode;
764  if( pNodeIdx )
765  *pNodeIdx = aPos.nNode;
766 }
767 
769  SwPosition& rInsPos,
770  const SwNodeOffset* pEndNdIdx, bool const bForceCreateFrames)
771 {
772  // here comes the recovery
773  SwNodes & rNds = rDoc.GetUndoManager().GetUndoNodes();
774  if( nNodeIdx == rNds.GetEndOfPostIts().GetIndex() )
775  return; // nothing saved
776 
777  ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
778 
779  SwPaM aPaM( rInsPos );
780  if( pEndNdIdx ) // than get the section from it
781  aPaM.GetPoint()->nNode.Assign( rNds, *pEndNdIdx );
782  else
783  {
784  aPaM.GetPoint()->nNode = rNds.GetEndOfExtras();
785  GoInContent( aPaM, fnMoveBackward );
786  }
787 
788  SwTextNode* pTextNd = aPaM.GetNode().GetTextNode();
789  if (!pEndNdIdx && pTextNd)
790  {
791  aPaM.SetMark();
792  aPaM.GetPoint()->nNode = nNodeIdx;
793  aPaM.GetPoint()->nContent.Assign(aPaM.GetContentNode(), 0);
794 
795  SaveRedlEndPosForRestore aRedlRest( rInsPos.nNode, rInsPos.nContent.GetIndex() );
796 
797  rNds.MoveRange( aPaM, rInsPos, rDoc.GetNodes() );
798 
799  // delete the last Node as well
800  if( !aPaM.GetPoint()->nContent.GetIndex() ||
801  ( aPaM.GetPoint()->nNode++ && // still empty Nodes at the end?
802  &rNds.GetEndOfExtras() != &aPaM.GetPoint()->nNode.GetNode() ))
803  {
804  aPaM.GetPoint()->nContent.Assign( nullptr, 0 );
805  aPaM.SetMark();
806  rNds.Delete( aPaM.GetPoint()->nNode,
807  rNds.GetEndOfExtras().GetIndex() -
808  aPaM.GetPoint()->nNode.GetIndex() );
809  }
810 
811  aRedlRest.Restore();
812  }
813  else
814  {
815  SwNodeRange aRg( rNds, nNodeIdx, rNds, (pEndNdIdx
816  ? ((*pEndNdIdx) + 1)
817  : rNds.GetEndOfExtras().GetIndex() ) );
818  rNds.MoveNodes(aRg, rDoc.GetNodes(), rInsPos.nNode, nullptr == pEndNdIdx || bForceCreateFrames);
819 
820  }
821 }
822 
823 // These two methods move the Point of Pam backwards/forwards. With that, one
824 // can span an area for a Undo/Redo. (The Point is then positioned in front of
825 // the area to manipulate!)
826 // The flag indicates if there is still content in front of Point.
828 {
829  rPam.SetMark();
830  if( rPam.Move( fnMoveBackward ))
831  return true;
832 
833  // If there is no content onwards, set Point simply to the previous position
834  // (Node and Content, so that Content will be detached!)
835  --rPam.GetPoint()->nNode;
836  rPam.GetPoint()->nContent.Assign( nullptr, 0 );
837  return false;
838 }
839 
840 void SwUndoSaveContent::MovePtForward( SwPaM& rPam, bool bMvBkwrd )
841 {
842  // Was there content before this position?
843  if( bMvBkwrd )
844  rPam.Move( fnMoveForward );
845  else
846  {
847  ++rPam.GetPoint()->nNode;
848  SwContentNode* pCNd = rPam.GetContentNode();
849  if( pCNd )
850  pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
851  else
852  rPam.Move( fnMoveForward );
853  }
854 }
855 
856 // Delete all objects that have ContentIndices to the given area.
857 // Currently (1994) these exist:
858 // - Footnotes
859 // - Flys
860 // - Bookmarks
861 
862 // #i81002# - extending method
863 // delete certain (not all) cross-reference bookmarks at text node of <rMark>
864 // and at text node of <rPoint>, if these text nodes aren't the same.
866  const SwPosition& rPoint,
867  DelContentType nDelContentType )
868 {
869  const SwPosition *pStt = rMark < rPoint ? &rMark : &rPoint,
870  *pEnd = &rMark == pStt ? &rPoint : &rMark;
871 
872  SwDoc& rDoc = rMark.nNode.GetNode().GetDoc();
873 
874  // if it's not in the doc array, probably missing some invalidation somewhere
875  assert(&rPoint.nNode.GetNodes() == &rDoc.GetNodes());
876  assert(&rMark.nNode.GetNodes() == &rDoc.GetNodes());
877 
878  ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
879 
880  // 1. Footnotes
881  if( DelContentType::Ftn & nDelContentType )
882  {
883  SwFootnoteIdxs& rFootnoteArr = rDoc.GetFootnoteIdxs();
884  if( !rFootnoteArr.empty() )
885  {
886  const SwNode* pFootnoteNd;
887  size_t nPos = 0;
888  rFootnoteArr.SeekEntry( pStt->nNode, &nPos );
889  SwTextFootnote* pSrch;
890 
891  // for now delete all that come afterwards
892  while( nPos < rFootnoteArr.size() && ( pFootnoteNd =
893  &( pSrch = rFootnoteArr[ nPos ] )->GetTextNode())->GetIndex()
894  <= pEnd->nNode.GetIndex() )
895  {
896  const sal_Int32 nFootnoteSttIdx = pSrch->GetStart();
897  if( (DelContentType::CheckNoCntnt & nDelContentType )
898  ? (&pEnd->nNode.GetNode() == pFootnoteNd )
899  : (( &pStt->nNode.GetNode() == pFootnoteNd &&
900  pStt->nContent.GetIndex() > nFootnoteSttIdx) ||
901  ( &pEnd->nNode.GetNode() == pFootnoteNd &&
902  nFootnoteSttIdx >= pEnd->nContent.GetIndex() )) )
903  {
904  ++nPos; // continue searching
905  continue;
906  }
907 
908 // FIXME: duplicated code here and below -> refactor?
909  // Unfortunately an index needs to be created. Otherwise there
910  // will be problems with TextNode because the index will be
911  // deleted in the DTOR of SwFootnote!
912  SwTextNode* pTextNd = const_cast<SwTextNode*>(static_cast<const SwTextNode*>(pFootnoteNd));
913  if( !m_pHistory )
914  m_pHistory.reset( new SwHistory );
915  SwTextAttr* const pFootnoteHint =
916  pTextNd->GetTextAttrForCharAt( nFootnoteSttIdx );
917  assert(pFootnoteHint);
918  SwIndex aIdx( pTextNd, nFootnoteSttIdx );
919  m_pHistory->Add( pFootnoteHint, pTextNd->GetIndex(), false );
920  pTextNd->EraseText( aIdx, 1 );
921  }
922 
923  while( nPos-- && ( pFootnoteNd = &( pSrch = rFootnoteArr[ nPos ] )->
924  GetTextNode())->GetIndex() >= pStt->nNode.GetIndex() )
925  {
926  const sal_Int32 nFootnoteSttIdx = pSrch->GetStart();
927  if( !(DelContentType::CheckNoCntnt & nDelContentType) && (
928  ( &pStt->nNode.GetNode() == pFootnoteNd &&
929  pStt->nContent.GetIndex() > nFootnoteSttIdx ) ||
930  ( &pEnd->nNode.GetNode() == pFootnoteNd &&
931  nFootnoteSttIdx >= pEnd->nContent.GetIndex() )))
932  continue; // continue searching
933 
934  // Unfortunately an index needs to be created. Otherwise there
935  // will be problems with TextNode because the index will be
936  // deleted in the DTOR of SwFootnote!
937  SwTextNode* pTextNd = const_cast<SwTextNode*>(static_cast<const SwTextNode*>(pFootnoteNd));
938  if( !m_pHistory )
939  m_pHistory.reset( new SwHistory );
940  SwTextAttr* const pFootnoteHint =
941  pTextNd->GetTextAttrForCharAt( nFootnoteSttIdx );
942  assert(pFootnoteHint);
943  SwIndex aIdx( pTextNd, nFootnoteSttIdx );
944  m_pHistory->Add( pFootnoteHint, pTextNd->GetIndex(), false );
945  pTextNd->EraseText( aIdx, 1 );
946  }
947  }
948  }
949 
950  // 2. Flys
951  if( DelContentType::Fly & nDelContentType )
952  {
953  sal_uInt16 nChainInsPos = m_pHistory ? m_pHistory->Count() : 0;
954  const SwFrameFormats& rSpzArr = *rDoc.GetSpzFrameFormats();
955  if( !rSpzArr.empty() )
956  {
957  SwFrameFormat* pFormat;
958  const SwFormatAnchor* pAnchor;
959  size_t n = rSpzArr.size();
960  const SwPosition* pAPos;
961 
962  while( n && !rSpzArr.empty() )
963  {
964  pFormat = rSpzArr[--n];
965  pAnchor = &pFormat->GetAnchor();
966  switch( pAnchor->GetAnchorId() )
967  {
968  case RndStdIds::FLY_AS_CHAR:
969  if( nullptr != (pAPos = pAnchor->GetContentAnchor() ) &&
970  (( DelContentType::CheckNoCntnt & nDelContentType )
971  ? ( pStt->nNode <= pAPos->nNode &&
972  pAPos->nNode < pEnd->nNode )
973  : ( *pStt <= *pAPos && *pAPos < *pEnd )) )
974  {
975  if( !m_pHistory )
976  m_pHistory.reset( new SwHistory );
977  SwTextNode *const pTextNd =
978  pAPos->nNode.GetNode().GetTextNode();
979  SwTextAttr* const pFlyHint = pTextNd->GetTextAttrForCharAt(
980  pAPos->nContent.GetIndex());
981  assert(pFlyHint);
982  m_pHistory->Add( pFlyHint, SwNodeOffset(0), false );
983  // reset n so that no Format is skipped
984  n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
985  }
986  break;
987  case RndStdIds::FLY_AT_PARA:
988  {
989  pAPos = pAnchor->GetContentAnchor();
990  if (pAPos &&
991  pStt->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode)
992  {
993  if (!m_pHistory)
994  m_pHistory.reset( new SwHistory );
995 
996  if (!(DelContentType::Replace & nDelContentType)
997  && IsSelectFrameAnchoredAtPara(*pAPos, *pStt, *pEnd, nDelContentType))
998  {
999  m_pHistory->AddDeleteFly(*pFormat, nChainInsPos);
1000  // reset n so that no Format is skipped
1001  n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
1002  }
1003  // Moving the anchor?
1005  & nDelContentType) &&
1006  // at least for calls from SwUndoDelete,
1007  // this should work - other Undos don't
1008  // remember the order of the cursor
1009  (rPoint.nNode.GetIndex() == pAPos->nNode.GetIndex())
1010  // Do not try to move the anchor to a table!
1011  && rMark.nNode.GetNode().IsTextNode())
1012  {
1013  m_pHistory->AddChangeFlyAnchor(*pFormat);
1014  SwFormatAnchor aAnch( *pAnchor );
1015  SwPosition aPos( rMark.nNode );
1016  aAnch.SetAnchor( &aPos );
1017  pFormat->SetFormatAttr( aAnch );
1018  }
1019  }
1020  }
1021  break;
1022  case RndStdIds::FLY_AT_CHAR:
1023  if( nullptr != (pAPos = pAnchor->GetContentAnchor() ) &&
1024  ( pStt->nNode <= pAPos->nNode && pAPos->nNode <= pEnd->nNode ) )
1025  {
1026  if( !m_pHistory )
1027  m_pHistory.reset( new SwHistory );
1028  if (!(DelContentType::Replace & nDelContentType)
1030  *pAPos, *pStt, *pEnd, nDelContentType))
1031  {
1032  m_pHistory->AddDeleteFly(*pFormat, nChainInsPos);
1033  n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
1034  }
1035  else if (!((DelContentType::CheckNoCntnt |
1037  & nDelContentType))
1038  {
1039  if( *pStt <= *pAPos && *pAPos < *pEnd )
1040  {
1041  // These are the objects anchored
1042  // between section start and end position
1043  // Do not try to move the anchor to a table!
1044  if( rMark.nNode.GetNode().GetTextNode() )
1045  {
1046  m_pHistory->AddChangeFlyAnchor(*pFormat);
1047  SwFormatAnchor aAnch( *pAnchor );
1048  aAnch.SetAnchor( &rMark );
1049  pFormat->SetFormatAttr( aAnch );
1050  }
1051  }
1052  }
1053  }
1054  break;
1055  case RndStdIds::FLY_AT_FLY:
1056 
1057  if( nullptr != (pAPos = pAnchor->GetContentAnchor() ) &&
1058  pStt->nNode == pAPos->nNode )
1059  {
1060  if( !m_pHistory )
1061  m_pHistory.reset( new SwHistory );
1062 
1063  m_pHistory->AddDeleteFly(*pFormat, nChainInsPos);
1064 
1065  // reset n so that no Format is skipped
1066  n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
1067  }
1068  break;
1069  default: break;
1070  }
1071  }
1072  }
1073  }
1074 
1075  // 3. Bookmarks
1076  if( !(DelContentType::Bkm & nDelContentType) )
1077  return;
1078 
1079  IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
1080  if( !pMarkAccess->getAllMarksCount() )
1081  return;
1082 
1083  for( sal_Int32 n = 0; n < pMarkAccess->getAllMarksCount(); ++n )
1084  {
1085  // #i81002#
1086  bool bSavePos = false;
1087  bool bSaveOtherPos = false;
1088  const ::sw::mark::IMark *const pBkmk = pMarkAccess->getAllMarksBegin()[n];
1089  auto const type(IDocumentMarkAccess::GetType(*pBkmk));
1090 
1091  if( DelContentType::CheckNoCntnt & nDelContentType )
1092  {
1093  if ( pStt->nNode <= pBkmk->GetMarkPos().nNode
1094  && pBkmk->GetMarkPos().nNode < pEnd->nNode )
1095  {
1096  bSavePos = true;
1097  }
1098  if ( pBkmk->IsExpanded()
1099  && pStt->nNode <= pBkmk->GetOtherMarkPos().nNode
1100  && pBkmk->GetOtherMarkPos().nNode < pEnd->nNode )
1101  {
1102  bSaveOtherPos = true;
1103  }
1104  }
1105  else
1106  {
1107  // #i92125#
1108  // keep cross-reference bookmarks, if content inside one paragraph is deleted.
1109  if ( rMark.nNode == rPoint.nNode
1112  {
1113  continue;
1114  }
1115 
1116  bool bMaybe = false;
1117  if ( *pStt <= pBkmk->GetMarkPos() && pBkmk->GetMarkPos() <= *pEnd )
1118  {
1119  if ( pBkmk->GetMarkPos() == *pEnd
1120  || ( *pStt == pBkmk->GetMarkPos() && pBkmk->IsExpanded() ) )
1121  bMaybe = true;
1122  else
1123  bSavePos = true;
1124  }
1125  if( pBkmk->IsExpanded() &&
1126  *pStt <= pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() <= *pEnd )
1127  {
1128  assert(!bSaveOtherPos);
1129  if ( bSavePos
1130  || (*pStt < pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() < *pEnd)
1131  || (bMaybe
1136  {
1137  if( bMaybe )
1138  bSavePos = true;
1139  bSaveOtherPos = true;
1140  }
1141  }
1142 
1143  if ( !bSavePos && !bSaveOtherPos
1144  && dynamic_cast< const ::sw::mark::CrossRefBookmark* >(pBkmk) )
1145  {
1146  // certain special handling for cross-reference bookmarks
1147  const bool bDifferentTextNodesAtMarkAndPoint =
1148  rMark.nNode != rPoint.nNode
1149  && rMark.nNode.GetNode().GetTextNode()
1150  && rPoint.nNode.GetNode().GetTextNode();
1151  if ( bDifferentTextNodesAtMarkAndPoint )
1152  {
1153  // delete cross-reference bookmark at <pStt>, if only part of
1154  // <pEnd> text node content is deleted.
1155  if( pStt->nNode == pBkmk->GetMarkPos().nNode
1156  && pEnd->nContent.GetIndex() != pEnd->nNode.GetNode().GetTextNode()->Len() )
1157  {
1158  bSavePos = true;
1159  bSaveOtherPos = false; // cross-reference bookmarks are not expanded
1160  }
1161  // delete cross-reference bookmark at <pEnd>, if only part of
1162  // <pStt> text node content is deleted.
1163  else if( pEnd->nNode == pBkmk->GetMarkPos().nNode &&
1164  pStt->nContent.GetIndex() != 0 )
1165  {
1166  bSavePos = true;
1167  bSaveOtherPos = false; // cross-reference bookmarks are not expanded
1168  }
1169  }
1170  }
1172  {
1173  // delete annotation marks, if its end position is covered by the deletion
1174  const SwPosition& rAnnotationEndPos = pBkmk->GetMarkEnd();
1175  if ( *pStt < rAnnotationEndPos && rAnnotationEndPos <= *pEnd )
1176  {
1177  bSavePos = true;
1178  bSaveOtherPos = pBkmk->IsExpanded(); //tdf#90138, only save the other pos if there is one
1179  }
1180  }
1181  }
1182 
1183  if ( bSavePos || bSaveOtherPos )
1184  {
1186  {
1187  if( !m_pHistory )
1188  m_pHistory.reset( new SwHistory );
1189  m_pHistory->Add( *pBkmk, bSavePos, bSaveOtherPos );
1190  }
1191  if ( bSavePos
1192  && ( bSaveOtherPos
1193  || !pBkmk->IsExpanded() ) )
1194  {
1195  pMarkAccess->deleteMark(pMarkAccess->getAllMarksBegin()+n);
1196  n--;
1197  }
1198  }
1199  }
1200 }
1201 
1202 // save a complete section into UndoNodes array
1204  : m_nMoveLen( 0 ), m_nStartPos( NODE_OFFSET_MAX )
1205 {
1206 }
1207 
1209 {
1210  if (m_pMovedStart) // delete also the section from UndoNodes array
1211  {
1212  // SaveSection saves the content in the PostIt section.
1213  SwNodes& rUNds = m_pMovedStart->GetNode().GetNodes();
1214  // cid#1486004 Uncaught exception
1216 
1217  m_pMovedStart.reset();
1218  }
1219  m_pRedlineSaveData.reset();
1220 }
1221 
1223 {
1224  SwNodeRange aRg( rSttIdx.GetNode(), *rSttIdx.GetNode().EndOfSectionNode() );
1225  SaveSection( aRg );
1226 }
1227 
1229  const SwNodeRange& rRange, bool const bExpandNodes)
1230 {
1231  SwPaM aPam( rRange.aStart, rRange.aEnd );
1232 
1233  // delete all footnotes, fly frames, bookmarks
1234  DelContentIndex( *aPam.GetMark(), *aPam.GetPoint() );
1235 
1236  // redlines *before* CorrAbs, because DelBookmarks will make them 0-length
1237  // but *after* DelContentIndex because that also may use FillSaveData (in
1238  // flys) and that will be restored *after* this one...
1241  {
1242  m_pRedlineSaveData.reset();
1243  }
1244 
1245  {
1246  // move certain indexes out of deleted range
1247  SwNodeIndex aSttIdx( aPam.Start()->nNode.GetNode() );
1248  SwNodeIndex aEndIdx( aPam.End()->nNode.GetNode() );
1249  SwNodeIndex aMvStt( aEndIdx, 1 );
1250  SwDoc::CorrAbs( aSttIdx, aEndIdx, SwPosition( aMvStt ), true );
1251  }
1252 
1253  m_nStartPos = rRange.aStart.GetIndex();
1254 
1255  if (bExpandNodes)
1256  {
1257  --aPam.GetPoint()->nNode;
1258  ++aPam.GetMark()->nNode;
1259  }
1260 
1261  SwContentNode* pCNd = aPam.GetContentNode( false );
1262  if( pCNd )
1263  aPam.GetMark()->nContent.Assign( pCNd, 0 );
1264  pCNd = aPam.GetContentNode();
1265  if( nullptr != pCNd )
1266  aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
1267 
1268  // Keep positions as SwIndex so that this section can be deleted in DTOR
1269  SwNodeOffset nEnd;
1270  m_pMovedStart.reset(new SwNodeIndex(rRange.aStart));
1271  MoveToUndoNds(aPam, m_pMovedStart.get(), &nEnd);
1272  m_nMoveLen = nEnd - m_pMovedStart->GetIndex() + 1;
1273 }
1274 
1276  sal_uInt16 nSectType )
1277 {
1278  if( NODE_OFFSET_MAX == m_nStartPos ) // was there any content?
1279  return;
1280 
1281  // check if the content is at the old position
1282  SwNodeIndex aSttIdx( pDoc->GetNodes(), m_nStartPos );
1283 
1284  // move the content from UndoNodes array into Fly
1285  SwStartNode* pSttNd = SwNodes::MakeEmptySection( aSttIdx,
1286  static_cast<SwStartNodeType>(nSectType) );
1287 
1288  RestoreSection( pDoc, SwNodeIndex( *pSttNd->EndOfSectionNode() ));
1289 
1290  if( pIdx )
1291  *pIdx = *pSttNd;
1292 }
1293 
1295  SwDoc *const pDoc, const SwNodeIndex& rInsPos, bool bForceCreateFrames)
1296 {
1297  if( NODE_OFFSET_MAX == m_nStartPos ) // was there any content?
1298  return;
1299 
1300  SwPosition aInsPos( rInsPos );
1301  SwNodeOffset nEnd = m_pMovedStart->GetIndex() + m_nMoveLen - 1;
1302  MoveFromUndoNds(*pDoc, m_pMovedStart->GetIndex(), aInsPos, &nEnd, bForceCreateFrames);
1303 
1304  // destroy indices again, content was deleted from UndoNodes array
1305  m_pMovedStart.reset();
1306  m_nMoveLen = SwNodeOffset(0);
1307 
1308  if( m_pRedlineSaveData )
1309  {
1311  m_pRedlineSaveData.reset();
1312  }
1313 }
1314 
1316 {
1318 }
1319 
1320 // save and set the RedlineData
1322  SwComparePosition eCmpPos,
1323  const SwPosition& rSttPos,
1324  const SwPosition& rEndPos,
1325  SwRangeRedline& rRedl,
1326  bool bCopyNext )
1327  : SwUndRng( rRedl )
1328  , SwRedlineData( rRedl.GetRedlineData(), bCopyNext )
1329 {
1330  assert( SwComparePosition::Outside == eCmpPos ||
1331  !rRedl.GetContentIdx() ); // "Redline with Content"
1332 
1333  switch (eCmpPos)
1334  {
1335  case SwComparePosition::OverlapBefore: // Pos1 overlaps Pos2 at the beginning
1336  m_nEndNode = rEndPos.nNode.GetIndex();
1337  m_nEndContent = rEndPos.nContent.GetIndex();
1338  break;
1339 
1340  case SwComparePosition::OverlapBehind: // Pos1 overlaps Pos2 at the end
1341  m_nSttNode = rSttPos.nNode.GetIndex();
1342  m_nSttContent = rSttPos.nContent.GetIndex();
1343  break;
1344 
1345  case SwComparePosition::Inside: // Pos1 lays completely in Pos2
1346  m_nSttNode = rSttPos.nNode.GetIndex();
1347  m_nSttContent = rSttPos.nContent.GetIndex();
1348  m_nEndNode = rEndPos.nNode.GetIndex();
1349  m_nEndContent = rEndPos.nContent.GetIndex();
1350  break;
1351 
1352  case SwComparePosition::Outside: // Pos2 lays completely in Pos1
1353  if ( rRedl.GetContentIdx() )
1354  {
1355  // than move section into UndoArray and memorize it
1356  SaveSection( *rRedl.GetContentIdx() );
1357  rRedl.SetContentIdx( nullptr );
1358  }
1359  break;
1360 
1361  case SwComparePosition::Equal: // Pos1 is exactly as big as Pos2
1362  break;
1363 
1364  default:
1365  assert(false);
1366  }
1367 
1368 #if OSL_DEBUG_LEVEL > 0
1370  m_bRedlineMoved = rRedl.IsMoved();
1371 #endif
1372 }
1373 
1375 {
1376 }
1377 
1379 {
1380  SwDoc& rDoc = rPam.GetDoc();
1381  SwRangeRedline* pRedl = new SwRangeRedline( *this, rPam );
1382 
1383  if( GetMvSttIdx() )
1384  {
1385  SwNodeIndex aIdx( rDoc.GetNodes() );
1386  RestoreSection( &rDoc, &aIdx, SwNormalStartNode );
1387  if( GetHistory() )
1388  GetHistory()->Rollback( &rDoc );
1389  pRedl->SetContentIdx( &aIdx );
1390  }
1391  SetPaM( *pRedl );
1392  // First, delete the "old" so that in an Append no unexpected things will
1393  // happen, e.g. a delete in an insert. In the latter case the just restored
1394  // content will be deleted and not the one you originally wanted.
1395  rDoc.getIDocumentRedlineAccess().DeleteRedline( *pRedl, false, RedlineType::Any );
1396 
1399  //#i92154# let UI know about a new redline with comment
1400  if (rDoc.GetDocShell() && (!pRedl->GetComment().isEmpty()) )
1401  rDoc.GetDocShell()->Broadcast(SwRedlineHint());
1402 
1403  auto const result(rDoc.getIDocumentRedlineAccess().AppendRedline(pRedl, true));
1404  assert(result != IDocumentRedlineAccess::AppendResult::IGNORED); // SwRedlineSaveData::RedlineToDoc: insert redline failed
1405  (void) result; // unused in non-debug
1407 }
1408 
1410  const SwPaM& rRange,
1411  SwRedlineSaveDatas& rSData,
1412  bool bDelRange,
1413  bool bCopyNext )
1414 {
1415  rSData.clear();
1416 
1417  const SwPosition* pStt = rRange.Start();
1418  const SwPosition* pEnd = rRange.End();
1419  const SwRedlineTable& rTable = rRange.GetDoc().getIDocumentRedlineAccess().GetRedlineTable();
1421  rRange.GetDoc().getIDocumentRedlineAccess().GetRedline( *pStt, &n );
1422  for ( ; n < rTable.size(); ++n )
1423  {
1424  SwRangeRedline* pRedl = rTable[n];
1425 
1426  const SwComparePosition eCmpPos =
1427  ComparePosition( *pStt, *pEnd, *pRedl->Start(), *pRedl->End() );
1428  if ( eCmpPos != SwComparePosition::Before
1429  && eCmpPos != SwComparePosition::Behind
1430  && eCmpPos != SwComparePosition::CollideEnd
1431  && eCmpPos != SwComparePosition::CollideStart )
1432  {
1433 
1434  rSData.push_back(std::unique_ptr<SwRedlineSaveData>(new SwRedlineSaveData(eCmpPos, *pStt, *pEnd, *pRedl, bCopyNext)));
1435  }
1436  }
1437  if( !rSData.empty() && bDelRange )
1438  {
1439  rRange.GetDoc().getIDocumentRedlineAccess().DeleteRedline( rRange, false, RedlineType::Any );
1440  }
1441  return !rSData.empty();
1442 }
1443 
1445  const SwPaM& rRange,
1446  SwRedlineSaveDatas& rSData )
1447 {
1448  rSData.clear();
1449 
1450  const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
1451  const SwRedlineTable& rTable = rRange.GetDoc().getIDocumentRedlineAccess().GetRedlineTable();
1453  rRange.GetDoc().getIDocumentRedlineAccess().GetRedline( *pStt, &n );
1454  for ( ; n < rTable.size(); ++n )
1455  {
1456  SwRangeRedline* pRedl = rTable[n];
1457  if ( RedlineType::Format == pRedl->GetType() )
1458  {
1459  const SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRedl->Start(), *pRedl->End() );
1460  if ( eCmpPos != SwComparePosition::Before
1461  && eCmpPos != SwComparePosition::Behind
1462  && eCmpPos != SwComparePosition::CollideEnd
1463  && eCmpPos != SwComparePosition::CollideStart )
1464  {
1465  rSData.push_back(std::unique_ptr<SwRedlineSaveData>(new SwRedlineSaveData(eCmpPos, *pStt, *pEnd, *pRedl, true)));
1466  }
1467 
1468  }
1469  }
1470  return !rSData.empty();
1471 }
1472 
1473 
1475 {
1478  SwPaM aPam( rDoc.GetNodes().GetEndOfContent() );
1479 
1480  for( size_t n = rSData.size(); n; )
1481  rSData[ --n ].RedlineToDoc( aPam );
1482 
1483 #if OSL_DEBUG_LEVEL > 0
1484  // check redline count against count saved in RedlineSaveData object
1485  // except in the case of moved redlines
1486  assert(rSData.empty() || rSData[0].m_bRedlineMoved ||
1487  (rSData[0].m_nRedlineCount == rDoc.getIDocumentRedlineAccess().GetRedlineTable().size()));
1488  // "redline count not restored properly"
1489 #endif
1490 
1492 }
1493 
1495 {
1496  for( size_t n = rSData.size(); n; )
1497  if( rSData[ --n ].GetMvSttIdx() )
1498  return true;
1499  return false;
1500 }
1501 
1503  const SwRedlineSaveDatas& rCheck, bool bCurrIsEnd )
1504 {
1505  if( rCurr.size() != rCheck.size() )
1506  return false;
1507 
1508  for( size_t n = 0; n < rCurr.size(); ++n )
1509  {
1510  const SwRedlineSaveData& rSet = rCurr[ n ];
1511  const SwRedlineSaveData& rGet = rCheck[ n ];
1512  if( rSet.m_nSttNode != rGet.m_nSttNode ||
1513  rSet.GetMvSttIdx() || rGet.GetMvSttIdx() ||
1514  ( bCurrIsEnd ? rSet.m_nSttContent != rGet.m_nEndContent
1515  : rSet.m_nEndContent != rGet.m_nSttContent ) ||
1516  !rGet.CanCombine( rSet ) )
1517  {
1518  return false;
1519  }
1520  }
1521 
1522  for( size_t n = 0; n < rCurr.size(); ++n )
1523  {
1524  SwRedlineSaveData& rSet = rCurr[ n ];
1525  const SwRedlineSaveData& rGet = rCheck[ n ];
1526  if( bCurrIsEnd )
1527  rSet.m_nSttContent = rGet.m_nSttContent;
1528  else
1529  rSet.m_nEndContent = rGet.m_nEndContent;
1530  }
1531  return true;
1532 }
1533 
1534 OUString ShortenString(const OUString & rStr, sal_Int32 nLength, const OUString & rFillStr)
1535 {
1536  assert(nLength - rFillStr.getLength() >= 2);
1537 
1538  if (rStr.getLength() <= nLength)
1539  return rStr;
1540 
1541  nLength -= rFillStr.getLength();
1542  if ( nLength < 2 )
1543  nLength = 2;
1544 
1545  const sal_Int32 nFrontLen = nLength - nLength / 2;
1546  const sal_Int32 nBackLen = nLength - nFrontLen;
1547 
1548  return rStr.subView(0, nFrontLen)
1549  + rFillStr
1550  + rStr.subView(rStr.getLength() - nBackLen);
1551 }
1552 
1553 static bool IsAtEndOfSection(SwPosition const& rAnchorPos)
1554 {
1555  SwNodeIndex node(*rAnchorPos.nNode.GetNode().EndOfSectionNode());
1556  SwContentNode *const pNode(SwNodes::GoPrevious(&node));
1557  assert(pNode);
1558  assert(rAnchorPos.nNode <= node); // last valid anchor pos is last content
1559  return node == rAnchorPos.nNode
1560  // at-para fly has no SwIndex!
1561  && (rAnchorPos.nContent == pNode->Len() || rAnchorPos.nContent.GetIdxReg() == nullptr);
1562 }
1563 
1564 static bool IsAtStartOfSection(SwPosition const& rAnchorPos)
1565 {
1566  SwNodes const& rNodes(rAnchorPos.nNode.GetNodes());
1567  SwNodeIndex node(*rAnchorPos.nNode.GetNode().StartOfSectionNode());
1568  SwContentNode *const pNode(rNodes.GoNext(&node));
1569  assert(pNode);
1570  (void) pNode;
1571  assert(node <= rAnchorPos.nNode);
1572  return node == rAnchorPos.nNode && rAnchorPos.nContent == 0;
1573 }
1574 
1576 static bool IsAtEndOfSection2(SwPosition const& rPos)
1577 {
1578  return rPos.nNode.GetNode().IsEndNode()
1579  || IsAtEndOfSection(rPos);
1580 }
1581 
1582 static bool IsAtStartOfSection2(SwPosition const& rPos)
1583 {
1584  return rPos.nNode.GetNode().IsStartNode()
1585  || IsAtStartOfSection(rPos);
1586 }
1587 
1589  SwPosition const& rStart, SwPosition const& rEnd)
1590 {
1591  // check if the selection is backspace/delete created by DelLeft/DelRight
1592  if (rStart.nNode.GetIndex() + 1 != rEnd.nNode.GetIndex())
1593  return true;
1594  if (rEnd.nContent != 0)
1595  return true;
1596  const SwTextNode* pTextNode = rStart.nNode.GetNode().GetTextNode();
1597  if (!pTextNode || rStart.nContent != pTextNode->Len())
1598  return true;
1599  return false;
1600 }
1601 
1603  SwPosition const & rStart, SwPosition const & rEnd,
1604  DelContentType const nDelContentType)
1605 {
1606  assert(rStart <= rEnd);
1607 
1608  // CheckNoCntnt means DelFullPara which is obvious to handle
1609  if (DelContentType::CheckNoCntnt & nDelContentType)
1610  { // exclude selection end node because it won't be deleted
1611  return (rAnchorPos.nNode < rEnd.nNode)
1612  && (rStart.nNode <= rAnchorPos.nNode);
1613  }
1614 
1615  if ((nDelContentType & DelContentType::WriterfilterHack)
1616  && rAnchorPos.GetDoc().IsInWriterfilterImport())
1617  { // FIXME hack for writerfilter RemoveLastParagraph() and MakeFlyAndMove(); can't test file format more specific?
1618  return (rStart < rAnchorPos) && (rAnchorPos < rEnd);
1619  }
1620 
1621  if (nDelContentType & DelContentType::ExcludeFlyAtStartEnd)
1622  { // exclude selection start and end node
1623  return (rAnchorPos.nNode < rEnd.nNode)
1624  && (rStart.nNode < rAnchorPos.nNode);
1625  }
1626 
1627  // in general, exclude the start and end position
1628  return ((rStart < rAnchorPos)
1629  || (rStart == rAnchorPos
1630  // special case: fully deleted node
1631  && ((rStart.nNode != rEnd.nNode && rStart.nContent == 0
1632  // but not if the selection is backspace/delete!
1633  && IsNotBackspaceHeuristic(rStart, rEnd))
1634  || (IsAtStartOfSection(rAnchorPos) && IsAtEndOfSection2(rEnd)))))
1635  && ((rAnchorPos < rEnd)
1636  || (rAnchorPos == rEnd
1637  // special case: fully deleted node
1638  && ((rEnd.nNode != rStart.nNode && rEnd.nContent == rEnd.nNode.GetNode().GetTextNode()->Len()
1639  && IsNotBackspaceHeuristic(rStart, rEnd))
1640  || (IsAtEndOfSection(rAnchorPos) && IsAtStartOfSection2(rStart)))));
1641 }
1642 
1643 bool IsSelectFrameAnchoredAtPara(SwPosition const & rAnchorPos,
1644  SwPosition const & rStart, SwPosition const & rEnd,
1645  DelContentType const nDelContentType)
1646 {
1647  assert(rStart <= rEnd);
1648 
1649  // CheckNoCntnt means DelFullPara which is obvious to handle
1650  if (DelContentType::CheckNoCntnt & nDelContentType)
1651  { // exclude selection end node because it won't be deleted
1652  return (rAnchorPos.nNode < rEnd.nNode)
1653  && (rStart.nNode <= rAnchorPos.nNode);
1654  }
1655 
1656  if ((nDelContentType & DelContentType::WriterfilterHack)
1657  && rAnchorPos.GetDoc().IsInWriterfilterImport())
1658  { // FIXME hack for writerfilter RemoveLastParagraph() and MakeFlyAndMove(); can't test file format more specific?
1659  // but it MUST NOT be done during the SetRedlineFlags at the end of ODF
1660  // import, where the IsInXMLImport() cannot be checked because the
1661  // stupid code temp. overrides it - instead rely on setting the ALLFLYS
1662  // flag in MoveFromSection() and converting that to CheckNoCntnt with
1663  // adjusted cursor!
1664  return (rStart.nNode < rAnchorPos.nNode) && (rAnchorPos.nNode < rEnd.nNode);
1665  }
1666 
1667  // in general, exclude the start and end position
1668  return ((rStart.nNode < rAnchorPos.nNode)
1669  || (rStart.nNode == rAnchorPos.nNode
1670  && !(nDelContentType & DelContentType::ExcludeFlyAtStartEnd)
1671  // special case: fully deleted node
1672  && ((rStart.nNode != rEnd.nNode && rStart.nContent == 0
1673  // but not if the selection is backspace/delete!
1674  && IsNotBackspaceHeuristic(rStart, rEnd))
1675  || (IsAtStartOfSection2(rStart) && IsAtEndOfSection2(rEnd)))))
1676  && ((rAnchorPos.nNode < rEnd.nNode)
1677  || (rAnchorPos.nNode == rEnd.nNode
1678  && !(nDelContentType & DelContentType::ExcludeFlyAtStartEnd)
1679  // special case: fully deleted node
1680  && ((rEnd.nNode != rStart.nNode && rEnd.nContent == rEnd.nNode.GetNode().GetTextNode()->Len()
1681  && IsNotBackspaceHeuristic(rStart, rEnd))
1682  || (IsAtEndOfSection2(rEnd) && IsAtStartOfSection2(rStart)))));
1683 }
1684 
1685 bool IsFlySelectedByCursor(SwDoc const & rDoc,
1686  SwPosition const & rStart, SwPosition const & rEnd)
1687 {
1688  for (SwFrameFormat const*const pFly : *rDoc.GetSpzFrameFormats())
1689  {
1690  SwFormatAnchor const& rAnchor(pFly->GetAnchor());
1691  switch (rAnchor.GetAnchorId())
1692  {
1693  case RndStdIds::FLY_AT_CHAR:
1694  case RndStdIds::FLY_AT_PARA:
1695  {
1696  SwPosition const*const pAnchorPos(rAnchor.GetContentAnchor());
1697  // can this really be null?
1698  if (pAnchorPos != nullptr
1699  && ((rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
1700  ? IsDestroyFrameAnchoredAtChar(*pAnchorPos, rStart, rEnd)
1701  : IsSelectFrameAnchoredAtPara(*pAnchorPos, rStart, rEnd)))
1702  {
1703  return true;
1704  }
1705  }
1706  break;
1707  default: // other types not relevant
1708  break;
1709  }
1710  }
1711  return false;
1712 }
1713 
1714 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static bool IsAtEndOfSection(SwPosition const &rAnchorPos)
Definition: undobj.cxx:1553
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:686
Starts a section of nodes in the document model.
Definition: node.hxx:313
virtual SwCursor & CreateNewShellCursor()=0
SwPaM & AddUndoRedoPaM(::sw::UndoRedoContext &, bool const bCorrToContent=false) const
Definition: undobj.cxx:108
virtual sal_Int32 Len() const
Definition: node.cxx:1243
void DeleteMark()
Definition: pam.hxx:178
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:224
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:970
std::unique_ptr< SwRedlineSaveDatas > m_pRedlineSaveData
Definition: undobj.hxx:204
Marks a position in the document model.
Definition: pam.hxx:36
std::unique_ptr< SwHistory > m_pHistory
Definition: undobj.hxx:167
SwNodes const & GetUndoNodes() const
Definition: docundo.cxx:77
void SetContentIdx(const SwNodeIndex *)
Definition: docredln.cxx:1829
SwComparePosition ComparePosition(const T &rStt1, const T &rEnd1, const T &rStt2, const T &rEnd2)
Definition: pam.hxx:78
static bool IsAtStartOfSection(SwPosition const &rAnchorPos)
Definition: undobj.cxx:1564
constexpr SwNodeOffset NODE_OFFSET_MAX(SAL_MAX_INT32)
SwUndoId
Definition: swundo.hxx:29
SwDocShell * GetDocShell()
Definition: doc.hxx:1352
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
size_t size() const
Definition: UndoCore.hxx:78
bool Rollback(SwDoc *pDoc, sal_uInt16 nStart=0)
Definition: rolbck.cxx:1209
virtual void SetRedlineFlags_intern(RedlineFlags eMode)=0
Set a new redline mode.
static bool FillSaveDataForFormat(const SwPaM &, SwRedlineSaveDatas &)
Definition: undobj.cxx:1444
SwNodeIndex nNode
Definition: pam.hxx:38
static void RemoveIdxFromSection(SwDoc &, SwNodeOffset nSttIdx, const SwNodeOffset *pEndIdx=nullptr)
Definition: undobj.cxx:116
virtual void Repeat(SfxRepeatTarget &) override
Definition: undobj.cxx:247
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:278
Pos1 is as large as Pos2.
static SW_DLLPUBLIC MarkType GetType(const ::sw::mark::IMark &rMark)
Returns the MarkType used to create the mark.
Definition: docbm.cxx:478
const SwPosition * GetMark() const
Definition: pam.hxx:210
Pos1 completely contained in Pos2.
sal_Int64 n
static ViewShellId CreateViewShellId(const SwDoc *pDoc)
Try to obtain the view shell ID of the current view.
Definition: undobj.cxx:169
Provides access to the marks of a document.
Definition: doc.hxx:188
virtual ~SwUndoSaveContent() COVERITY_NOEXCEPT_FALSE
Definition: undobj.cxx:706
SwRedlineSaveData(SwComparePosition eCmpPos, const SwPosition &rSttPos, const SwPosition &rEndPos, SwRangeRedline &rRedl, bool bCopyNext)
Definition: undobj.cxx:1321
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1317
static bool IsAtStartOfSection2(SwPosition const &rPos)
Definition: undobj.cxx:1582
SwNode & GetNode() const
Definition: ndindex.hxx:121
bool IsSelectFrameAnchoredAtPara(SwPosition const &rAnchorPos, SwPosition const &rStart, SwPosition const &rEnd, DelContentType const nDelContentType)
is a fly anchored at paragraph at rAnchorPos selected?
Definition: undobj.cxx:1643
const SwHistory * GetHistory() const
Definition: undobj.hxx:221
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1790
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
SwNode & GetEndOfPostIts() const
A still empty section.
Definition: ndarr.hxx:151
bool IsDestroyFrameAnchoredAtChar(SwPosition const &rAnchorPos, SwPosition const &rStart, SwPosition const &rEnd, DelContentType const nDelContentType)
will DelContentIndex destroy a frame anchored at character at rAnchorPos?
Definition: undobj.cxx:1602
virtual void RepeatImpl(::sw::RepeatContext &)
Definition: undobj.cxx:267
SwUndoId GetId() const
Definition: undobj.hxx:102
bool CanCombine(const SwRedlineData &rCmp) const
Definition: docredln.cxx:1036
const SwFrameFormats * GetSpzFrameFormats() const
Definition: doc.hxx:744
IShellCursorSupplier & GetCursorSupplier()
Definition: UndoCore.hxx:98
SwUndRng()
Definition: undobj.cxx:50
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: undobj.cxx:710
size_type size() const
Definition: docary.hxx:268
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:230
void SetValues(const SwPaM &rPam)
Definition: undobj.cxx:60
SwTextAttr * GetTextAttrForCharAt(const sal_Int32 nIndex, const sal_uInt16 nWhich=RES_TXTATR_END) const
get the text attribute at position nIndex which owns the dummy character CH_TXTATR_* at that position...
Definition: ndtxt.cxx:3030
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:165
Pos1 end touches at Pos2 start.
sal_uInt16 m_nRedlineCount
Definition: UndoCore.hxx:64
SwNodeIndex * GetMvSttIdx() const
Definition: UndoCore.hxx:58
SwIndex nContent
Definition: pam.hxx:39
SwNodeIndex aStart
Definition: ndindex.hxx:134
A wrapper around SfxPoolItem to store the start position of (usually) a text portion, with an optional end.
Definition: txatbase.hxx:41
sal_Int32 GetStart() const
Definition: txatbase.hxx:86
virtual SwRewriter GetRewriter() const
Returns the rewriter for this object.
Definition: undobj.cxx:696
bool IsStartNode() const
Definition: node.hxx:628
Pos2 completely contained in Pos1.
static bool CanRedlineGroup(SwRedlineSaveDatas &rCurr, const SwRedlineSaveDatas &rCheck, bool bCurrIsEnd)
Definition: undobj.cxx:1502
#define suppress_fun_call_w_exception(expr)
bool empty() const
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:154
Pos1 before Pos2.
RedlineFlags on.
size_type size() const
static void RemoveIdxFromRange(SwPaM &rPam, bool bMoveNext)
Definition: undobj.cxx:126
virtual bool CanRepeat(SfxRepeatTarget &) const override
Definition: undobj.cxx:259
RedlineFlags GetRedlineFlags() const
Definition: undobj.hxx:120
Specific frame formats (frames, DrawObjects).
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:162
virtual std::unique_ptr< ILazyDeleter > deleteMark(const IDocumentMarkAccess::const_iterator_t &ppMark)=0
Deletes a mark.
virtual const_iterator_t getAllMarksBegin() const =0
returns a STL-like random access iterator to the begin of the sequence of marks.
bool IsContentNode() const
Definition: node.hxx:632
static void MovePtForward(SwPaM &rPam, bool bMvBkwrd)
Definition: undobj.cxx:840
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
virtual void UndoImpl(::sw::UndoRedoContext &)=0
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:504
static bool IsNotBackspaceHeuristic(SwPosition const &rStart, SwPosition const &rEnd)
Definition: undobj.cxx:1588
SwTextFootnote * SeekEntry(const SwNodeIndex &rIdx, size_t *pPos=nullptr) const
Definition: ftnidx.cxx:409
Style of a layout element.
Definition: frmfmt.hxx:59
::sw::UndoManager & GetUndoManager()
Definition: doc.cxx:133
static bool HasHiddenRedlines(const SwRedlineSaveDatas &rSData)
Definition: undobj.cxx:1494
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:133
SwDoc & GetDoc()
Definition: node.hxx:213
const SwPosition * GetPoint() const
Definition: pam.hxx:208
Pos1 start touches at Pos2 end.
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: undobj.cxx:1315
void DelContentIndex(const SwPosition &pMark, const SwPosition &pPoint, DelContentType nDelContentType=DelContentType::AllMask)
Definition: undobj.cxx:865
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
OUString Apply(const OUString &rStr) const
Definition: SwRewriter.cxx:39
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
OUString ShortenString(const OUString &rStr, sal_Int32 nLength, const OUString &rFillStr)
Shortens a string to a maximum length.
Definition: undobj.cxx:1534
static void SetSaveData(SwDoc &rDoc, SwRedlineSaveDatas &rSData)
Definition: undobj.cxx:1474
void Exchange()
Definition: pam.cxx:492
virtual bool DeleteRedline(const SwPaM &rPam, bool bSaveInUndo, RedlineType nDelType)=0
SwContentNode * GetContentNode()
Definition: node.hxx:619
SwNodeOffset GetIndex() const
Definition: node.hxx:292
vector_type::size_type size_type
Definition: docary.hxx:223
FlyAnchors.
Definition: fmtanchr.hxx:34
void MakeStartIndex(SwIndex *pIdx)
Definition: node.hxx:399
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:206
SwNoTextNode * GetNoTextNode()
Definition: ndnotxt.hxx:96
SwNodeOffset m_nMoveLen
Definition: undobj.hxx:205
ViewShellId m_nViewShellId
Definition: undobj.hxx:58
sal_Int32 m_nEndContent
Definition: undobj.hxx:232
virtual void UndoWithContext(SfxUndoContext &) override
Definition: undobj.cxx:229
Marks a character position inside a document model node.
Definition: index.hxx:33
void PaMCorrRel(const SwNodeIndex &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset)
Sets all PaMs in OldNode to relative Pos.
Definition: doccorr.cxx:241
std::optional< OUString > maComment
Definition: undobj.hxx:63
Marks a node in the document model.
Definition: ndindex.hxx:32
bool m_bCacheComment
Definition: undobj.hxx:62
bool IsEndNode() const
Definition: node.hxx:636
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:697
static bool MovePtBackward(SwPaM &rPam)
Definition: undobj.cxx:827
bool empty() const
void push_back(std::unique_ptr< SwRedlineSaveData > pNew)
Definition: UndoCore.hxx:79
virtual OUString GetComment() const override
Returns textual comment for this undo object.
Definition: undobj.cxx:662
std::unique_ptr< SwNodeIndex > m_pMovedStart
Definition: undobj.hxx:203
const SwPosition * Start() const
Definition: pam.hxx:213
void RedlineToDoc(SwPaM const &rPam)
Definition: undobj.cxx:1378
SwNodeOffset m_nEndNode
Definition: undobj.hxx:231
SwNodeOffset m_nStartPos
Definition: undobj.hxx:206
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:450
const OUString & GetComment(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1908
ignore Redlines
void EraseText(const SwIndex &rIdx, const sal_Int32 nCount=SAL_MAX_INT32, const SwInsertFlags nMode=SwInsertFlags::DEFAULT)
delete text content ATTENTION: must not be called with a range that overlaps the start of an attribut...
Definition: ndtxt.cxx:2650
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
void RestoreSection(SwDoc *pDoc, SwNodeIndex *pIdx, sal_uInt16 nSectType)
Definition: undobj.cxx:1275
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:335
bool IsMoved() const
Definition: redline.hxx:270
void SetPaM(SwPaM &, bool bCorrToContent=false) const
Definition: undobj.cxx:80
DelContentType
Definition: undobj.hxx:134
virtual sal_Int32 getAllMarksCount() const =0
returns the number of marks.
void CorrAbs(const SwNodeIndex &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset=0, bool bMoveCursor=false)
Definition: doccorr.cxx:168
Pos1 overlaps Pos2 at the end.
const SwNodes & GetNodes() const
Definition: ndindex.hxx:158
virtual ~SwUndo() override
Definition: undobj.cxx:188
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
#define SAL_INFO(area, stream)
sal_Int32 GetIndex() const
Definition: index.hxx:91
SwNodes & GetNodes()
Definition: doc.hxx:409
SwUndo(SwUndoId const nId, const SwDoc *pDoc)
Definition: undobj.cxx:161
const SwPosition * End() const
Definition: pam.hxx:218
SwNodeIndex aEnd
Definition: ndindex.hxx:135
SwDoc & GetDoc() const
Returns the document this position is in.
Definition: pam.cxx:181
bool m_isRepeatIgnored
for multi-selection, only repeat 1st selection
Definition: undobj.hxx:59
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1903
void Delete(const SwNodeIndex &rPos, SwNodeOffset nNodes=SwNodeOffset(1))
delete nodes
Definition: nodes.cxx:1085
virtual void Redo() override
Definition: undobj.cxx:224
virtual void RedoWithContext(SfxUndoContext &) override
Definition: undobj.cxx:238
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
static void RemoveIdxRel(SwNodeOffset, const SwPosition &)
Definition: undobj.cxx:153
bool empty() const
Definition: UndoCore.hxx:77
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:58
friend class SwRangeRedline
Definition: redline.hxx:88
virtual void RedoImpl(::sw::UndoRedoContext &)=0
OUString GetUndoComment(SwUndoId eId)
Definition: undobj.cxx:271
virtual void Undo() override
Definition: undobj.cxx:219
Any result
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:634
ResultType type
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
struct _xmlTextWriter * xmlTextWriterPtr
size_t size() const
SwDoc & GetDoc() const
Definition: pam.hxx:244
bool IsFlySelectedByCursor(SwDoc const &rDoc, SwPosition const &rStart, SwPosition const &rEnd)
check at-char and at-para flys in rDoc
Definition: undobj.cxx:1685
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:478
Pos1 behind Pos2.
static bool FillSaveData(const SwPaM &rRange, SwRedlineSaveDatas &rSData, bool bDelRange=true, bool bCopyNext=true)
Definition: undobj.cxx:1409
virtual const SwRedlineTable & GetRedlineTable() const =0
ViewShellId GetViewShellId() const override
See SfxUndoAction::GetViewShellId().
Definition: undobj.cxx:691
const SwIndexReg * GetIdxReg() const
Definition: index.hxx:97
SwNode & GetEndOfExtras() const
This is the last EndNode of a special section.
Definition: ndarr.hxx:160
static void MoveToUndoNds(SwPaM &rPam, SwNodeIndex *pNodeIdx, SwNodeOffset *pEndNdIdx=nullptr)
Definition: undobj.cxx:731
bool IsTextNode() const
Definition: node.hxx:640
void SaveSection(const SwNodeIndex &rSttIdx)
Definition: undobj.cxx:1222
SwNodeIndex * GetContentIdx() const
Definition: redline.hxx:187
bool IsDelBox() const
Definition: undobj.cxx:182
Pos1 overlaps Pos2 at the beginning.
sal_Int32 m_nSttContent
Definition: undobj.hxx:232
Definition: view.hxx:144
sal_uInt16 nPos
bool IsInWriterfilterImport() const
Definition: doc.hxx:972
SwComparePosition
Definition: pam.hxx:65
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:856
static bool IsAtEndOfSection2(SwPosition const &rPos)
passed start / end position could be on section start / end node
Definition: undobj.cxx:1576
void SetAnchor(const SwPosition *pPos)
Definition: atrfrm.cxx:1584
bool MoveNodes(const SwNodeRange &, SwNodes &rNodes, const SwNodeIndex &, bool bNewFrames=true)
move the node pointer
Definition: nodes.cxx:409
static SwStartNode * MakeEmptySection(const SwNodeIndex &rIdx, SwStartNodeType=SwNormalStartNode)
Create an empty section of Start- and EndNote.
Definition: nodes.cxx:1888
Base class of the Writer document model elements.
Definition: node.hxx:81
void MoveRange(SwPaM &, SwPosition &, SwNodes &rNodes)
move a range
Definition: nodes.cxx:1435
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
SwNodeOffset m_nSttNode
Definition: undobj.hxx:231
static void MoveFromUndoNds(SwDoc &rDoc, SwNodeOffset nNodeIdx, SwPosition &rInsPos, const SwNodeOffset *pEndNdIdx=nullptr, bool bForceCreateFrames=false)
Definition: undobj.cxx:768