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
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
56{
57 SetValues( rPam );
58}
59
60void 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->GetNodeIndex();
68 }
69 else
70 {
71 // no selection !!
74 }
75
76 m_nSttNode = pStt->GetNodeIndex();
78}
79
80void SwUndRng::SetPaM( SwPaM & rPam, bool bCorrToContent ) const
81{
82 rPam.DeleteMark();
84 SwNode& rNd = rPam.GetPointNode();
85 if( !rNd.IsContentNode() && bCorrToContent )
87
88 if( !m_nEndNode && COMPLETE_STRING == m_nEndContent ) // no selection
89 return ;
90
91 rPam.SetMark();
93 return; // nothing left to do
94
96 if( !rPam.GetPointNode().IsContentNode() && bCorrToContent )
98}
99
101 ::sw::UndoRedoContext & rContext, bool const bCorrToContent) const
102{
103 SwCursor & rPaM( rContext.GetCursorSupplier().CreateNewShellCursor() );
104 SetPaM( rPaM, bCorrToContent );
105 return rPaM;
106}
107
109 const SwNodeOffset* pEndIdx )
110{
111 SwNodeIndex aIdx( rDoc.GetNodes(), nSttIdx );
112 SwNodeIndex aEndIdx( rDoc.GetNodes(), pEndIdx ? *pEndIdx
113 : aIdx.GetNode().EndOfSectionIndex() );
114 SwPosition aPos( rDoc.GetNodes().GetEndOfPostIts() );
115 SwDoc::CorrAbs( aIdx, aEndIdx, aPos, true );
116}
117
118void SwUndo::RemoveIdxFromRange( SwPaM& rPam, bool bMoveNext )
119{
120 const SwPosition* pEnd = rPam.End();
121 if( bMoveNext )
122 {
123 if( pEnd != rPam.GetPoint() )
124 rPam.Exchange();
125
126 SwNodeIndex aStt( rPam.GetMark()->GetNode() );
127 SwNodeIndex aEnd( rPam.GetPoint()->GetNode() );
128
129 if( !rPam.Move( fnMoveForward ) )
130 {
131 rPam.Exchange();
132 if( !rPam.Move( fnMoveBackward ) )
133 {
134 rPam.GetPoint()->Assign( rPam.GetDoc().GetNodes().GetEndOfPostIts() );
135 }
136 }
137
138 SwDoc::CorrAbs( aStt, aEnd, *rPam.GetPoint(), true );
139 }
140 else
141 SwDoc::CorrAbs( rPam, *pEnd, true );
142}
143
145{
146 // Move only the Cursor. Bookmarks/TOXMarks/etc. are done by the corresponding
147 // JoinNext/JoinPrev
148 ::PaMCorrRel( *rPos.GetNode().GetNodes()[nIdx], rPos );
149}
150
151SwUndo::SwUndo(SwUndoId const nId, const SwDoc* pDoc)
152 : m_nId(nId), m_nOrigRedlineFlags(RedlineFlags::NONE)
153 , m_nViewShellId(CreateViewShellId(pDoc))
154 , m_isRepeatIgnored(false)
155 , m_bCacheComment(true)
156{
157}
158
160{
161 ViewShellId nRet(-1);
162
163 if (const SwDocShell* pDocShell = pDoc->GetDocShell())
164 {
165 if (const SwView* pView = pDocShell->GetView())
166 nRet = pView->GetViewShellId();
167 }
168
169 return nRet;
170}
171
173{
176}
177
179{
180}
181
182namespace {
183
184class UndoRedoRedlineGuard
185{
186public:
187 UndoRedoRedlineGuard(::sw::UndoRedoContext const & rContext, SwUndo const & rUndo)
188 : m_rRedlineAccess(rContext.GetDoc().getIDocumentRedlineAccess())
189 , m_eMode(m_rRedlineAccess.GetRedlineFlags())
190 {
191 RedlineFlags const eTmpMode = rUndo.GetRedlineFlags();
192 if ((RedlineFlags::ShowMask & eTmpMode) != (RedlineFlags::ShowMask & m_eMode))
193 {
194 m_rRedlineAccess.SetRedlineFlags( eTmpMode );
195 }
196 m_rRedlineAccess.SetRedlineFlags_intern( eTmpMode | RedlineFlags::Ignore );
197 }
198 ~UndoRedoRedlineGuard()
199 {
200 m_rRedlineAccess.SetRedlineFlags(m_eMode);
201 }
202private:
203 IDocumentRedlineAccess & m_rRedlineAccess;
204 RedlineFlags const m_eMode;
205};
206
207}
208
210{
211 assert(false); // SwUndo::Undo(): ERROR: must call UndoWithContext instead
212}
213
215{
216 assert(false); // SwUndo::Redo(): ERROR: must call RedoWithContext instead
217}
218
220{
221 ::sw::UndoRedoContext *const pContext(
222 dynamic_cast< ::sw::UndoRedoContext * >(& rContext));
223 assert(pContext);
224 const UndoRedoRedlineGuard aUndoRedoRedlineGuard(*pContext, *this);
225 UndoImpl(*pContext);
226}
227
229{
230 ::sw::UndoRedoContext *const pContext(
231 dynamic_cast< ::sw::UndoRedoContext * >(& rContext));
232 assert(pContext);
233 const UndoRedoRedlineGuard aUndoRedoRedlineGuard(*pContext, *this);
234 RedoImpl(*pContext);
235}
236
237void SwUndo::Repeat(SfxRepeatTarget & rContext)
238{
240 {
241 return; // ignore Repeat for multi-selections
242 }
243 ::sw::RepeatContext *const pRepeatContext(
244 dynamic_cast< ::sw::RepeatContext * >(& rContext));
245 assert(pRepeatContext);
246 RepeatImpl(*pRepeatContext);
247}
248
249bool SwUndo::CanRepeat(SfxRepeatTarget & rContext) const
250{
251 assert(dynamic_cast< ::sw::RepeatContext * >(& rContext));
252 (void)rContext;
253 // a MultiSelection action that doesn't do anything must still return true
255}
256
258{
259}
260
262{
263 TranslateId pId;
264 switch (eId)
265 {
266 case SwUndoId::EMPTY:
267 pId = STR_CANT_UNDO;
268 break;
269 case SwUndoId::START:
270 case SwUndoId::END:
271 break;
272 case SwUndoId::DELETE:
273 pId = STR_DELETE_UNDO;
274 break;
275 case SwUndoId::INSERT:
276 pId = STR_INSERT_UNDO;
277 break;
279 pId = STR_OVR_UNDO;
280 break;
282 pId = STR_SPLITNODE_UNDO;
283 break;
285 pId = STR_INSATTR_UNDO;
286 break;
288 pId = STR_SETFMTCOLL_UNDO;
289 break;
291 pId = STR_RESET_ATTR_UNDO;
292 break;
294 pId = STR_INSFMT_ATTR_UNDO;
295 break;
297 pId = STR_INSERT_DOC_UNDO;
298 break;
299 case SwUndoId::COPY:
300 pId = STR_COPY_UNDO;
301 break;
303 pId = STR_INSTABLE_UNDO;
304 break;
306 pId = STR_TABLETOTEXT_UNDO;
307 break;
309 pId = STR_TEXTTOTABLE_UNDO;
310 break;
312 pId = STR_SORT_TXT;
313 break;
315 pId = STR_INSERTFLY;
316 break;
318 pId = STR_TABLEHEADLINE;
319 break;
321 pId = STR_INSERTSECTION;
322 break;
324 pId = STR_OUTLINE_LR;
325 break;
327 pId = STR_OUTLINE_UD;
328 break;
330 pId = STR_OUTLINE_EDIT;
331 break;
332 case SwUndoId::INSNUM:
333 pId = STR_INSNUM;
334 break;
335 case SwUndoId::NUMUP:
336 pId = STR_NUMUP;
337 break;
339 pId = STR_MOVENUM;
340 break;
342 pId = STR_INSERTDRAW;
343 break;
345 pId = STR_NUMORNONUM;
346 break;
348 pId = STR_INC_LEFTMARGIN;
349 break;
351 pId = STR_DEC_LEFTMARGIN;
352 break;
354 pId = STR_INSERTLABEL;
355 break;
357 pId = STR_SETNUMRULESTART;
358 break;
359 case SwUndoId::CHGFTN:
360 pId = STR_CHANGEFTN;
361 break;
363 SAL_INFO("sw.core", "Should NEVER be used/translated");
364 return "$1";
366 pId = STR_ACCEPT_REDLINE;
367 break;
369 pId = STR_REJECT_REDLINE;
370 break;
372 pId = STR_SPLIT_TABLE;
373 break;
375 pId = STR_DONTEXPAND;
376 break;
378 pId = STR_AUTOCORRECT;
379 break;
381 pId = STR_MERGE_TABLE;
382 break;
384 pId = STR_TRANSLITERATE;
385 break;
387 pId = STR_PASTE_CLIPBOARD_UNDO;
388 break;
389 case SwUndoId::TYPING:
390 pId = STR_TYPING_UNDO;
391 break;
392 case SwUndoId::MOVE:
393 pId = STR_MOVE_UNDO;
394 break;
396 pId = STR_INSERT_GLOSSARY;
397 break;
399 pId = STR_DELBOOKMARK;
400 break;
402 pId = STR_INSBOOKMARK;
403 break;
405 pId = STR_SORT_TBL;
406 break;
408 pId = STR_DELETEFLY;
409 break;
411 pId = STR_AUTOFORMAT;
412 break;
414 pId = STR_REPLACE;
415 break;
417 pId = STR_DELETESECTION;
418 break;
420 pId = STR_CHANGESECTION;
421 break;
423 pId = STR_CHANGEDEFATTR;
424 break;
425 case SwUndoId::DELNUM:
426 pId = STR_DELNUM;
427 break;
429 pId = STR_DRAWUNDO;
430 break;
432 pId = STR_DRAWGROUP;
433 break;
435 pId = STR_DRAWUNGROUP;
436 break;
438 pId = STR_DRAWDELETE;
439 break;
440 case SwUndoId::REREAD:
441 pId = STR_REREAD;
442 break;
443 case SwUndoId::DELGRF:
444 pId = STR_DELGRF;
445 break;
447 pId = STR_TABLE_ATTR;
448 break;
450 pId = STR_UNDO_TABLE_AUTOFMT;
451 break;
453 pId = STR_UNDO_TABLE_INSCOL;
454 break;
456 pId = STR_UNDO_TABLE_INSROW;
457 break;
459 pId = STR_UNDO_TABLE_DELBOX;
460 break;
462 pId = STR_UNDO_TABLE_SPLIT;
463 break;
465 pId = STR_UNDO_TABLE_MERGE;
466 break;
468 pId = STR_TABLE_NUMFORMAT;
469 break;
470 case SwUndoId::INSTOX:
471 pId = STR_INSERT_TOX;
472 break;
474 pId = STR_CLEAR_TOX_RANGE;
475 break;
477 pId = STR_TABLE_TBLCPYTBL;
478 break;
479 case SwUndoId::CPYTBL:
480 pId = STR_TABLE_CPYTBL;
481 break;
483 pId = STR_INS_FROM_SHADOWCRSR;
484 break;
485 case SwUndoId::CHAINE:
486 pId = STR_UNDO_CHAIN;
487 break;
489 pId = STR_UNDO_UNCHAIN;
490 break;
492 pId = STR_UNDO_FTNINFO;
493 break;
495 pId = STR_UNDO_COMPAREDOC;
496 break;
498 pId = STR_UNDO_SETFLYFRMFMT;
499 break;
501 pId = STR_UNDO_SETRUBYATTR;
502 break;
504 pId = STR_TOXCHANGE;
505 break;
507 pId = STR_UNDO_PAGEDESC_CREATE;
508 break;
510 pId = STR_UNDO_PAGEDESC;
511 break;
513 pId = STR_UNDO_PAGEDESC_DELETE;
514 break;
516 pId = STR_UNDO_HEADER_FOOTER;
517 break;
518 case SwUndoId::FIELD:
519 pId = STR_UNDO_FIELD;
520 break;
522 pId = STR_UNDO_TXTFMTCOL_CREATE;
523 break;
525 pId = STR_UNDO_TXTFMTCOL_DELETE;
526 break;
528 pId = STR_UNDO_TXTFMTCOL_RENAME;
529 break;
531 pId = STR_UNDO_CHARFMT_CREATE;
532 break;
534 pId = STR_UNDO_CHARFMT_DELETE;
535 break;
537 pId = STR_UNDO_CHARFMT_RENAME;
538 break;
540 pId = STR_UNDO_FRMFMT_CREATE;
541 break;
543 pId = STR_UNDO_FRMFMT_DELETE;
544 break;
546 pId = STR_UNDO_FRMFMT_RENAME;
547 break;
549 pId = STR_UNDO_NUMRULE_CREATE;
550 break;
552 pId = STR_UNDO_NUMRULE_DELETE;
553 break;
555 pId = STR_UNDO_NUMRULE_RENAME;
556 break;
558 pId = STR_UNDO_BOOKMARK_RENAME;
559 break;
561 pId = STR_UNDO_INDEX_ENTRY_INSERT;
562 break;
564 pId = STR_UNDO_INDEX_ENTRY_DELETE;
565 break;
567 pId = STR_UNDO_COL_DELETE;
568 break;
570 pId = STR_UNDO_ROW_DELETE;
571 break;
573 pId = STR_UNDO_PAGEDESC_RENAME;
574 break;
576 pId = STR_NUMDOWN;
577 break;
579 pId = STR_UNDO_FLYFRMFMT_TITLE;
580 break;
582 pId = STR_UNDO_FLYFRMFMT_DESCRIPTION;
583 break;
585 pId = STR_UNDO_TBLSTYLE_CREATE;
586 break;
588 pId = STR_UNDO_TBLSTYLE_DELETE;
589 break;
591 pId = STR_UNDO_TBLSTYLE_UPDATE;
592 break;
594 pId = STR_REPLACE_UNDO;
595 break;
597 pId = STR_INSERT_PAGE_BREAK_UNDO;
598 break;
600 pId = STR_INSERT_COLUMN_BREAK_UNDO;
601 break;
603 pId = STR_INSERT_ENV_UNDO;
604 break;
606 pId = STR_DRAG_AND_COPY;
607 break;
609 pId = STR_DRAG_AND_MOVE;
610 break;
612 pId = STR_INSERT_CHART;
613 break;
615 pId = STR_INSERT_FOOTNOTE;
616 break;
618 pId = STR_INSERT_URLBTN;
619 break;
621 pId = STR_INSERT_URLTXT;
622 break;
624 pId = STR_DELETE_INVISIBLECNTNT;
625 break;
627 pId = STR_REPLACE_STYLE;
628 break;
630 pId = STR_DELETE_PAGE_BREAK;
631 break;
633 pId = STR_TEXT_CORRECTION;
634 break;
636 pId = STR_UNDO_TABLE_DELETE;
637 break;
639 break;
641 pId = STR_PARAGRAPH_SIGN_UNDO;
642 break;
644 pId = STR_UNDO_INSERT_FORM_FIELD;
645 break;
647 pId = STR_UNDO_INSERT_PAGE_NUMBER;
648 break;
650 pId = STR_UNDO_UPDATE_FORM_FIELD;
651 break;
653 pId = STR_UNDO_UPDATE_FORM_FIELDS;
654 break;
656 pId = STR_UNDO_DELETE_FORM_FIELDS;
657 break;
659 pId = STR_UPDATE_BOOKMARK;
660 break;
662 pId = STR_UPDATE_BOOKMARKS;
663 break;
665 pId = STR_DELETE_BOOKMARKS;
666 break;
668 pId = STR_UPDATE_FIELD;
669 break;
671 pId = STR_UPDATE_FIELDS;
672 break;
674 pId = STR_DELETE_FIELDS;
675 break;
677 pId = STR_UPDATE_SECTIONS;
678 break;
680 pId = STR_UNDO_CHANGE_THEME_COLORS;
681 break;
683 pId = STR_DELETE_SECTIONS;
684 break;
686 pId = STR_UNDO_FLYFRMFMT_DECORATIVE;
687 break;
688 }
689
690 assert(pId);
691 return SwResId(pId);
692}
693
694OUString SwUndo::GetComment() const
695{
696 OUString aResult;
697
698 if (m_bCacheComment)
699 {
700 if (! maComment)
701 {
703
704 SwRewriter aRewriter = GetRewriter();
705
706 maComment = aRewriter.Apply(*maComment);
707 }
708
709 aResult = *maComment;
710 }
711 else
712 {
713 aResult = GetUndoComment(GetId());
714
715 SwRewriter aRewriter = GetRewriter();
716
717 aResult = aRewriter.Apply(aResult);
718 }
719
720 return aResult;
721}
722
724{
725 return m_nViewShellId;
726}
727
729{
730 SwRewriter aResult;
731
732 return aResult;
733}
734
736{}
737
739{
740}
741
743{
744 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwUndoSaveContent"));
745 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
746
747 if (m_pHistory)
748 {
749 m_pHistory->dumpAsXml(pWriter);
750 }
751
752 (void)xmlTextWriterEndElement(pWriter);
753}
754
755// This is needed when deleting content. For REDO all contents will be moved
756// into the UndoNodesArray. These methods always create a new node to insert
757// content. As a result, the attributes will not be expanded.
758// - MoveTo moves from NodesArray into UndoNodesArray
759// - MoveFrom moves from UndoNodesArray into NodesArray
760
761// If pEndNdIdx is given, Undo/Redo calls -Ins/DelFly. In that case the whole
762// section should be moved.
764 SwNodeOffset* pEndNdIdx )
765{
766 SwDoc& rDoc = rPaM.GetDoc();
767 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
768
769 SwNoTextNode* pCpyNd = rPaM.GetPointNode().GetNoTextNode();
770
771 // here comes the actual delete (move)
772 SwNodes & rNds = rDoc.GetUndoManager().GetUndoNodes();
773 SwPosition aPos( pEndNdIdx ? rNds.GetEndOfPostIts()
774 : rNds.GetEndOfExtras() );
775
776 const SwPosition* pStt = rPaM.Start(), *pEnd = rPaM.End();
777
778 SwNodeOffset nTmpMvNode = aPos.GetNodeIndex();
779
780 if( pCpyNd || pEndNdIdx )
781 {
782 SwNodeRange aRg( pStt->GetNode(), SwNodeOffset(0), pEnd->GetNode(), SwNodeOffset(1) );
783 rDoc.GetNodes().MoveNodes( aRg, rNds, aPos.GetNode(), true );
784 aPos.Adjust(SwNodeOffset(-1));
785 }
786 else
787 {
788 rDoc.GetNodes().MoveRange( rPaM, aPos, rNds );
789 }
790 if( pEndNdIdx )
791 *pEndNdIdx = aPos.GetNodeIndex();
792
793 // old position
794 aPos.Assign(nTmpMvNode);
795 if( pNodeIdx )
796 *pNodeIdx = aPos.GetNode();
797}
798
800 SwPosition& rInsPos,
801 const SwNodeOffset* pEndNdIdx, bool const bForceCreateFrames)
802{
803 // here comes the recovery
804 SwNodes & rNds = rDoc.GetUndoManager().GetUndoNodes();
805 if( nNodeIdx == rNds.GetEndOfPostIts().GetIndex() )
806 return; // nothing saved
807
808 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
809
810 SwPaM aPaM( rInsPos );
811 if( pEndNdIdx ) // than get the section from it
812 aPaM.GetPoint()->Assign( *rNds[SwNodeOffset(0)], *pEndNdIdx );
813 else
814 {
815 aPaM.GetPoint()->Assign( rNds.GetEndOfExtras() );
817 }
818
819 SwTextNode* pTextNd = aPaM.GetPointNode().GetTextNode();
820 if (!pEndNdIdx && pTextNd)
821 {
822 aPaM.SetMark();
823 aPaM.GetPoint()->Assign(nNodeIdx, 0);
824
825 SaveRedlEndPosForRestore aRedlRest( rInsPos.GetNode(), rInsPos.GetContentIndex() );
826
827 rNds.MoveRange( aPaM, rInsPos, rDoc.GetNodes() );
828
829 // delete the last Node as well
830 bool bDeleteLastNode = false;
831 if( !aPaM.GetPoint()->GetContentIndex() )
832 bDeleteLastNode = true;
833 else
834 {
835 // still empty Nodes at the end?
836 aPaM.GetPoint()->Adjust(SwNodeOffset(1));
837 if ( &rNds.GetEndOfExtras() != &aPaM.GetPoint()->GetNode() )
838 bDeleteLastNode = true;
839 }
840 if( bDeleteLastNode )
841 {
842 SwNode& rDelNode = aPaM.GetPoint()->GetNode();
843 SwNodeOffset nDelOffset = rNds.GetEndOfExtras().GetIndex() -
844 aPaM.GetPoint()->GetNodeIndex();
845 //move it so we don't have SwContentIndex pointing at a node when it is deleted.
846 aPaM.GetPoint()->Adjust(SwNodeOffset(-1));
847 aPaM.SetMark();
848 rNds.Delete( rDelNode, nDelOffset );
849 }
850
851 aRedlRest.Restore();
852 }
853 else
854 {
855 SwNodeRange aRg( rNds, nNodeIdx, (pEndNdIdx
856 ? ((*pEndNdIdx) + 1)
857 : rNds.GetEndOfExtras().GetIndex() ) );
858 rNds.MoveNodes(aRg, rDoc.GetNodes(), rInsPos.GetNode(), nullptr == pEndNdIdx || bForceCreateFrames);
859
860 }
861}
862
863// These two methods move the Point of Pam backwards/forwards. With that, one
864// can span an area for a Undo/Redo. (The Point is then positioned in front of
865// the area to manipulate!)
866// The flag indicates if there is still content in front of Point.
868{
869 rPam.SetMark();
870 if( rPam.Move( fnMoveBackward ))
871 return true;
872
873 // If there is no content onwards, set Point simply to the previous position
874 // (Node and Content, so that Content will be detached!)
875 rPam.GetPoint()->Adjust(SwNodeOffset(-1));
876 return false;
877}
878
879void SwUndoSaveContent::MovePtForward( SwPaM& rPam, bool bMvBkwrd )
880{
881 // Was there content before this position?
882 if( bMvBkwrd )
883 rPam.Move( fnMoveForward );
884 else
885 {
886 rPam.GetPoint()->Adjust(SwNodeOffset(1));
887 SwContentNode* pCNd = rPam.GetPointContentNode();
888 if( !pCNd )
889 rPam.Move( fnMoveForward );
890 }
891}
892
893// Delete all objects that have ContentIndices to the given area.
894// Currently (1994) these exist:
895// - Footnotes
896// - Flys
897// - Bookmarks
898
899// #i81002# - extending method
900// delete certain (not all) cross-reference bookmarks at text node of <rMark>
901// and at text node of <rPoint>, if these text nodes aren't the same.
903 const SwPosition& rPoint,
904 DelContentType nDelContentType )
905{
906 const SwPosition *pStt = rMark < rPoint ? &rMark : &rPoint,
907 *pEnd = &rMark == pStt ? &rPoint : &rMark;
908
909 SwDoc& rDoc = rMark.GetNode().GetDoc();
910
911 // if it's not in the doc array, probably missing some invalidation somewhere
912 assert(&rPoint.GetNodes() == &rDoc.GetNodes());
913 assert(&rMark.GetNodes() == &rDoc.GetNodes());
914
915 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
916
917 // 1. Footnotes
918 if( DelContentType::Ftn & nDelContentType )
919 {
920 SwFootnoteIdxs& rFootnoteArr = rDoc.GetFootnoteIdxs();
921 if( !rFootnoteArr.empty() )
922 {
923 const SwNode* pFootnoteNd;
924 size_t nPos = 0;
925 rFootnoteArr.SeekEntry( pStt->GetNode(), &nPos );
926 SwTextFootnote* pSrch;
927
928 // for now delete all that come afterwards
929 while( nPos < rFootnoteArr.size() && ( pFootnoteNd =
930 &( pSrch = rFootnoteArr[ nPos ] )->GetTextNode())->GetIndex()
931 <= pEnd->GetNodeIndex() )
932 {
933 const sal_Int32 nFootnoteSttIdx = pSrch->GetStart();
934 if( (DelContentType::CheckNoCntnt & nDelContentType )
935 ? (&pEnd->GetNode() == pFootnoteNd )
936 : (( &pStt->GetNode() == pFootnoteNd &&
937 pStt->GetContentIndex() > nFootnoteSttIdx) ||
938 ( &pEnd->GetNode() == pFootnoteNd &&
939 nFootnoteSttIdx >= pEnd->GetContentIndex() )) )
940 {
941 ++nPos; // continue searching
942 continue;
943 }
944
945// FIXME: duplicated code here and below -> refactor?
946 // Unfortunately an index needs to be created. Otherwise there
947 // will be problems with TextNode because the index will be
948 // deleted in the DTOR of SwFootnote!
949 SwTextNode* pTextNd = const_cast<SwTextNode*>(static_cast<const SwTextNode*>(pFootnoteNd));
950 if( !m_pHistory )
951 m_pHistory.reset( new SwHistory );
952 SwTextAttr* const pFootnoteHint =
953 pTextNd->GetTextAttrForCharAt( nFootnoteSttIdx );
954 assert(pFootnoteHint);
955 SwContentIndex aIdx( pTextNd, nFootnoteSttIdx );
956 m_pHistory->Add( pFootnoteHint, pTextNd->GetIndex(), false );
957 pTextNd->EraseText( aIdx, 1 );
958 }
959
960 while( nPos-- && ( pFootnoteNd = &( pSrch = rFootnoteArr[ nPos ] )->
961 GetTextNode())->GetIndex() >= pStt->GetNodeIndex() )
962 {
963 const sal_Int32 nFootnoteSttIdx = pSrch->GetStart();
964 if( !(DelContentType::CheckNoCntnt & nDelContentType) && (
965 ( &pStt->GetNode() == pFootnoteNd &&
966 pStt->GetContentIndex() > nFootnoteSttIdx ) ||
967 ( &pEnd->GetNode() == pFootnoteNd &&
968 nFootnoteSttIdx >= pEnd->GetContentIndex() )))
969 continue; // continue searching
970
971 // Unfortunately an index needs to be created. Otherwise there
972 // will be problems with TextNode because the index will be
973 // deleted in the DTOR of SwFootnote!
974 SwTextNode* pTextNd = const_cast<SwTextNode*>(static_cast<const SwTextNode*>(pFootnoteNd));
975 if( !m_pHistory )
976 m_pHistory.reset( new SwHistory );
977 SwTextAttr* const pFootnoteHint =
978 pTextNd->GetTextAttrForCharAt( nFootnoteSttIdx );
979 assert(pFootnoteHint);
980 SwContentIndex aIdx( pTextNd, nFootnoteSttIdx );
981 m_pHistory->Add( pFootnoteHint, pTextNd->GetIndex(), false );
982 pTextNd->EraseText( aIdx, 1 );
983 }
984 }
985 }
986
987 // 2. Flys
988 if( DelContentType::Fly & nDelContentType )
989 {
990 sal_uInt16 nChainInsPos = m_pHistory ? m_pHistory->Count() : 0;
991 const sw::SpzFrameFormats& rSpzArr = *rDoc.GetSpzFrameFormats();
992 if( !rSpzArr.empty() )
993 {
994 sw::SpzFrameFormat* pFormat;
995 const SwFormatAnchor* pAnchor;
996 size_t n = rSpzArr.size();
997 const SwPosition* pAPos;
998
999 while( n && !rSpzArr.empty() )
1000 {
1001 pFormat = rSpzArr[--n];
1002 pAnchor = &pFormat->GetAnchor();
1003 switch( pAnchor->GetAnchorId() )
1004 {
1005 case RndStdIds::FLY_AS_CHAR:
1006 if( nullptr != (pAPos = pAnchor->GetContentAnchor() ) &&
1007 (( DelContentType::CheckNoCntnt & nDelContentType )
1008 ? ( pStt->GetNode() <= pAPos->GetNode() &&
1009 pAPos->GetNode() < pEnd->GetNode() )
1010 : ( *pStt <= *pAPos && *pAPos < *pEnd )) )
1011 {
1012 if( !m_pHistory )
1013 m_pHistory.reset( new SwHistory );
1014 SwTextNode *const pTextNd =
1015 pAPos->GetNode().GetTextNode();
1016 SwTextAttr* const pFlyHint = pTextNd->GetTextAttrForCharAt(
1017 pAPos->GetContentIndex());
1018 assert(pFlyHint);
1019 m_pHistory->Add( pFlyHint, SwNodeOffset(0), false );
1020 // reset n so that no Format is skipped
1021 n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
1022 }
1023 break;
1024 case RndStdIds::FLY_AT_PARA:
1025 {
1026 pAPos = pAnchor->GetContentAnchor();
1027 if (pAPos &&
1028 pStt->GetNode() <= pAPos->GetNode() && pAPos->GetNode() <= pEnd->GetNode())
1029 {
1030 if (!m_pHistory)
1031 m_pHistory.reset( new SwHistory );
1032
1033 if (!(DelContentType::Replace & nDelContentType)
1034 && IsSelectFrameAnchoredAtPara(*pAPos, *pStt, *pEnd, nDelContentType))
1035 {
1036 m_pHistory->AddDeleteFly(*pFormat, nChainInsPos);
1037 // reset n so that no Format is skipped
1038 n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
1039 }
1040 // Moving the anchor?
1042 & nDelContentType) &&
1043 // for SwUndoDelete: rPoint is the node that
1044 // will be Joined - so anchor should be moved
1045 // off it - but UndoImpl() split will insert
1046 // new node *before* existing one so a no-op
1047 // may need to be done here to add it to
1048 // history for Undo.
1049 (rPoint.GetNodeIndex() == pAPos->GetNodeIndex()
1050 || pStt->GetNodeIndex() == pAPos->GetNodeIndex())
1051 // Do not try to move the anchor to a table!
1052 && rMark.GetNode().IsTextNode())
1053 {
1054 m_pHistory->AddChangeFlyAnchor(*pFormat);
1055 SwFormatAnchor aAnch( *pAnchor );
1056 SwPosition aPos( rMark.GetNode() );
1057 aAnch.SetAnchor( &aPos );
1058 pFormat->SetFormatAttr( aAnch );
1059 }
1060 }
1061 }
1062 break;
1063 case RndStdIds::FLY_AT_CHAR:
1064 if( nullptr != (pAPos = pAnchor->GetContentAnchor() ) &&
1065 ( pStt->GetNode() <= pAPos->GetNode() && pAPos->GetNode() <= pEnd->GetNode() ) )
1066 {
1067 if( !m_pHistory )
1068 m_pHistory.reset( new SwHistory );
1069 if (!(DelContentType::Replace & nDelContentType)
1071 *pAPos, *pStt, *pEnd, nDelContentType))
1072 {
1073 m_pHistory->AddDeleteFly(*pFormat, nChainInsPos);
1074 n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
1075 }
1076 else if (!((DelContentType::CheckNoCntnt |
1078 & nDelContentType))
1079 {
1080 if( *pStt <= *pAPos && *pAPos < *pEnd )
1081 {
1082 // These are the objects anchored
1083 // between section start and end position
1084 // Do not try to move the anchor to a table!
1085 if( rMark.GetNode().GetTextNode() )
1086 {
1087 m_pHistory->AddChangeFlyAnchor(*pFormat);
1088 SwFormatAnchor aAnch( *pAnchor );
1089 aAnch.SetAnchor( &rMark );
1090 pFormat->SetFormatAttr( aAnch );
1091 }
1092 }
1093 }
1094 }
1095 break;
1096 case RndStdIds::FLY_AT_FLY:
1097
1098 if( nullptr != (pAPos = pAnchor->GetContentAnchor() ) &&
1099 pStt->GetNode() == pAPos->GetNode() )
1100 {
1101 if( !m_pHistory )
1102 m_pHistory.reset( new SwHistory );
1103
1104 m_pHistory->AddDeleteFly(*pFormat, nChainInsPos);
1105
1106 // reset n so that no Format is skipped
1107 n = n >= rSpzArr.size() ? rSpzArr.size() : n+1;
1108 }
1109 break;
1110 default: break;
1111 }
1112 }
1113 }
1114 }
1115
1116 // 3. Bookmarks
1117 if( !(DelContentType::Bkm & nDelContentType) )
1118 return;
1119
1120 IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
1121 if( !pMarkAccess->getAllMarksCount() )
1122 return;
1123
1124 for( sal_Int32 n = 0; n < pMarkAccess->getAllMarksCount(); ++n )
1125 {
1126 // #i81002#
1127 bool bSavePos = false;
1128 bool bSaveOtherPos = false;
1129 const ::sw::mark::IMark *const pBkmk = pMarkAccess->getAllMarksBegin()[n];
1130 auto const type(IDocumentMarkAccess::GetType(*pBkmk));
1131
1132 if( DelContentType::CheckNoCntnt & nDelContentType )
1133 {
1134 if ( pStt->GetNode() <= pBkmk->GetMarkPos().GetNode()
1135 && pBkmk->GetMarkPos().GetNode() < pEnd->GetNode() )
1136 {
1137 bSavePos = true;
1138 }
1139 if ( pBkmk->IsExpanded()
1140 && pStt->GetNode() <= pBkmk->GetOtherMarkPos().GetNode()
1141 && pBkmk->GetOtherMarkPos().GetNode() < pEnd->GetNode() )
1142 {
1143 bSaveOtherPos = true;
1144 }
1145 }
1146 else
1147 {
1148 // #i92125#
1149 // keep cross-reference bookmarks, if content inside one paragraph is deleted.
1150 if ( rMark.GetNode() == rPoint.GetNode()
1153 {
1154 continue;
1155 }
1156
1157 bool bMaybe = false;
1158 if ( *pStt <= pBkmk->GetMarkPos() && pBkmk->GetMarkPos() <= *pEnd )
1159 {
1160 if ( pBkmk->GetMarkPos() == *pEnd
1161 || ( *pStt == pBkmk->GetMarkPos() && pBkmk->IsExpanded() ) )
1162 bMaybe = true;
1163 else
1164 bSavePos = true;
1165 }
1166 if( pBkmk->IsExpanded() &&
1167 *pStt <= pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() <= *pEnd )
1168 {
1169 assert(!bSaveOtherPos);
1170 if ( bSavePos
1171 || (*pStt < pBkmk->GetOtherMarkPos() && pBkmk->GetOtherMarkPos() < *pEnd)
1172 || (bMaybe
1177 || (bMaybe
1178 && !(nDelContentType & DelContentType::Replace)
1180 && pStt->GetContentIndex() == 0 // entire paragraph deleted?
1181 && pEnd->GetContentIndex() == pEnd->GetNode().GetTextNode()->Len()))
1182 {
1183 if( bMaybe )
1184 bSavePos = true;
1185 bSaveOtherPos = true;
1186 }
1187 }
1188
1189 if ( !bSavePos && !bSaveOtherPos
1190 && dynamic_cast< const ::sw::mark::CrossRefBookmark* >(pBkmk) )
1191 {
1192 // certain special handling for cross-reference bookmarks
1193 const bool bDifferentTextNodesAtMarkAndPoint =
1194 rMark.GetNode() != rPoint.GetNode()
1195 && rMark.GetNode().GetTextNode()
1196 && rPoint.GetNode().GetTextNode();
1197 if ( bDifferentTextNodesAtMarkAndPoint )
1198 {
1199 // delete cross-reference bookmark at <pStt>, if only part of
1200 // <pEnd> text node content is deleted.
1201 if( pStt->GetNode() == pBkmk->GetMarkPos().GetNode()
1202 && pEnd->GetContentIndex() != pEnd->GetNode().GetTextNode()->Len() )
1203 {
1204 bSavePos = true;
1205 bSaveOtherPos = false; // cross-reference bookmarks are not expanded
1206 }
1207 // delete cross-reference bookmark at <pEnd>, if only part of
1208 // <pStt> text node content is deleted.
1209 else if( pEnd->GetNode() == pBkmk->GetMarkPos().GetNode() &&
1210 pStt->GetContentIndex() != 0 )
1211 {
1212 bSavePos = true;
1213 bSaveOtherPos = false; // cross-reference bookmarks are not expanded
1214 }
1215 }
1216 }
1218 {
1219 // delete annotation marks, if its end position is covered by the deletion
1220 const SwPosition& rAnnotationEndPos = pBkmk->GetMarkEnd();
1221 if ( *pStt < rAnnotationEndPos && rAnnotationEndPos <= *pEnd )
1222 {
1223 bSavePos = true;
1224 bSaveOtherPos = pBkmk->IsExpanded(); //tdf#90138, only save the other pos if there is one
1225 }
1226 }
1227 }
1228
1229 if ( bSavePos || bSaveOtherPos )
1230 {
1232 {
1233 if( !m_pHistory )
1234 m_pHistory.reset( new SwHistory );
1235 m_pHistory->Add( *pBkmk, bSavePos, bSaveOtherPos );
1236 }
1237 if ( bSavePos
1238 && ( bSaveOtherPos
1239 || !pBkmk->IsExpanded() ) )
1240 {
1241 pMarkAccess->deleteMark(pMarkAccess->getAllMarksBegin()+n, false);
1242 n--;
1243 }
1244 }
1245 }
1246}
1247
1248// save a complete section into UndoNodes array
1250 : m_nMoveLen( 0 ), m_nStartPos( NODE_OFFSET_MAX )
1251{
1252}
1253
1255{
1256 if (m_oMovedStart) // delete also the section from UndoNodes array
1257 {
1258 // SaveSection saves the content in the PostIt section.
1259 SwNodes& rUNds = m_oMovedStart->GetNode().GetNodes();
1260 // cid#1486004 Uncaught exception
1262
1263 m_oMovedStart.reset();
1264 }
1265 m_pRedlineSaveData.reset();
1266}
1267
1269{
1270 SwNodeRange aRg( rSttIdx.GetNode(), *rSttIdx.GetNode().EndOfSectionNode() );
1271 SaveSection( aRg );
1272}
1273
1275 const SwNodeRange& rRange, bool const bExpandNodes)
1276{
1277 SwPaM aPam( rRange.aStart, rRange.aEnd );
1278
1279 // delete all footnotes, fly frames, bookmarks
1280 DelContentIndex( *aPam.GetMark(), *aPam.GetPoint() );
1281
1282 // redlines *before* CorrAbs, because DelBookmarks will make them 0-length
1283 // but *after* DelContentIndex because that also may use FillSaveData (in
1284 // flys) and that will be restored *after* this one...
1287 {
1288 m_pRedlineSaveData.reset();
1289 }
1290
1291 {
1292 // move certain indexes out of deleted range
1293 SwNodeIndex aSttIdx( aPam.Start()->GetNode() );
1294 SwNodeIndex aEndIdx( aPam.End()->GetNode() );
1295 SwNodeIndex aMvStt( aEndIdx, 1 );
1296 SwDoc::CorrAbs( aSttIdx, aEndIdx, SwPosition( aMvStt ), true );
1297 }
1298
1299 m_nStartPos = rRange.aStart.GetIndex();
1300
1301 if (bExpandNodes)
1302 {
1303 aPam.GetPoint()->Adjust(SwNodeOffset(-1));
1304 aPam.GetMark()->Adjust(SwNodeOffset(+1));
1305 }
1306
1307 SwContentNode* pCNd = aPam.GetMarkContentNode();
1308 if( pCNd )
1309 aPam.GetMark()->SetContent( 0 );
1310 pCNd = aPam.GetPointContentNode();
1311 if( nullptr != pCNd )
1312 aPam.GetPoint()->SetContent( pCNd->Len() );
1313
1314 // Keep positions as SwContentIndex so that this section can be deleted in DTOR
1315 SwNodeOffset nEnd;
1316 m_oMovedStart = rRange.aStart;
1317 MoveToUndoNds(aPam, &*m_oMovedStart, &nEnd);
1318 m_nMoveLen = nEnd - m_oMovedStart->GetIndex() + 1;
1319}
1320
1322 sal_uInt16 nSectType )
1323{
1324 if( NODE_OFFSET_MAX == m_nStartPos ) // was there any content?
1325 return;
1326
1327 // check if the content is at the old position
1328 SwNodeIndex aSttIdx( pDoc->GetNodes(), m_nStartPos );
1329
1330 // move the content from UndoNodes array into Fly
1331 SwStartNode* pSttNd = SwNodes::MakeEmptySection( aSttIdx.GetNode(),
1332 static_cast<SwStartNodeType>(nSectType) );
1333
1334 RestoreSection( pDoc, *pSttNd->EndOfSectionNode() );
1335
1336 if( pIdx )
1337 *pIdx = *pSttNd;
1338}
1339
1341 SwDoc *const pDoc, const SwNode& rInsPos, bool bForceCreateFrames)
1342{
1343 if( NODE_OFFSET_MAX == m_nStartPos ) // was there any content?
1344 return;
1345
1346 SwPosition aInsPos( rInsPos );
1347 SwNodeOffset nEnd = m_oMovedStart->GetIndex() + m_nMoveLen - 1;
1348 MoveFromUndoNds(*pDoc, m_oMovedStart->GetIndex(), aInsPos, &nEnd, bForceCreateFrames);
1349
1350 // destroy indices again, content was deleted from UndoNodes array
1351 m_oMovedStart.reset();
1353
1354 if( m_pRedlineSaveData )
1355 {
1357 m_pRedlineSaveData.reset();
1358 }
1359}
1360
1362{
1364}
1365
1366// save and set the RedlineData
1368 SwComparePosition eCmpPos,
1369 const SwPosition& rSttPos,
1370 const SwPosition& rEndPos,
1371 SwRangeRedline& rRedl,
1372 bool bCopyNext )
1373 : SwUndRng( rRedl )
1374 , SwRedlineData( rRedl.GetRedlineData(), bCopyNext )
1375{
1376 assert( SwComparePosition::Outside == eCmpPos ||
1377 !rRedl.GetContentIdx() ); // "Redline with Content"
1378
1379 switch (eCmpPos)
1380 {
1381 case SwComparePosition::OverlapBefore: // Pos1 overlaps Pos2 at the beginning
1382 m_nEndNode = rEndPos.GetNodeIndex();
1383 m_nEndContent = rEndPos.GetContentIndex();
1384 break;
1385
1386 case SwComparePosition::OverlapBehind: // Pos1 overlaps Pos2 at the end
1387 m_nSttNode = rSttPos.GetNodeIndex();
1388 m_nSttContent = rSttPos.GetContentIndex();
1389 break;
1390
1391 case SwComparePosition::Inside: // Pos1 lays completely in Pos2
1392 m_nSttNode = rSttPos.GetNodeIndex();
1393 m_nSttContent = rSttPos.GetContentIndex();
1394 m_nEndNode = rEndPos.GetNodeIndex();
1395 m_nEndContent = rEndPos.GetContentIndex();
1396 break;
1397
1398 case SwComparePosition::Outside: // Pos2 lays completely in Pos1
1399 if ( rRedl.GetContentIdx() )
1400 {
1401 // than move section into UndoArray and memorize it
1402 SaveSection( *rRedl.GetContentIdx() );
1403 rRedl.ClearContentIdx();
1404 }
1405 break;
1406
1407 case SwComparePosition::Equal: // Pos1 is exactly as big as Pos2
1408 break;
1409
1410 default:
1411 assert(false);
1412 }
1413
1414#if OSL_DEBUG_LEVEL > 0
1416 m_bRedlineMoved = rRedl.IsMoved();
1417#endif
1418}
1419
1421{
1422}
1423
1425{
1426 SwDoc& rDoc = rPam.GetDoc();
1427 SwRangeRedline* pRedl = new SwRangeRedline( *this, rPam );
1428
1429 if( GetMvSttIdx() )
1430 {
1431 SwNodeIndex aIdx( rDoc.GetNodes() );
1432 RestoreSection( &rDoc, &aIdx, SwNormalStartNode );
1433 if( GetHistory() )
1434 GetHistory()->Rollback( &rDoc );
1435 pRedl->SetContentIdx( aIdx );
1436 }
1437 SetPaM( *pRedl );
1438 // First, delete the "old" so that in an Append no unexpected things will
1439 // happen, e.g. a delete in an insert. In the latter case the just restored
1440 // content will be deleted and not the one you originally wanted.
1441 rDoc.getIDocumentRedlineAccess().DeleteRedline( *pRedl, false, RedlineType::Any );
1442
1445 //#i92154# let UI know about a new redline with comment
1446 if (rDoc.GetDocShell() && (!pRedl->GetComment().isEmpty()) )
1447 rDoc.GetDocShell()->Broadcast(SwRedlineHint());
1448
1449 auto const result(rDoc.getIDocumentRedlineAccess().AppendRedline(pRedl, true));
1450 assert(result != IDocumentRedlineAccess::AppendResult::IGNORED); // SwRedlineSaveData::RedlineToDoc: insert redline failed
1451 (void) result; // unused in non-debug
1453}
1454
1456 const SwPaM& rRange,
1457 SwRedlineSaveDatas& rSData,
1458 bool bDelRange,
1459 bool bCopyNext )
1460{
1461 rSData.clear();
1462
1463 auto [pStt, pEnd] = rRange.StartEnd(); // SwPosition*
1466 rRange.GetDoc().getIDocumentRedlineAccess().GetRedline( *pStt, &n );
1467 for ( ; n < rTable.size(); ++n )
1468 {
1469 SwRangeRedline* pRedl = rTable[n];
1470
1471 const SwComparePosition eCmpPos =
1472 ComparePosition( *pStt, *pEnd, *pRedl->Start(), *pRedl->End() );
1473 if ( eCmpPos != SwComparePosition::Before
1474 && eCmpPos != SwComparePosition::Behind
1475 && eCmpPos != SwComparePosition::CollideEnd
1476 && eCmpPos != SwComparePosition::CollideStart )
1477 {
1478
1479 rSData.push_back(std::unique_ptr<SwRedlineSaveData>(new SwRedlineSaveData(eCmpPos, *pStt, *pEnd, *pRedl, bCopyNext)));
1480 }
1481 }
1482 if( !rSData.empty() && bDelRange )
1483 {
1484 rRange.GetDoc().getIDocumentRedlineAccess().DeleteRedline( rRange, false, RedlineType::Any );
1485 }
1486 return !rSData.empty();
1487}
1488
1490 const SwPaM& rRange,
1491 SwRedlineSaveDatas& rSData )
1492{
1493 rSData.clear();
1494
1495 const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
1498 rRange.GetDoc().getIDocumentRedlineAccess().GetRedline( *pStt, &n );
1499 for ( ; n < rTable.size(); ++n )
1500 {
1501 SwRangeRedline* pRedl = rTable[n];
1502 if ( RedlineType::Format == pRedl->GetType() )
1503 {
1504 const SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRedl->Start(), *pRedl->End() );
1505 if ( eCmpPos != SwComparePosition::Before
1506 && eCmpPos != SwComparePosition::Behind
1507 && eCmpPos != SwComparePosition::CollideEnd
1508 && eCmpPos != SwComparePosition::CollideStart )
1509 {
1510 rSData.push_back(std::unique_ptr<SwRedlineSaveData>(new SwRedlineSaveData(eCmpPos, *pStt, *pEnd, *pRedl, true)));
1511 }
1512
1513 }
1514 }
1515 return !rSData.empty();
1516}
1517
1518
1520{
1523 SwPaM aPam( rDoc.GetNodes().GetEndOfContent() );
1524
1525 for( size_t n = rSData.size(); n; )
1526 rSData[ --n ].RedlineToDoc( aPam );
1527
1528#if OSL_DEBUG_LEVEL > 0
1529 // check redline count against count saved in RedlineSaveData object
1530 // except in the case of moved redlines
1531 assert(rSData.empty() || rSData[0].m_bRedlineMoved ||
1532 (rSData[0].m_nRedlineCount == rDoc.getIDocumentRedlineAccess().GetRedlineTable().size()));
1533 // "redline count not restored properly"
1534#endif
1535
1537}
1538
1540{
1541 for( size_t n = rSData.size(); n; )
1542 if( rSData[ --n ].GetMvSttIdx() )
1543 return true;
1544 return false;
1545}
1546
1548 const SwRedlineSaveDatas& rCheck, bool bCurrIsEnd )
1549{
1550 if( rCurr.size() != rCheck.size() )
1551 return false;
1552
1553 for( size_t n = 0; n < rCurr.size(); ++n )
1554 {
1555 const SwRedlineSaveData& rSet = rCurr[ n ];
1556 const SwRedlineSaveData& rGet = rCheck[ n ];
1557 if( rSet.m_nSttNode != rGet.m_nSttNode ||
1558 rSet.GetMvSttIdx() || rGet.GetMvSttIdx() ||
1559 ( bCurrIsEnd ? rSet.m_nSttContent != rGet.m_nEndContent
1560 : rSet.m_nEndContent != rGet.m_nSttContent ) ||
1561 !rGet.CanCombine( rSet ) )
1562 {
1563 return false;
1564 }
1565 }
1566
1567 for( size_t n = 0; n < rCurr.size(); ++n )
1568 {
1569 SwRedlineSaveData& rSet = rCurr[ n ];
1570 const SwRedlineSaveData& rGet = rCheck[ n ];
1571 if( bCurrIsEnd )
1572 rSet.m_nSttContent = rGet.m_nSttContent;
1573 else
1574 rSet.m_nEndContent = rGet.m_nEndContent;
1575 }
1576 return true;
1577}
1578
1579OUString ShortenString(const OUString & rStr, sal_Int32 nLength, std::u16string_view aFillStr)
1580{
1581 assert(nLength - aFillStr.size() >= 2);
1582
1583 if (rStr.getLength() <= nLength)
1584 return rStr;
1585
1586 nLength -= aFillStr.size();
1587 if ( nLength < 2 )
1588 nLength = 2;
1589
1590 const sal_Int32 nFrontLen = nLength - nLength / 2;
1591 const sal_Int32 nBackLen = nLength - nFrontLen;
1592
1593 return OUString::Concat(rStr.subView(0, nFrontLen))
1594 + aFillStr
1595 + rStr.subView(rStr.getLength() - nBackLen);
1596}
1597
1598static bool IsAtEndOfSection(SwPosition const& rAnchorPos)
1599{
1600 SwNodeIndex node(*rAnchorPos.GetNode().EndOfSectionNode());
1601 SwContentNode *const pNode(SwNodes::GoPrevious(&node));
1602 assert(pNode);
1603 assert(rAnchorPos.GetNode() <= node.GetNode()); // last valid anchor pos is last content
1604 return node == rAnchorPos.GetNode()
1605 // at-para fly has no SwContentIndex!
1606 && (rAnchorPos.GetContentIndex() == pNode->Len() || rAnchorPos.GetContentNode() == nullptr);
1607}
1608
1609static bool IsAtStartOfSection(SwPosition const& rAnchorPos)
1610{
1611 SwNodes const& rNodes(rAnchorPos.GetNodes());
1612 SwNodeIndex node(*rAnchorPos.GetNode().StartOfSectionNode());
1613 SwContentNode *const pNode(rNodes.GoNext(&node));
1614 assert(pNode);
1615 (void) pNode;
1616 assert(node <= rAnchorPos.GetNode());
1617 return node == rAnchorPos.GetNode() && rAnchorPos.GetContentIndex() == 0;
1618}
1619
1621static bool IsAtEndOfSection2(SwPosition const& rPos)
1622{
1623 return rPos.GetNode().IsEndNode()
1624 || IsAtEndOfSection(rPos);
1625}
1626
1627static bool IsAtStartOfSection2(SwPosition const& rPos)
1628{
1629 return rPos.GetNode().IsStartNode()
1630 || IsAtStartOfSection(rPos);
1631}
1632
1634 SwPosition const& rStart, SwPosition const& rEnd)
1635{
1636 // check if the selection is backspace/delete created by DelLeft/DelRight
1637 if (rStart.GetNodeIndex() + 1 != rEnd.GetNodeIndex())
1638 return true;
1639 if (rEnd.GetContentIndex() != 0)
1640 return true;
1641 const SwTextNode* pTextNode = rStart.GetNode().GetTextNode();
1642 if (!pTextNode || rStart.GetContentIndex() != pTextNode->Len())
1643 return true;
1644 return false;
1645}
1646
1648 SwPosition const & rStart, SwPosition const & rEnd,
1649 DelContentType const nDelContentType)
1650{
1651 assert(rStart <= rEnd);
1652
1653 // CheckNoCntnt means DelFullPara which is obvious to handle
1654 if (DelContentType::CheckNoCntnt & nDelContentType)
1655 { // exclude selection end node because it won't be deleted
1656 return (rAnchorPos.GetNode() < rEnd.GetNode())
1657 && (rStart.GetNode() <= rAnchorPos.GetNode());
1658 }
1659
1660 if ((nDelContentType & DelContentType::WriterfilterHack)
1661 && rAnchorPos.GetDoc().IsInWriterfilterImport())
1662 { // FIXME hack for writerfilter RemoveLastParagraph() and MakeFlyAndMove(); can't test file format more specific?
1663 return (rStart < rAnchorPos) && (rAnchorPos < rEnd);
1664 }
1665
1666 if (nDelContentType & DelContentType::ExcludeFlyAtStartEnd)
1667 { // exclude selection start and end node
1668 return (rAnchorPos.GetNode() < rEnd.GetNode())
1669 && (rStart.GetNode() < rAnchorPos.GetNode());
1670 }
1671
1672 // in general, exclude the start and end position
1673 return ((rStart < rAnchorPos)
1674 || (rStart == rAnchorPos
1675 // special case: fully deleted node
1676 && ((rStart.GetNode() != rEnd.GetNode() && rStart.GetContentIndex() == 0
1677 // but not if the selection is backspace/delete!
1678 && IsNotBackspaceHeuristic(rStart, rEnd))
1679 || (IsAtStartOfSection(rAnchorPos) && IsAtEndOfSection2(rEnd)))))
1680 && ((rAnchorPos < rEnd)
1681 || (rAnchorPos == rEnd
1682 // special case: fully deleted node
1683 && ((rEnd.GetNode() != rStart.GetNode() && rEnd.GetContentIndex() == rEnd.GetNode().GetTextNode()->Len()
1684 && IsNotBackspaceHeuristic(rStart, rEnd))
1685 || (IsAtEndOfSection(rAnchorPos) && IsAtStartOfSection2(rStart)))));
1686}
1687
1689 SwPosition const & rStart, SwPosition const & rEnd,
1690 DelContentType const nDelContentType)
1691{
1692 assert(rStart <= rEnd);
1693
1694 // CheckNoCntnt means DelFullPara which is obvious to handle
1695 if (DelContentType::CheckNoCntnt & nDelContentType)
1696 { // exclude selection end node because it won't be deleted
1697 return (rAnchorPos.GetNode() < rEnd.GetNode())
1698 && (rStart.GetNode() <= rAnchorPos.GetNode());
1699 }
1700
1701 if ((nDelContentType & DelContentType::WriterfilterHack)
1702 && rAnchorPos.GetDoc().IsInWriterfilterImport())
1703 { // FIXME hack for writerfilter RemoveLastParagraph() and MakeFlyAndMove(); can't test file format more specific?
1704 // but it MUST NOT be done during the SetRedlineFlags at the end of ODF
1705 // import, where the IsInXMLImport() cannot be checked because the
1706 // stupid code temp. overrides it - instead rely on setting the ALLFLYS
1707 // flag in MoveFromSection() and converting that to CheckNoCntnt with
1708 // adjusted cursor!
1709 return (rStart.GetNode() < rAnchorPos.GetNode()) && (rAnchorPos.GetNode() < rEnd.GetNode());
1710 }
1711
1712 // in general, exclude the start and end position
1713 return ((rStart.GetNode() < rAnchorPos.GetNode())
1714 || (rStart.GetNode() == rAnchorPos.GetNode()
1715 && !(nDelContentType & DelContentType::ExcludeFlyAtStartEnd)
1716 // special case: fully deleted node
1717 && ((rStart.GetNode() != rEnd.GetNode() && rStart.GetContentIndex() == 0
1718 // but not if the selection is backspace/delete!
1719 && IsNotBackspaceHeuristic(rStart, rEnd))
1720 || (IsAtStartOfSection2(rStart) && IsAtEndOfSection2(rEnd)))))
1721 && ((rAnchorPos.GetNode() < rEnd.GetNode())
1722 || (rAnchorPos.GetNode() == rEnd.GetNode()
1723 && !(nDelContentType & DelContentType::ExcludeFlyAtStartEnd)
1724 // special case: fully deleted node
1725 && ((rEnd.GetNode() != rStart.GetNode() && rEnd.GetContentIndex() == rEnd.GetNode().GetTextNode()->Len()
1726 && IsNotBackspaceHeuristic(rStart, rEnd))
1727 || (IsAtEndOfSection2(rEnd) && IsAtStartOfSection2(rStart)))));
1728}
1729
1731 SwPosition const & rStart, SwPosition const & rEnd)
1732{
1733 for (SwFrameFormat const*const pFly : *rDoc.GetSpzFrameFormats())
1734 {
1735 SwFormatAnchor const& rAnchor(pFly->GetAnchor());
1736 switch (rAnchor.GetAnchorId())
1737 {
1738 case RndStdIds::FLY_AT_CHAR:
1739 case RndStdIds::FLY_AT_PARA:
1740 {
1741 SwPosition const*const pAnchorPos(rAnchor.GetContentAnchor());
1742 // can this really be null?
1743 if (pAnchorPos != nullptr
1744 && ((rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
1745 ? IsDestroyFrameAnchoredAtChar(*pAnchorPos, rStart, rEnd)
1746 : IsSelectFrameAnchoredAtPara(*pAnchorPos, rStart, rEnd)))
1747 {
1748 return true;
1749 }
1750 }
1751 break;
1752 default: // other types not relevant
1753 break;
1754 }
1755 }
1756 return false;
1757}
1758
1759/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ On
RedlineFlags on.
@ Ignore
ignore Redlines
Provides access to the marks of a document.
virtual sal_Int32 getAllMarksCount() const =0
returns the number of marks.
virtual std::unique_ptr< ILazyDeleter > deleteMark(const IDocumentMarkAccess::const_iterator_t &ppMark, bool isMoveNodes)=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.
static SW_DLLPUBLIC MarkType GetType(const ::sw::mark::IMark &rMark)
Returns the MarkType used to create the mark.
Definition: docbm.cxx:502
virtual bool DeleteRedline(const SwPaM &rPam, bool bSaveInUndo, RedlineType nDelType)=0
virtual void SetRedlineFlags_intern(RedlineFlags eMode)=0
Set a new redline mode.
virtual const SwRedlineTable & GetRedlineTable() const =0
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
virtual const SwRangeRedline * GetRedline(const SwPosition &rPos, SwRedlineTable::size_type *pFndPos) const =0
virtual RedlineFlags GetRedlineFlags() const =0
Query the currently set redline mode.
Marks a character position inside a document model content node (SwContentNode)
virtual sal_Int32 Len() const
Definition: node.cxx:1256
Definition: doc.hxx:197
void CorrAbs(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset=0, bool bMoveCursor=false)
Definition: doccorr.cxx:171
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:158
SwNodes & GetNodes()
Definition: doc.hxx:422
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:349
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:649
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1890
const sw::FrameFormats< sw::SpzFrameFormat * > * GetSpzFrameFormats() const
Definition: doc.hxx:759
SwDocShell * GetDocShell()
Definition: doc.hxx:1370
::sw::UndoManager & GetUndoManager()
Definition: doc.cxx:147
bool IsInWriterfilterImport() const
Definition: doc.hxx:987
SwTextFootnote * SeekEntry(const SwNode &rNd, size_t *pPos=nullptr) const
Definition: ftnidx.cxx:408
FlyAnchors.
Definition: fmtanchr.hxx:37
void SetAnchor(const SwPosition *pPos)
Definition: atrfrm.cxx:1593
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:67
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:74
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:88
virtual bool SetFormatAttr(const SfxPoolItem &rAttr)
Definition: format.cxx:447
Style of a layout element.
Definition: frmfmt.hxx:72
bool Rollback(SwDoc *pDoc, sal_uInt16 nStart=0)
Definition: rolbck.cxx:1202
Layout frame for SwNoTextNode, i.e. graphics and OLE nodes (including charts).
Definition: ndnotxt.hxx:30
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
SwNodeIndex aStart
Definition: ndindex.hxx:136
SwNodeIndex aEnd
Definition: ndindex.hxx:137
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwNodeOffset GetIndex() const
Definition: node.hxx:312
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:706
bool IsContentNode() const
Definition: node.hxx:188
SwDoc & GetDoc()
Definition: node.hxx:233
bool IsEndNode() const
Definition: node.hxx:189
bool IsStartNode() const
Definition: node.hxx:187
bool IsTextNode() const
Definition: node.hxx:190
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
SwNoTextNode * GetNoTextNode()
Definition: ndnotxt.hxx:95
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:695
void MoveRange(SwPaM &, SwPosition &, SwNodes &rNodes)
move a range
Definition: nodes.cxx:1470
SwNode & GetEndOfExtras() const
This is the last EndNode of a special section.
Definition: ndarr.hxx:163
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:165
bool MoveNodes(const SwNodeRange &, SwNodes &rNodes, SwNode &rPos, bool bNewFrames=true)
move the node pointer
Definition: nodes.cxx:404
void Delete(const SwNodeIndex &rPos, SwNodeOffset nNodes=SwNodeOffset(1))
Definition: nodes.cxx:1070
static SwStartNode * MakeEmptySection(SwNode &rWhere, SwStartNodeType=SwNormalStartNode)
Create an empty section of Start- and EndNote.
Definition: nodes.cxx:1917
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1333
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1299
SwNode & GetEndOfPostIts() const
A still empty section.
Definition: ndarr.hxx:154
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
SwNode & GetPointNode() const
Definition: pam.hxx:275
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:643
void Exchange()
Definition: pam.hxx:242
std::pair< const SwPosition *, const SwPosition * > StartEnd() const
Because sometimes the cost of the operator<= can add up.
Definition: pam.hxx:269
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:279
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:657
const SwPosition * End() const
Definition: pam.hxx:263
SwContentNode * GetMarkContentNode() const
Definition: pam.hxx:280
SwDoc & GetDoc() const
Definition: pam.hxx:291
void DeleteMark()
Definition: pam.hxx:232
const SwPosition * GetPoint() const
Definition: pam.hxx:253
const SwPosition * Start() const
Definition: pam.hxx:258
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
void ClearContentIdx()
Definition: docredln.cxx:1908
const OUString & GetComment(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1985
const SwNodeIndex * GetContentIdx() const
Definition: redline.hxx:195
bool IsMoved() const
Definition: redline.hxx:282
void SetContentIdx(const SwNodeIndex &)
Definition: docredln.cxx:1894
RedlineType GetType(sal_uInt16 nPos=0) const
Definition: docredln.cxx:1975
friend class SwRangeRedline
Definition: redline.hxx:88
bool CanCombine(const SwRedlineData &rCmp) const
Definition: docredln.cxx:1097
const SwNodeIndex * GetMvSttIdx() const
Definition: UndoCore.hxx:57
sal_uInt16 m_nRedlineCount
Definition: UndoCore.hxx:63
void RedlineToDoc(SwPaM const &rPam)
Definition: undobj.cxx:1424
SwRedlineSaveData(SwComparePosition eCmpPos, const SwPosition &rSttPos, const SwPosition &rEndPos, SwRangeRedline &rRedl, bool bCopyNext)
Definition: undobj.cxx:1367
bool empty() const
Definition: UndoCore.hxx:76
void push_back(std::unique_ptr< SwRedlineSaveData > pNew)
Definition: UndoCore.hxx:78
size_t size() const
Definition: UndoCore.hxx:77
size_type size() const
Definition: docary.hxx:268
vector_type::size_type size_type
Definition: docary.hxx:223
OUString Apply(const OUString &rStr) const
Definition: SwRewriter.cxx:39
Starts a section of nodes in the document model.
Definition: node.hxx:348
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
SwTextAttr subclass for footnotes and endnotes.
Definition: txtftn.hxx:34
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
void EraseText(const SwContentIndex &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:2777
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:3155
SwPaM & AddUndoRedoPaM(::sw::UndoRedoContext &, bool const bCorrToContent=false) const
Definition: undobj.cxx:100
void SetPaM(SwPaM &, bool bCorrToContent=false) const
Definition: undobj.cxx:80
SwUndRng()
Definition: undobj.cxx:50
sal_Int32 m_nSttContent
Definition: undobj.hxx:232
SwNodeOffset m_nSttNode
Definition: undobj.hxx:231
SwNodeOffset m_nEndNode
Definition: undobj.hxx:231
sal_Int32 m_nEndContent
Definition: undobj.hxx:232
void SetValues(const SwPaM &rPam)
Definition: undobj.cxx:60
static void MoveFromUndoNds(SwDoc &rDoc, SwNodeOffset nNodeIdx, SwPosition &rInsPos, const SwNodeOffset *pEndNdIdx=nullptr, bool bForceCreateFrames=false)
Definition: undobj.cxx:799
virtual ~SwUndoSaveContent() COVERITY_NOEXCEPT_FALSE
Definition: undobj.cxx:738
void DelContentIndex(const SwPosition &pMark, const SwPosition &pPoint, DelContentType nDelContentType=DelContentType::AllMask)
Definition: undobj.cxx:902
static void MoveToUndoNds(SwPaM &rPam, SwNodeIndex *pNodeIdx, SwNodeOffset *pEndNdIdx=nullptr)
Definition: undobj.cxx:763
std::unique_ptr< SwHistory > m_pHistory
Definition: undobj.hxx:167
static bool MovePtBackward(SwPaM &rPam)
Definition: undobj.cxx:867
static void MovePtForward(SwPaM &rPam, bool bMvBkwrd)
Definition: undobj.cxx:879
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: undobj.cxx:742
void SaveSection(const SwNodeIndex &rSttIdx)
Definition: undobj.cxx:1268
const SwHistory * GetHistory() const
Definition: undobj.hxx:221
virtual void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: undobj.cxx:1361
std::unique_ptr< SwRedlineSaveDatas > m_pRedlineSaveData
Definition: undobj.hxx:204
SwNodeOffset m_nStartPos
Definition: undobj.hxx:206
void RestoreSection(SwDoc *pDoc, SwNodeIndex *pIdx, sal_uInt16 nSectType)
Definition: undobj.cxx:1321
std::optional< SwNodeIndex > m_oMovedStart
Definition: undobj.hxx:203
SwNodeOffset m_nMoveLen
Definition: undobj.hxx:205
virtual SwRewriter GetRewriter() const
Returns the rewriter for this object.
Definition: undobj.cxx:728
std::optional< OUString > maComment
Definition: undobj.hxx:63
virtual void UndoImpl(::sw::UndoRedoContext &)=0
SwUndo(SwUndoId const nId, const SwDoc *pDoc)
Definition: undobj.cxx:151
virtual void Repeat(SfxRepeatTarget &) override
Definition: undobj.cxx:237
virtual void Redo() override
Definition: undobj.cxx:214
RedlineFlags GetRedlineFlags() const
Definition: undobj.hxx:120
ViewShellId GetViewShellId() const override
See SfxUndoAction::GetViewShellId().
Definition: undobj.cxx:723
virtual bool CanRepeat(SfxRepeatTarget &) const override
Definition: undobj.cxx:249
static bool FillSaveData(const SwPaM &rRange, SwRedlineSaveDatas &rSData, bool bDelRange=true, bool bCopyNext=true)
Definition: undobj.cxx:1455
virtual OUString GetComment() const override
Returns textual comment for this undo object.
Definition: undobj.cxx:694
static void RemoveIdxRel(SwNodeOffset, const SwPosition &)
Definition: undobj.cxx:144
static void RemoveIdxFromRange(SwPaM &rPam, bool bMoveNext)
Definition: undobj.cxx:118
virtual void UndoWithContext(SfxUndoContext &) override
Definition: undobj.cxx:219
bool IsDelBox() const
Definition: undobj.cxx:172
static bool HasHiddenRedlines(const SwRedlineSaveDatas &rSData)
Definition: undobj.cxx:1539
static void SetSaveData(SwDoc &rDoc, SwRedlineSaveDatas &rSData)
Definition: undobj.cxx:1519
static bool CanRedlineGroup(SwRedlineSaveDatas &rCurr, const SwRedlineSaveDatas &rCheck, bool bCurrIsEnd)
Definition: undobj.cxx:1547
SwUndoId GetId() const
Definition: undobj.hxx:102
virtual void RepeatImpl(::sw::RepeatContext &)
Definition: undobj.cxx:257
bool m_bCacheComment
Definition: undobj.hxx:62
static ViewShellId CreateViewShellId(const SwDoc *pDoc)
Try to obtain the view shell ID of the current view.
Definition: undobj.cxx:159
static bool FillSaveDataForFormat(const SwPaM &, SwRedlineSaveDatas &)
Definition: undobj.cxx:1489
virtual void RedoImpl(::sw::UndoRedoContext &)=0
static void RemoveIdxFromSection(SwDoc &, SwNodeOffset nSttIdx, const SwNodeOffset *pEndIdx=nullptr)
Definition: undobj.cxx:108
virtual void Undo() override
Definition: undobj.cxx:209
bool m_isRepeatIgnored
for multi-selection, only repeat 1st selection
Definition: undobj.hxx:59
ViewShellId m_nViewShellId
Definition: undobj.hxx:58
virtual void RedoWithContext(SfxUndoContext &) override
Definition: undobj.cxx:228
virtual ~SwUndo() override
Definition: undobj.cxx:178
Definition: view.hxx:146
bool empty() const
size_type size() const
bool empty() const
size_t size() const
virtual SwCursor & CreateNewShellCursor()=0
SwNodes const & GetUndoNodes() const
Definition: docundo.cxx:79
IShellCursorSupplier & GetCursorSupplier()
Definition: UndoCore.hxx:97
struct _xmlTextWriter * xmlTextWriterPtr
#define suppress_fun_call_w_exception(expr)
void PaMCorrRel(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset)
Sets all PaMs in OldNode to relative Pos.
Definition: doccorr.cxx:244
sal_Int64 n
sal_uInt16 nPos
#define SAL_INFO(area, stream)
SwStartNodeType
Definition: ndtyp.hxx:51
@ SwNormalStartNode
Definition: ndtyp.hxx:52
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
constexpr SwNodeOffset NODE_OFFSET_MAX(SAL_MAX_INT32)
sal_Int16 nId
bool GoInContent(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1203
SwComparePosition ComparePosition(const T &rStt1, const T &rEnd1, const T &rStt2, const T &rEnd2)
Definition: pam.hxx:123
SwComparePosition
Definition: pam.hxx:110
@ OverlapBehind
Pos1 overlaps Pos2 at the end.
@ CollideEnd
Pos1 end touches at Pos2 start.
@ Behind
Pos1 behind Pos2.
@ OverlapBefore
Pos1 overlaps Pos2 at the beginning.
@ Outside
Pos2 completely contained in Pos1.
@ Before
Pos1 before Pos2.
@ Inside
Pos1 completely contained in Pos2.
@ CollideStart
Pos1 start touches at Pos2 end.
@ Equal
Pos1 is as large as Pos2.
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:60
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:61
static SfxItemSet & rSet
Marks a position in the document model.
Definition: pam.hxx:38
void Adjust(SwNodeOffset nDelta)
Adjust node position, and resets content position to zero.
Definition: pam.cxx:257
SwNode & GetNode() const
Definition: pam.hxx:81
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:231
void SetContent(sal_Int32 nContentIndex)
Set content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:267
const SwContentNode * GetContentNode() const
Definition: pam.hxx:84
SwNodeOffset GetNodeIndex() const
Definition: pam.hxx:78
const SwNodes & GetNodes() const
Definition: pam.hxx:79
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
SwDoc & GetDoc() const
Returns the document this position is in.
Definition: pam.cxx:218
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:57
SwUndoId
Definition: swundo.hxx:30
@ UI_TABLE_DELETE
@ INDEX_ENTRY_INSERT
@ NUMRULE_RENAME
@ UI_INSERT_CHART
@ UPDATE_FORM_FIELD
@ NUMRULE_CREATE
@ PASTE_CLIPBOARD
@ FLYFRMFMT_TITLE
@ INSERT_PAGE_NUMBER
@ TBLSTYLE_UPDATE
@ UI_INSERT_FOOTNOTE
@ UI_DELETE_PAGE_BREAK
@ CHARFMT_CREATE
@ DELETE_SECTIONS
@ INSERT_FORM_FIELD
@ UPDATE_BOOKMARK
@ UI_REPLACE_STYLE
@ FLYFRMFMT_DECORATIVE
@ CREATE_PAGEDESC
@ DELETE_PAGEDESC
@ INS_FROM_SHADOWCRSR
@ UPDATE_BOOKMARKS
@ REJECT_REDLINE
@ UPDATE_SECTIONS
@ TXTFMTCOL_CREATE
@ UPDATE_FORM_FIELDS
@ UI_INSERT_URLBTN
@ INC_LEFTMARGIN
@ RENAME_PAGEDESC
@ UI_TEXT_CORRECTION
@ UI_INSERT_ENVELOPE
@ CHARFMT_RENAME
@ TXTFMTCOL_DELETE
@ FLYFRMFMT_DESCRIPTION
@ NUMRULE_DELETE
@ DELETE_BOOKMARKS
@ DELETE_FORM_FIELDS
@ UI_INSERT_COLUMN_BREAK
@ BOOKMARK_RENAME
@ ACCEPT_REDLINE
@ UI_INSERT_URLTXT
@ TXTFMTCOL_RENAME
@ TBLSTYLE_CREATE
@ DEC_LEFTMARGIN
@ UI_INSERT_PAGE_BREAK
@ TBLSTYLE_DELETE
@ INDEX_ENTRY_DELETE
@ CHARFMT_DELETE
@ CHANGE_PAGEDESC
@ UI_DELETE_INVISIBLECNTNT
@ UI_DRAG_AND_COPY
@ UI_DRAG_AND_MOVE
@ SETNUMRULESTART
Any result
ResultType type
OUString ShortenString(const OUString &rStr, sal_Int32 nLength, std::u16string_view aFillStr)
Shortens a string to a maximum length.
Definition: undobj.cxx:1579
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:1688
static bool IsAtEndOfSection2(SwPosition const &rPos)
passed start / end position could be on section start / end node
Definition: undobj.cxx:1621
static bool IsAtStartOfSection(SwPosition const &rAnchorPos)
Definition: undobj.cxx:1609
static bool IsNotBackspaceHeuristic(SwPosition const &rStart, SwPosition const &rEnd)
Definition: undobj.cxx:1633
bool IsFlySelectedByCursor(SwDoc const &rDoc, SwPosition const &rStart, SwPosition const &rEnd)
check at-char and at-para flys in rDoc
Definition: undobj.cxx:1730
static bool IsAtStartOfSection2(SwPosition const &rPos)
Definition: undobj.cxx:1627
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:1647
OUString GetUndoComment(SwUndoId eId)
Definition: undobj.cxx:261
static bool IsAtEndOfSection(SwPosition const &rAnchorPos)
Definition: undobj.cxx:1598
DelContentType
Definition: undobj.hxx:135
sal_Int32 nLength