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