1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
24 #include <UndoAttribute.hxx>
25 #include <svl/itemiter.hxx>
26 #include <editeng/tstpitem.hxx>
27 #include <svx/svdobj.hxx>
28 #include <osl/diagnose.h>
29 #include <hintids.hxx>
30 #include <fmtflcnt.hxx>
32 #include <fmtanchr.hxx>
33 #include <fmtfsize.hxx>
35 #include <fmtcntnt.hxx>
38 #include <IDocumentLayoutAccess.hxx>
39 #include <IDocumentRedlineAccess.hxx>
40 #include <IDocumentState.hxx>
41 #include <IDocumentUndoRedo.hxx>
42 #include <IShellCursorSupplier.hxx>
48 #include <swtable.hxx>
49 #include <swtblfmt.hxx>
50 #include <UndoCore.hxx>
53 #include <ndnotxt.hxx>
54 #include <ftninfo.hxx>
55 #include <redline.hxx>
56 #include <section.hxx>
57 #include <charfmt.hxx>
59 #include <frameformats.hxx>
62 SwUndoFormatAttrHelper::SwUndoFormatAttrHelper(SwFormat
& rFormat
, bool bSvDrwPt
)
65 , m_bSaveDrawPt(bSvDrwPt
)
69 void SwUndoFormatAttrHelper::SwClientNotify(const SwModify
&, const SfxHint
& rHint
)
71 if (rHint
.GetId() != SfxHintId::SwLegacyModify
)
73 auto pLegacy
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
76 assert(pLegacy
->m_pOld
->Which() != RES_OBJECTDYING
);
79 const SwDoc
& rDoc
= *m_rFormat
.GetDoc();
80 auto pOld
= pLegacy
->m_pOld
;
81 if(POOLATTR_END
>= pLegacy
->m_pOld
->Which()) {
83 m_pUndo
.reset(new SwUndoFormatAttr(*pOld
, m_rFormat
, m_bSaveDrawPt
));
85 m_pUndo
->PutAttr(*pOld
, rDoc
);
86 } else if(RES_ATTRSET_CHG
== pOld
->Which()) {
87 auto& rChgSet
= *static_cast<const SwAttrSetChg
*>(pOld
)->GetChgSet();
89 m_pUndo
.reset(new SwUndoFormatAttr(SfxItemSet(rChgSet
), m_rFormat
, m_bSaveDrawPt
));
91 SfxItemIter
aIter(rChgSet
);
92 for(auto pItem
= aIter
.GetCurItem(); pItem
; pItem
= aIter
.NextItem())
93 m_pUndo
->PutAttr(*pItem
, rDoc
);
98 SwDocModifyAndUndoGuard::SwDocModifyAndUndoGuard(SwFormat
& format
)
99 : doc(format
.GetName().isEmpty() ? nullptr : format
.GetDoc())
100 , helper(doc
? new SwUndoFormatAttrHelper(format
) : nullptr)
104 SwDocModifyAndUndoGuard::~SwDocModifyAndUndoGuard()
106 if (helper
&& helper
->GetUndo())
108 // helper tracks changes, even when DoesUndo is false, to detect modified state
109 if (doc
->GetIDocumentUndoRedo().DoesUndo())
110 doc
->GetIDocumentUndoRedo().AppendUndo(helper
->ReleaseUndo());
112 doc
->getIDocumentState().SetModified();
116 SwUndoFormatAttr::SwUndoFormatAttr( SfxItemSet
&& rOldSet
,
117 SwFormat
& rChgFormat
,
119 : SwUndo( SwUndoId::INSFMTATTR
, rChgFormat
.GetDoc() )
120 , m_sFormatName ( rChgFormat
.GetName() )
122 , m_oOldSet( std::move( rOldSet
) )
123 , m_nAnchorContentOffset( 0 )
125 , m_nFormatWhich( rChgFormat
.Which() )
126 , m_bSaveDrawPt( bSaveDrawPt
)
128 assert(m_sFormatName
.getLength());
133 SwUndoFormatAttr::SwUndoFormatAttr( const SfxPoolItem
& rItem
, SwFormat
& rChgFormat
,
135 : SwUndo( SwUndoId::INSFMTATTR
, rChgFormat
.GetDoc() )
136 , m_sFormatName(rChgFormat
.GetName())
137 , m_oOldSet( rChgFormat
.GetAttrSet().CloneAsValue( false ) )
138 , m_nAnchorContentOffset( 0 )
140 , m_nFormatWhich( rChgFormat
.Which() )
141 , m_bSaveDrawPt( bSaveDrawPt
)
143 assert(m_sFormatName
.getLength());
145 m_oOldSet
->Put( rItem
);
149 void SwUndoFormatAttr::Init( const SwFormat
& rFormat
)
151 // tdf#126017 never save SwNodeIndex, it will go stale
152 m_oOldSet
->ClearItem(RES_CNTNT
);
153 // treat change of anchor specially
154 if ( SfxItemState::SET
== m_oOldSet
->GetItemState( RES_ANCHOR
, false )) {
155 SaveFlyAnchor( &rFormat
, m_bSaveDrawPt
);
156 } else if ( RES_FRMFMT
== m_nFormatWhich
) {
157 const SwDoc
* pDoc
= rFormat
.GetDoc();
158 auto pTableFormat
= dynamic_cast<const SwTableFormat
*>(&rFormat
);
159 if (pTableFormat
&& pDoc
->GetTableFrameFormats()->ContainsFormat(const_cast<SwTableFormat
*>(pTableFormat
)))
161 // Table Format: save table position, table formats are volatile!
162 SwTable
* pTable
= SwIterator
<SwTable
,SwFormat
>( rFormat
).First();
164 m_nNodeIndex
= pTable
->GetTabSortBoxes()[ 0 ]->GetSttNd()
165 ->FindTableNode()->GetIndex();
167 } else if (dynamic_cast<const SwSectionFormat
*>(&rFormat
)) {
168 if (auto pContentIndex
= rFormat
.GetContent().GetContentIdx())
169 m_nNodeIndex
= pContentIndex
->GetIndex();
170 } else if(auto pBoxFormat
= dynamic_cast<const SwTableBoxFormat
*>(&rFormat
))
172 auto pTableBox
= pBoxFormat
->GetTableBox();
174 m_nNodeIndex
= pTableBox
->GetSttIdx();
179 SwUndoFormatAttr::~SwUndoFormatAttr()
183 void SwUndoFormatAttr::UndoImpl(::sw::UndoRedoContext
& rContext
)
185 // OD 2004-10-26 #i35443#
186 // Important note: <Undo(..)> also called by <ReDo(..)>
191 SwFormat
* pFormat
= GetFormat(rContext
.GetDoc());
195 // #i35443# - If anchor attribute has been successful
196 // restored, all other attributes are also restored.
197 // Thus, keep track of its restoration
198 bool bAnchorAttrRestored( false );
199 if ( SfxItemState::SET
== m_oOldSet
->GetItemState( RES_ANCHOR
, false )) {
200 bAnchorAttrRestored
= RestoreFlyAnchor(rContext
);
201 if ( bAnchorAttrRestored
) {
202 // Anchor attribute successful restored.
203 // Thus, keep anchor position for redo
204 SaveFlyAnchor(pFormat
);
206 // Anchor attribute not restored due to invalid anchor position.
207 // Thus, delete anchor attribute.
208 m_oOldSet
->ClearItem( RES_ANCHOR
);
212 if ( bAnchorAttrRestored
) return;
214 SwUndoFormatAttrHelper
aTmp( *pFormat
, m_bSaveDrawPt
);
215 pFormat
->SetFormatAttr( *m_oOldSet
);
216 if ( aTmp
.GetUndo() ) {
217 // transfer ownership of helper object's old set
218 if (aTmp
.GetUndo()->m_oOldSet
)
219 m_oOldSet
.emplace(std::move(*aTmp
.GetUndo()->m_oOldSet
));
223 m_oOldSet
->ClearItem();
226 if ( RES_FLYFRMFMT
== m_nFormatWhich
|| RES_DRAWFRMFMT
== m_nFormatWhich
) {
227 rContext
.SetSelections(static_cast<SwFrameFormat
*>(pFormat
), nullptr);
231 // Check if it is still in Doc
232 SwFormat
* SwUndoFormatAttr::GetFormat( const SwDoc
& rDoc
)
234 switch (m_nFormatWhich
)
237 case RES_CONDTXTFMTCOLL
:
238 return rDoc
.FindTextFormatCollByName(m_sFormatName
);
241 return rDoc
.GetGrfFormatColls()->FindFormatByName(m_sFormatName
);
244 return rDoc
.FindCharFormatByName(m_sFormatName
);
247 if (m_nNodeIndex
&& (m_nNodeIndex
< rDoc
.GetNodes().Count()))
249 SwNode
* pNd
= rDoc
.GetNodes()[m_nNodeIndex
];
250 if (pNd
->IsTableNode())
252 return static_cast<SwTableNode
*>(pNd
)->GetTable().GetFrameFormat();
254 else if (pNd
->IsSectionNode())
256 return static_cast<SwSectionNode
*>(pNd
)->GetSection().GetFormat();
258 else if (pNd
->IsStartNode() && (SwTableBoxStartNode
==
259 static_cast<SwStartNode
*>(pNd
)->GetStartNodeType()))
261 SwTableNode
* pTableNode
= pNd
->FindTableNode();
264 SwTableBox
* pBox
= pTableNode
->GetTable().GetTableBox(m_nNodeIndex
);
267 return pBox
->GetFrameFormat();
276 auto it
= rDoc
.GetSpzFrameFormats()->findByTypeAndName( m_nFormatWhich
, m_sFormatName
);
277 if( it
!= rDoc
.GetSpzFrameFormats()->typeAndNameEnd() )
279 SwFormat
* pFormat
= rDoc
.GetFrameFormats()->FindFormatByName(m_sFormatName
);
289 void SwUndoFormatAttr::RedoImpl(::sw::UndoRedoContext
& rContext
)
291 // #i35443# - Because the undo stores the attributes for
292 // redo, the same code as for <Undo(..)> can be applied for <Redo(..)>
296 void SwUndoFormatAttr::RepeatImpl(::sw::RepeatContext
& rContext
)
301 SwDoc
& rDoc(rContext
.GetDoc());
303 SwFormat
* pFormat
= GetFormat(rDoc
);
307 switch ( m_nFormatWhich
) {
308 case RES_GRFFMTCOLL
: {
309 SwNoTextNode
*const pNd
=
310 rContext
.GetRepeatPaM().GetPointNode().GetNoTextNode();
312 rDoc
.SetAttr( pFormat
->GetAttrSet(), *pNd
->GetFormatColl() );
318 case RES_CONDTXTFMTCOLL
:
320 SwTextNode
*const pNd
=
321 rContext
.GetRepeatPaM().GetPointNode().GetTextNode();
323 rDoc
.SetAttr( pFormat
->GetAttrSet(), *pNd
->GetFormatColl() );
328 case RES_FLYFRMFMT
: {
329 // Check if the cursor is in a flying frame
330 // Steps: search in all FlyFrameFormats for the FlyContent attribute
331 // and validate if the cursor is in the respective section
332 SwFrameFormat
*const pFly
=
333 rContext
.GetRepeatPaM().GetPointNode().GetFlyFormat();
335 // Bug 43672: do not set all attributes!
336 if (SfxItemState::SET
==
337 pFormat
->GetAttrSet().GetItemState( RES_CNTNT
)) {
338 SfxItemSet
aTmpSet( pFormat
->GetAttrSet() );
339 aTmpSet
.ClearItem( RES_CNTNT
);
340 if( aTmpSet
.Count() ) {
341 rDoc
.SetAttr( aTmpSet
, *pFly
);
344 rDoc
.SetAttr( pFormat
->GetAttrSet(), *pFly
);
352 SwRewriter
SwUndoFormatAttr::GetRewriter() const
354 SwRewriter aRewriter
;
356 aRewriter
.AddRule(UndoArg1
, m_sFormatName
);
361 void SwUndoFormatAttr::PutAttr( const SfxPoolItem
& rItem
, const SwDoc
& rDoc
)
363 if (RES_CNTNT
== rItem
.Which())
365 return; // tdf#126017 never save SwNodeIndex, it will go stale
367 m_oOldSet
->Put( rItem
);
368 if ( RES_ANCHOR
== rItem
.Which() )
370 SwFormat
* pFormat
= GetFormat( rDoc
);
371 SaveFlyAnchor( pFormat
, m_bSaveDrawPt
);
375 void SwUndoFormatAttr::SaveFlyAnchor( const SwFormat
* pFormat
, bool bSvDrwPt
)
377 // Format is valid, otherwise you would not reach this point here
379 if ( RES_DRAWFRMFMT
== pFormat
->Which() ) {
380 Point
aPt( static_cast<const SwFrameFormat
*>(pFormat
)->FindSdrObject()
381 ->GetRelativePos() );
382 // store old value as attribute, to keep SwUndoFormatAttr small
383 m_oOldSet
->Put( SwFormatFrameSize( SwFrameSize::Variable
, aPt
.X(), aPt
.Y() ) );
387 const SwFormatAnchor
& rAnchor
=
388 m_oOldSet
->Get( RES_ANCHOR
, false );
389 if( !rAnchor
.GetAnchorNode() || rAnchor
.GetAnchorId() == RndStdIds::FLY_AT_PAGE
)
392 switch( rAnchor
.GetAnchorId() ) {
393 case RndStdIds::FLY_AS_CHAR
:
394 case RndStdIds::FLY_AT_CHAR
:
395 m_nAnchorContentOffset
= rAnchor
.GetAnchorContentOffset();
397 case RndStdIds::FLY_AT_PARA
:
398 case RndStdIds::FLY_AT_FLY
:
399 m_nNodeIndex
= rAnchor
.GetAnchorNode()->GetIndex();
405 SwFormatAnchor
aAnchor( rAnchor
.GetAnchorId(), 0 );
406 m_oOldSet
->Put( aAnchor
);
409 // #i35443# - Add return value, type <bool>.
410 // Return value indicates, if anchor attribute is restored.
411 // Note: If anchor attribute is restored, all other existing attributes
412 // are also restored.
413 bool SwUndoFormatAttr::RestoreFlyAnchor(::sw::UndoRedoContext
& rContext
)
415 SwDoc
*const pDoc
= & rContext
.GetDoc();
416 SwFrameFormat
* pFrameFormat
= static_cast<SwFrameFormat
*>( GetFormat( *pDoc
) );
417 const SwFormatAnchor
& rAnchor
=
418 m_oOldSet
->Get( RES_ANCHOR
, false );
420 SwFormatAnchor
aNewAnchor( rAnchor
.GetAnchorId() );
421 if (RndStdIds::FLY_AT_PAGE
!= rAnchor
.GetAnchorId()) {
422 SwNode
* pNd
= pDoc
->GetNodes()[ m_nNodeIndex
];
424 if ( (RndStdIds::FLY_AT_FLY
== rAnchor
.GetAnchorId())
425 ? ( !pNd
->IsStartNode() || (SwFlyStartNode
!=
426 static_cast<SwStartNode
*>(pNd
)->GetStartNodeType()) )
427 : !pNd
->IsTextNode() ) {
428 // #i35443# - invalid position.
429 // Thus, anchor attribute not restored
433 SwPosition
aPos( *pNd
);
434 if ((RndStdIds::FLY_AS_CHAR
== rAnchor
.GetAnchorId()) ||
435 (RndStdIds::FLY_AT_CHAR
== rAnchor
.GetAnchorId())) {
436 aPos
.SetContent( m_nAnchorContentOffset
);
437 if ( aPos
.GetContentIndex() > pNd
->GetTextNode()->GetText().getLength()) {
438 // #i35443# - invalid position.
439 // Thus, anchor attribute not restored
443 aNewAnchor
.SetAnchor( &aPos
);
445 aNewAnchor
.SetPageNum( rAnchor
.GetPageNum() );
447 Point aDrawSavePt
, aDrawOldPt
;
448 if( pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() ) {
449 if( RES_DRAWFRMFMT
== pFrameFormat
->Which() ) {
450 // get the old cached value
451 const SwFormatFrameSize
& rOldSize
= m_oOldSet
->Get( RES_FRM_SIZE
);
452 aDrawSavePt
.setX( rOldSize
.GetWidth() );
453 aDrawSavePt
.setY( rOldSize
.GetHeight() );
454 m_oOldSet
->ClearItem( RES_FRM_SIZE
);
456 // write the current value into cache
457 aDrawOldPt
= pFrameFormat
->FindSdrObject()->GetRelativePos();
459 pFrameFormat
->DelFrames(); // delete Frames
463 const SwFormatAnchor
&rOldAnch
= pFrameFormat
->GetAnchor();
465 // Consider case, that as-character anchored object has moved its anchor position.
466 if (RndStdIds::FLY_AS_CHAR
== rOldAnch
.GetAnchorId()) {
467 // With InContents it's tricky: the text attribute needs to be deleted.
468 // Unfortunately, this not only destroys the Frames but also the format.
469 // To prevent that, first detach the connection between attribute and
471 SwTextNode
*pTextNode
= static_cast<SwTextNode
*>(rOldAnch
.GetAnchorNode());
472 OSL_ENSURE( pTextNode
->HasHints(), "Missing FlyInCnt-Hint." );
473 const sal_Int32 nIdx
= rOldAnch
.GetAnchorContentOffset();
474 SwTextAttr
* const pHint
=
475 pTextNode
->GetTextAttrForCharAt( nIdx
, RES_TXTATR_FLYCNT
);
476 assert(pHint
&& "Missing Hint.");
477 OSL_ENSURE( pHint
->Which() == RES_TXTATR_FLYCNT
,
478 "Missing FlyInCnt-Hint." );
479 OSL_ENSURE( pHint
->GetFlyCnt().GetFrameFormat() == pFrameFormat
,
480 "Wrong TextFlyCnt-Hint." );
481 const_cast<SwFormatFlyCnt
&>(pHint
->GetFlyCnt()).SetFlyFormat();
483 // Connection is now detached, therefore the attribute can be deleted
484 pTextNode
->DeleteAttributes( RES_TXTATR_FLYCNT
, nIdx
, nIdx
);
488 m_oOldSet
->Put( aNewAnchor
);
489 SwUndoFormatAttrHelper
aTmp( *pFrameFormat
, m_bSaveDrawPt
);
490 pFrameFormat
->SetFormatAttr( *m_oOldSet
);
491 if ( aTmp
.GetUndo() ) {
492 m_nNodeIndex
= aTmp
.GetUndo()->m_nNodeIndex
;
493 // transfer ownership of helper object's old set
494 if (aTmp
.GetUndo()->m_oOldSet
)
495 m_oOldSet
.emplace(std::move(*aTmp
.GetUndo()->m_oOldSet
));
499 m_oOldSet
->ClearItem();
503 if ( RES_DRAWFRMFMT
== pFrameFormat
->Which() )
505 // The Draw model also prepared an Undo object for its right positioning
506 // which unfortunately is relative. Therefore block here a position
507 // change of the Contact object by setting the anchor.
508 const SwFormatVertOrient
& rVertOrient
= pFrameFormat
->GetVertOrient();
509 const SwFormatHoriOrient
& rHoriOrient
= pFrameFormat
->GetHoriOrient();
510 Point
aFormatPos(rHoriOrient
.GetPos(), rVertOrient
.GetPos());
511 if (aDrawSavePt
!= aFormatPos
)
513 // If the position would be the same, then skip the call: either it would do nothing or
514 // it would just go wrong.
515 pFrameFormat
->CallSwClientNotify(sw::RestoreFlyAnchorHint(aDrawSavePt
));
518 // cache the old value again
519 m_oOldSet
->Put(SwFormatFrameSize(SwFrameSize::Variable
, aDrawOldPt
.X(), aDrawOldPt
.Y()));
522 if (RndStdIds::FLY_AS_CHAR
== aNewAnchor
.GetAnchorId()) {
523 SwTextNode
* pTextNd
= aNewAnchor
.GetAnchorNode()->GetTextNode();
524 OSL_ENSURE( pTextNd
, "no Text Node at position." );
525 SwFormatFlyCnt
aFormat( pFrameFormat
);
526 pTextNd
->InsertItem( aFormat
, aNewAnchor
.GetAnchorContentOffset(), 0 );
529 if (RES_DRAWFRMFMT
!= pFrameFormat
->Which())
530 pFrameFormat
->MakeFrames();
533 pFrameFormat
->CallSwClientNotify(sw::DrawFrameFormatHint(sw::DrawFrameFormatHintId::POST_RESTORE_FLY_ANCHOR
));
536 rContext
.SetSelections(pFrameFormat
, nullptr);
538 // #i35443# - anchor attribute restored.
542 SwUndoFormatResetAttr::SwUndoFormatResetAttr( SwFormat
& rChangedFormat
,
543 const sal_uInt16 nWhichId
)
544 : SwUndo( SwUndoId::RESETATTR
, rChangedFormat
.GetDoc() )
545 , m_pChangedFormat( &rChangedFormat
)
546 , m_nWhichId( nWhichId
)
548 const SfxPoolItem
* pItem
= nullptr;
549 if (rChangedFormat
.GetItemState(nWhichId
, false, &pItem
) == SfxItemState::SET
&& pItem
) {
550 m_pOldItem
.reset( pItem
->Clone() );
554 SwUndoFormatResetAttr::~SwUndoFormatResetAttr()
558 void SwUndoFormatResetAttr::UndoImpl(::sw::UndoRedoContext
&)
562 m_pChangedFormat
->SetFormatAttr( *m_pOldItem
);
566 void SwUndoFormatResetAttr::RedoImpl(::sw::UndoRedoContext
&)
570 m_pChangedFormat
->ResetFormatAttr( m_nWhichId
);
574 SwUndoResetAttr::SwUndoResetAttr( const SwPaM
& rRange
, sal_uInt16 nFormatId
)
575 : SwUndo( SwUndoId::RESETATTR
, &rRange
.GetDoc() ), SwUndRng( rRange
)
576 , m_pHistory( new SwHistory
)
577 , m_nFormatId( nFormatId
)
581 SwUndoResetAttr::SwUndoResetAttr( const SwPosition
& rPos
, sal_uInt16 nFormatId
)
582 : SwUndo( SwUndoId::RESETATTR
, &rPos
.GetDoc() )
583 , m_pHistory( new SwHistory
)
584 , m_nFormatId( nFormatId
)
586 m_nSttNode
= m_nEndNode
= rPos
.GetNodeIndex();
587 m_nSttContent
= m_nEndContent
= rPos
.GetContentIndex();
590 SwUndoResetAttr::~SwUndoResetAttr()
594 void SwUndoResetAttr::UndoImpl(::sw::UndoRedoContext
& rContext
)
597 SwDoc
& rDoc
= rContext
.GetDoc();
598 m_pHistory
->TmpRollback( &rDoc
, 0 );
599 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
601 if ((RES_CONDTXTFMTCOLL
== m_nFormatId
) &&
602 (m_nSttNode
== m_nEndNode
) && (m_nSttContent
== m_nEndContent
)) {
603 SwTextNode
* pTNd
= rDoc
.GetNodes()[ m_nSttNode
]->GetTextNode();
605 pTNd
->DontExpandFormat( m_nSttContent
, false );
607 else if (m_nFormatId
== RES_TXTATR_REFMARK
)
609 rDoc
.GetEditShell()->SwViewShell::UpdateFields();
612 AddUndoRedoPaM(rContext
);
615 void SwUndoResetAttr::RedoImpl(::sw::UndoRedoContext
& rContext
)
617 SwDoc
& rDoc
= rContext
.GetDoc();
618 SwPaM
& rPam
= AddUndoRedoPaM(rContext
);
620 switch ( m_nFormatId
) {
622 rDoc
.RstTextAttrs(rPam
);
625 rDoc
.ResetAttrs(rPam
, false, m_Ids
);
627 case RES_CONDTXTFMTCOLL
:
628 rDoc
.ResetAttrs(rPam
, true, m_Ids
);
631 case RES_TXTATR_TOXMARK
:
632 // special treatment for TOXMarks
635 SwNodeIndex
aIdx( rDoc
.GetNodes(), m_nSttNode
);
636 SwPosition
aPos( aIdx
, aIdx
.GetNode().GetContentNode(), m_nSttContent
);
638 sal_uInt16 nCnt
= SwDoc::GetCurTOXMark( aPos
, aArr
);
641 // search for the right one
642 SwHistoryHint
* pHHint
= (GetHistory())[ 0 ];
643 if( pHHint
&& HSTRY_SETTOXMARKHNT
== pHHint
->Which() ) {
645 if ( static_cast<SwHistorySetTOXMark
*>(pHHint
)
646 ->IsEqual( *aArr
[ --nCnt
] ) ) {
654 // found one, thus delete it
656 rDoc
.DeleteTOXMark( aArr
[ nCnt
] );
661 case RES_TXTATR_REFMARK
:
663 SfxItemPool::Item2Range aRange
= rDoc
.GetAttrPool().GetItemSurrogates(RES_TXTATR_REFMARK
);
664 SwHistoryHint
* pHistoryHint
= GetHistory()[0];
665 if (pHistoryHint
&& HSTRY_SETREFMARKHNT
== pHistoryHint
->Which())
667 for (const SfxPoolItem
* pItem
: aRange
)
669 assert(dynamic_cast<const SwFormatRefMark
*>(pItem
));
670 const auto pFormatRefMark
= static_cast<const SwFormatRefMark
*>(pItem
);
671 if (static_cast<SwHistorySetRefMark
*>(pHistoryHint
)->GetRefName() ==
672 pFormatRefMark
->GetRefName())
674 rDoc
.DeleteFormatRefMark(pFormatRefMark
);
675 rDoc
.GetEditShell()->SwViewShell::UpdateFields();
685 void SwUndoResetAttr::RepeatImpl(::sw::RepeatContext
& rContext
)
687 if (m_nFormatId
< RES_FMT_BEGIN
) {
691 switch ( m_nFormatId
) {
693 rContext
.GetDoc().RstTextAttrs(rContext
.GetRepeatPaM());
696 rContext
.GetDoc().ResetAttrs(rContext
.GetRepeatPaM(), false, m_Ids
);
698 case RES_CONDTXTFMTCOLL
:
699 rContext
.GetDoc().ResetAttrs(rContext
.GetRepeatPaM(), true, m_Ids
);
704 void SwUndoResetAttr::SetAttrs( o3tl::sorted_vector
<sal_uInt16
> && rAttrs
)
706 m_Ids
= std::move(rAttrs
);
709 SwUndoAttr::SwUndoAttr( const SwPaM
& rRange
, const SfxPoolItem
& rAttr
,
710 const SetAttrMode nFlags
)
711 : SwUndo( SwUndoId::INSATTR
, &rRange
.GetDoc() ), SwUndRng( rRange
)
712 , m_AttrSet( rRange
.GetDoc().GetAttrPool(), rAttr
.Which(), rAttr
.Which() )
713 , m_pHistory( new SwHistory
)
714 , m_nNodeIndex( NODE_OFFSET_MAX
)
715 , m_nInsertFlags( nFlags
)
717 m_AttrSet
.Put( rAttr
);
719 // Save character style as a style name, not as a reference
720 const SfxPoolItem
* pItem
= m_AttrSet
.GetItem(RES_TXTATR_CHARFMT
);
724 pItem
->QueryValue(aValue
, RES_TXTATR_CHARFMT
);
725 aValue
>>= m_aChrFormatName
;
729 SwUndoAttr::SwUndoAttr( const SwPaM
& rRange
, SfxItemSet aSet
,
730 const SetAttrMode nFlags
)
731 : SwUndo( SwUndoId::INSATTR
, &rRange
.GetDoc() ), SwUndRng( rRange
)
732 , m_AttrSet(std::move( aSet
))
733 , m_pHistory( new SwHistory
)
734 , m_nNodeIndex( NODE_OFFSET_MAX
)
735 , m_nInsertFlags( nFlags
)
737 // Save character style as a style name, not as a reference
738 const SfxPoolItem
* pItem
= m_AttrSet
.GetItem(RES_TXTATR_CHARFMT
);
742 pItem
->QueryValue(aValue
, RES_TXTATR_CHARFMT
);
743 aValue
>>= m_aChrFormatName
;
747 SwUndoAttr::~SwUndoAttr()
751 void SwUndoAttr::SaveRedlineData( const SwPaM
& rPam
, bool bIsContent
)
753 SwDoc
& rDoc
= rPam
.GetDoc();
754 if ( rDoc
.getIDocumentRedlineAccess().IsRedlineOn() ) {
755 m_pRedlineData
.reset( new SwRedlineData( bIsContent
756 ? RedlineType::Insert
757 : RedlineType::Format
,
758 rDoc
.getIDocumentRedlineAccess().GetRedlineAuthor() ) );
761 m_pRedlineSaveData
.reset( new SwRedlineSaveDatas
);
762 if ( !FillSaveDataForFormat( rPam
, *m_pRedlineSaveData
))
763 m_pRedlineSaveData
.reset();
765 SetRedlineFlags( rDoc
.getIDocumentRedlineAccess().GetRedlineFlags() );
767 m_nNodeIndex
= rPam
.GetPoint()->GetNodeIndex();
771 void SwUndoAttr::UndoImpl(::sw::UndoRedoContext
& rContext
)
773 SwDoc
*const pDoc
= & rContext
.GetDoc();
777 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) ) {
778 SwPaM
aPam(pDoc
->GetNodes().GetEndOfContent());
779 if ( NODE_OFFSET_MAX
!= m_nNodeIndex
) {
781 aPam
.GetPoint()->Assign( m_nNodeIndex
, m_nSttContent
);
783 aPam
.GetPoint()->AdjustContent(+1);
784 pDoc
->getIDocumentRedlineAccess().DeleteRedline(aPam
, false, RedlineType::Any
);
786 // remove all format redlines, will be recreated if needed
788 pDoc
->getIDocumentRedlineAccess().DeleteRedline(aPam
, false, RedlineType::Format
);
789 if (m_pRedlineSaveData
)
791 SetSaveData( *pDoc
, *m_pRedlineSaveData
);
796 const bool bToLast
= (1 == m_AttrSet
.Count())
797 && (RES_TXTATR_FIELD
<= m_AttrSet
.GetRanges()[0].first
)
798 && (m_AttrSet
.GetRanges()[0].first
<= RES_TXTATR_ANNOTATION
);
800 // restore old values
801 m_pHistory
->TmpRollback( pDoc
, 0, !bToLast
);
802 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
804 // set cursor onto Undo area
805 if (!(m_nInsertFlags
& SetAttrMode::NO_CURSOR_CHANGE
))
806 AddUndoRedoPaM(rContext
);
809 void SwUndoAttr::RepeatImpl(::sw::RepeatContext
& rContext
)
811 // RefMarks are not repeat capable
812 if ( SfxItemState::SET
!= m_AttrSet
.GetItemState( RES_TXTATR_REFMARK
, false ) ) {
813 rContext
.GetDoc().getIDocumentContentOperations().InsertItemSet( rContext
.GetRepeatPaM(),
814 m_AttrSet
, m_nInsertFlags
);
815 } else if ( 1 < m_AttrSet
.Count() ) {
816 SfxItemSet
aTmpSet( m_AttrSet
);
817 aTmpSet
.ClearItem( RES_TXTATR_REFMARK
);
818 rContext
.GetDoc().getIDocumentContentOperations().InsertItemSet( rContext
.GetRepeatPaM(),
819 aTmpSet
, m_nInsertFlags
);
823 void SwUndoAttr::redoAttribute(SwPaM
& rPam
, sw::UndoRedoContext
& rContext
)
825 SwDoc
& rDoc
= rContext
.GetDoc();
827 // Restore pointer to char format from name
828 if (!m_aChrFormatName
.isEmpty())
830 SwCharFormat
* pCharFormat
= rDoc
.FindCharFormatByName(m_aChrFormatName
);
833 SwFormatCharFormat
aFormat(pCharFormat
);
834 m_AttrSet
.Put(aFormat
);
838 if ( m_pRedlineData
&&
839 IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) ) {
840 RedlineFlags eOld
= rDoc
.getIDocumentRedlineAccess().GetRedlineFlags();
841 rDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
& ~RedlineFlags::Ignore
);
842 rDoc
.getIDocumentContentOperations().InsertItemSet( rPam
, m_AttrSet
, m_nInsertFlags
);
844 if ( NODE_OFFSET_MAX
!= m_nNodeIndex
) {
846 if ( rPam
.Move( fnMoveBackward
) ) {
847 rDoc
.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlineData
, rPam
),
852 rDoc
.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlineData
, rPam
), true);
855 rDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
857 rDoc
.getIDocumentContentOperations().InsertItemSet( rPam
, m_AttrSet
, m_nInsertFlags
);
861 void SwUndoAttr::RedoImpl(sw::UndoRedoContext
& rContext
)
863 if (m_nInsertFlags
& SetAttrMode::NO_CURSOR_CHANGE
)
865 SwPaM
aPam(rContext
.GetDoc().GetNodes().GetEndOfContent());
867 redoAttribute(aPam
, rContext
);
871 SwPaM
& rPam
= AddUndoRedoPaM(rContext
);
872 redoAttribute(rPam
, rContext
);
876 void SwUndoAttr::RemoveIdx( SwDoc
& rDoc
)
878 if ( SfxItemState::SET
!= m_AttrSet
.GetItemState( RES_TXTATR_FTN
, false ))
881 SwNodes
& rNds
= rDoc
.GetNodes();
882 for ( sal_uInt16 n
= 0; n
< m_pHistory
->Count(); ++n
) {
883 sal_Int32 nContent
= 0;
884 SwNodeOffset
nNode(0);
885 SwHistoryHint
* pHstHint
= (*m_pHistory
)[ n
];
886 switch ( pHstHint
->Which() ) {
887 case HSTRY_RESETTXTHNT
: {
888 SwHistoryResetText
* pHistoryHint
889 = static_cast<SwHistoryResetText
*>(pHstHint
);
890 if ( RES_TXTATR_FTN
== pHistoryHint
->GetWhich() ) {
891 nNode
= pHistoryHint
->GetNode();
892 nContent
= pHistoryHint
->GetContent();
902 SwTextNode
* pTextNd
= rNds
[ nNode
]->GetTextNode();
904 SwTextAttr
*const pTextHt
=
905 pTextNd
->GetTextAttrForCharAt(nContent
, RES_TXTATR_FTN
);
908 SwTextFootnote
* pFootnote
= static_cast<SwTextFootnote
*>(pTextHt
);
909 RemoveIdxFromSection( rDoc
, pFootnote
->GetStartNode()->GetIndex() );
917 SwUndoDefaultAttr::SwUndoDefaultAttr( const SfxItemSet
& rSet
, const SwDoc
& rDoc
)
918 : SwUndo( SwUndoId::SETDEFTATTR
, &rDoc
)
920 const SvxTabStopItem
* pItem
= rSet
.GetItemIfSet( RES_PARATR_TABSTOP
, false );
923 // store separately, because it may change!
924 m_pTabStop
.reset(pItem
->Clone());
925 if ( 1 != rSet
.Count() ) { // are there more attributes?
926 m_oOldSet
.emplace( rSet
);
929 m_oOldSet
.emplace( rSet
);
933 SwUndoDefaultAttr::~SwUndoDefaultAttr()
937 void SwUndoDefaultAttr::UndoImpl(::sw::UndoRedoContext
& rContext
)
939 SwDoc
& rDoc
= rContext
.GetDoc();
942 SwUndoFormatAttrHelper
aTmp(
943 *rDoc
.GetDfltTextFormatColl() );
944 rDoc
.SetDefault( *m_oOldSet
);
946 if ( aTmp
.GetUndo() ) {
947 // transfer ownership of helper object's old set
948 if (aTmp
.GetUndo()->m_oOldSet
)
949 m_oOldSet
.emplace(std::move(*aTmp
.GetUndo()->m_oOldSet
));
954 std::unique_ptr
<SvxTabStopItem
> pOld(rDoc
.GetDefault(RES_PARATR_TABSTOP
).Clone());
955 rDoc
.SetDefault( *m_pTabStop
);
956 m_pTabStop
= std::move( pOld
);
960 void SwUndoDefaultAttr::RedoImpl(::sw::UndoRedoContext
& rContext
)
965 SwUndoMoveLeftMargin::SwUndoMoveLeftMargin(
966 const SwPaM
& rPam
, bool bFlag
, bool bMod
)
967 : SwUndo( bFlag
? SwUndoId::INC_LEFTMARGIN
: SwUndoId::DEC_LEFTMARGIN
, &rPam
.GetDoc() )
969 , m_pHistory( new SwHistory
)
974 SwUndoMoveLeftMargin::~SwUndoMoveLeftMargin()
978 void SwUndoMoveLeftMargin::UndoImpl(::sw::UndoRedoContext
& rContext
)
980 SwDoc
& rDoc
= rContext
.GetDoc();
982 // restore old values
983 m_pHistory
->TmpRollback( & rDoc
, 0 );
984 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
986 AddUndoRedoPaM(rContext
);
989 void SwUndoMoveLeftMargin::RedoImpl(::sw::UndoRedoContext
& rContext
)
991 SwDoc
& rDoc
= rContext
.GetDoc();
992 SwPaM
& rPam
= AddUndoRedoPaM(rContext
);
994 rDoc
.MoveLeftMargin( rPam
,
995 GetId() == SwUndoId::INC_LEFTMARGIN
, m_bModulus
,
996 rDoc
.getIDocumentLayoutAccess().GetCurrentLayout() );
999 void SwUndoMoveLeftMargin::RepeatImpl(::sw::RepeatContext
& rContext
)
1001 SwDoc
& rDoc
= rContext
.GetDoc();
1002 rDoc
.MoveLeftMargin(rContext
.GetRepeatPaM(), GetId() == SwUndoId::INC_LEFTMARGIN
,
1003 m_bModulus
, rDoc
.getIDocumentLayoutAccess().GetCurrentLayout());
1006 SwUndoChangeFootNote::SwUndoChangeFootNote(
1007 const SwPaM
& rRange
, OUString aText
,
1008 bool const bIsEndNote
)
1009 : SwUndo( SwUndoId::CHGFTN
, &rRange
.GetDoc() ), SwUndRng( rRange
)
1010 , m_pHistory( new SwHistory() )
1011 , m_Text(std::move( aText
))
1012 , m_bEndNote( bIsEndNote
)
1016 SwUndoChangeFootNote::~SwUndoChangeFootNote()
1020 void SwUndoChangeFootNote::UndoImpl(::sw::UndoRedoContext
& rContext
)
1022 SwDoc
& rDoc
= rContext
.GetDoc();
1024 m_pHistory
->TmpRollback( &rDoc
, 0 );
1025 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
1027 rDoc
.GetFootnoteIdxs().UpdateAllFootnote();
1029 AddUndoRedoPaM(rContext
);
1032 void SwUndoChangeFootNote::RedoImpl(::sw::UndoRedoContext
& rContext
)
1034 SwDoc
& rDoc( rContext
.GetDoc() );
1035 SwPaM
& rPaM
= AddUndoRedoPaM(rContext
);
1036 rDoc
.SetCurFootnote(rPaM
, m_Text
, m_bEndNote
);
1040 void SwUndoChangeFootNote::RepeatImpl(::sw::RepeatContext
& rContext
)
1042 SwDoc
& rDoc
= rContext
.GetDoc();
1043 rDoc
.SetCurFootnote(rContext
.GetRepeatPaM(), m_Text
, m_bEndNote
);
1046 SwUndoFootNoteInfo::SwUndoFootNoteInfo( const SwFootnoteInfo
&rInfo
, const SwDoc
& rDoc
)
1047 : SwUndo( SwUndoId::FTNINFO
, &rDoc
)
1048 , m_pFootNoteInfo( new SwFootnoteInfo( rInfo
) )
1052 SwUndoFootNoteInfo::~SwUndoFootNoteInfo()
1056 void SwUndoFootNoteInfo::UndoImpl(::sw::UndoRedoContext
& rContext
)
1058 SwDoc
& rDoc
= rContext
.GetDoc();
1059 SwFootnoteInfo
*pInf
= new SwFootnoteInfo( rDoc
.GetFootnoteInfo() );
1060 rDoc
.SetFootnoteInfo( *m_pFootNoteInfo
);
1061 m_pFootNoteInfo
.reset( pInf
);
1064 void SwUndoFootNoteInfo::RedoImpl(::sw::UndoRedoContext
& rContext
)
1066 SwDoc
& rDoc
= rContext
.GetDoc();
1067 SwFootnoteInfo
*pInf
= new SwFootnoteInfo( rDoc
.GetFootnoteInfo() );
1068 rDoc
.SetFootnoteInfo( *m_pFootNoteInfo
);
1069 m_pFootNoteInfo
.reset( pInf
);
1072 SwUndoEndNoteInfo::SwUndoEndNoteInfo( const SwEndNoteInfo
&rInfo
, const SwDoc
& rDoc
)
1073 : SwUndo( SwUndoId::FTNINFO
, &rDoc
)
1074 , m_pEndNoteInfo( new SwEndNoteInfo( rInfo
) )
1078 SwUndoEndNoteInfo::~SwUndoEndNoteInfo()
1082 void SwUndoEndNoteInfo::UndoImpl(::sw::UndoRedoContext
& rContext
)
1084 SwDoc
& rDoc
= rContext
.GetDoc();
1085 SwEndNoteInfo
*pInf
= new SwEndNoteInfo( rDoc
.GetEndNoteInfo() );
1086 rDoc
.SetEndNoteInfo( *m_pEndNoteInfo
);
1087 m_pEndNoteInfo
.reset( pInf
);
1090 void SwUndoEndNoteInfo::RedoImpl(::sw::UndoRedoContext
& rContext
)
1092 SwDoc
& rDoc
= rContext
.GetDoc();
1093 SwEndNoteInfo
*pInf
= new SwEndNoteInfo( rDoc
.GetEndNoteInfo() );
1094 rDoc
.SetEndNoteInfo( *m_pEndNoteInfo
);
1095 m_pEndNoteInfo
.reset( pInf
);
1098 SwUndoDontExpandFormat::SwUndoDontExpandFormat( const SwPosition
& rPos
)
1099 : SwUndo( SwUndoId::DONTEXPAND
, &rPos
.GetDoc() )
1100 , m_nNodeIndex( rPos
.GetNodeIndex() )
1101 , m_nContentIndex( rPos
.GetContentIndex() )
1105 void SwUndoDontExpandFormat::UndoImpl(::sw::UndoRedoContext
& rContext
)
1107 SwCursor
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
1108 SwDoc
*const pDoc
= & rContext
.GetDoc();
1110 SwPosition
& rPos
= *pPam
->GetPoint();
1111 rPos
.Assign( m_nNodeIndex
, m_nContentIndex
);
1112 pDoc
->DontExpandFormat( rPos
, false );
1115 void SwUndoDontExpandFormat::RedoImpl(::sw::UndoRedoContext
& rContext
)
1117 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
1118 SwDoc
*const pDoc
= & rContext
.GetDoc();
1120 SwPosition
& rPos
= *pPam
->GetPoint();
1121 rPos
.Assign( m_nNodeIndex
, m_nContentIndex
);
1122 pDoc
->DontExpandFormat( rPos
);
1125 void SwUndoDontExpandFormat::RepeatImpl(::sw::RepeatContext
& rContext
)
1127 SwPaM
& rPam
= rContext
.GetRepeatPaM();
1128 SwDoc
& rDoc
= rContext
.GetDoc();
1129 rDoc
.DontExpandFormat( *rPam
.GetPoint() );
1132 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */