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 .
21 #include <UndoSection.hxx>
23 #include <sfx2/linkmgr.hxx>
24 #include <fmtcntnt.hxx>
26 #include <IDocumentLinksAdministration.hxx>
27 #include <IDocumentRedlineAccess.hxx>
28 #include <IDocumentFieldsAccess.hxx>
33 #include <UndoCore.hxx>
34 #include <section.hxx>
36 #include <redline.hxx>
40 /// OD 04.10.2002 #102894#
41 /// class Calc needed for calculation of the hidden condition of a section.
44 static SfxItemSet
* lcl_GetAttrSet( const SwSection
& rSect
)
46 // save attributes of the format (columns, color, ...)
47 // Content and Protect items are not interesting since they are already
48 // stored in Section, thus delete them.
49 SfxItemSet
* pAttr
= nullptr;
50 if( rSect
.GetFormat() )
53 if( rSect
.IsProtect() )
56 if( nCnt
< rSect
.GetFormat()->GetAttrSet().Count() )
58 pAttr
= new SfxItemSet( rSect
.GetFormat()->GetAttrSet() );
59 pAttr
->ClearItem( RES_PROTECT
);
60 pAttr
->ClearItem( RES_CNTNT
);
71 SwUndoInsSection::SwUndoInsSection(
72 SwPaM
const& rPam
, SwSectionData
const& rNewData
,
73 SfxItemSet
const*const pSet
, SwTOXBase
const*const pTOXBase
)
74 : SwUndo( SwUndoId::INSSECTION
, rPam
.GetDoc() ), SwUndRng( rPam
)
75 , m_pSectionData(new SwSectionData(rNewData
))
76 , m_pTOXBase( pTOXBase
? new SwTOXBase(*pTOXBase
) : nullptr )
77 , m_pAttrSet( (pSet
&& pSet
->Count()) ? new SfxItemSet( *pSet
) : nullptr )
78 , m_nSectionNodePos(0)
79 , m_bSplitAtStart(false)
80 , m_bSplitAtEnd(false)
81 , m_bUpdateFootnote(false)
83 SwDoc
& rDoc
= *rPam
.GetDoc();
84 if( rDoc
.getIDocumentRedlineAccess().IsRedlineOn() )
86 m_pRedlData
.reset(new SwRedlineData( nsRedlineType_t::REDLINE_INSERT
,
87 rDoc
.getIDocumentRedlineAccess().GetRedlineAuthor() ));
88 SetRedlineFlags( rDoc
.getIDocumentRedlineAccess().GetRedlineFlags() );
90 m_pRedlineSaveData
.reset( new SwRedlineSaveDatas
);
91 if( !FillSaveData( rPam
, *m_pRedlineSaveData
, false ))
92 m_pRedlineSaveData
.reset( nullptr );
96 const SwContentNode
* pCNd
= rPam
.GetPoint()->nNode
.GetNode().GetContentNode();
97 if( pCNd
&& pCNd
->HasSwAttrSet() && (
98 !rPam
.GetPoint()->nContent
.GetIndex() ||
99 rPam
.GetPoint()->nContent
.GetIndex() == pCNd
->Len() ))
101 SfxItemSet
aBrkSet( rDoc
.GetAttrPool(), aBreakSetRange
);
102 aBrkSet
.Put( *pCNd
->GetpSwAttrSet() );
103 if( aBrkSet
.Count() )
105 m_pHistory
.reset( new SwHistory
);
106 m_pHistory
->CopyFormatAttr( aBrkSet
, pCNd
->GetIndex() );
112 SwUndoInsSection::~SwUndoInsSection()
116 void SwUndoInsSection::UndoImpl(::sw::UndoRedoContext
& rContext
)
118 SwDoc
& rDoc
= rContext
.GetDoc();
120 RemoveIdxFromSection( rDoc
, m_nSectionNodePos
);
122 SwSectionNode
*const pNd
=
123 rDoc
.GetNodes()[ m_nSectionNodePos
]->GetSectionNode();
124 OSL_ENSURE( pNd
, "where is my SectionNode?" );
126 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
127 rDoc
.getIDocumentRedlineAccess().DeleteRedline( *pNd
, true, USHRT_MAX
);
130 SwNodeIndex
aIdx( *pNd
);
131 if( ( !nEndNode
&& COMPLETE_STRING
== nEndContent
) ||
132 ( nSttNode
== nEndNode
&& nSttContent
== nEndContent
))
133 // delete simply all nodes
134 rDoc
.GetNodes().Delete( aIdx
, pNd
->EndOfSectionIndex() -
137 // just delete format, rest happens automatically
138 rDoc
.DelSectionFormat( pNd
->GetSection().GetFormat() );
140 // do we need to consolidate?
143 Join( rDoc
, nSttNode
);
148 Join( rDoc
, nEndNode
);
151 if (m_pHistory
.get())
153 m_pHistory
->TmpRollback( &rDoc
, 0, false );
156 if (m_bUpdateFootnote
)
158 rDoc
.GetFootnoteIdxs().UpdateFootnote( aIdx
);
161 AddUndoRedoPaM(rContext
);
163 if( m_pRedlineSaveData
.get())
164 SetSaveData( rDoc
, *m_pRedlineSaveData
);
167 void SwUndoInsSection::RedoImpl(::sw::UndoRedoContext
& rContext
)
169 SwDoc
& rDoc
= rContext
.GetDoc();
170 SwPaM
& rPam( AddUndoRedoPaM(rContext
) );
172 const SwTOXBaseSection
* pUpdateTOX
= nullptr;
173 if (m_pTOXBase
.get())
175 pUpdateTOX
= rDoc
.InsertTableOf( *rPam
.GetPoint(),
176 *m_pTOXBase
, m_pAttrSet
.get(), true);
180 rDoc
.InsertSwSection(rPam
, *m_pSectionData
, nullptr, m_pAttrSet
.get());
183 if (m_pHistory
.get())
185 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
188 SwSectionNode
*const pSectNd
=
189 rDoc
.GetNodes()[ m_nSectionNodePos
]->GetSectionNode();
190 if (m_pRedlData
.get() &&
191 IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags()))
193 RedlineFlags eOld
= rDoc
.getIDocumentRedlineAccess().GetRedlineFlags();
194 rDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern(eOld
& ~RedlineFlags::Ignore
);
196 SwPaM
aPam( *pSectNd
->EndOfSectionNode(), *pSectNd
, 1 );
197 rDoc
.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlData
, aPam
), true);
198 rDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
200 else if( !( RedlineFlags::Ignore
& GetRedlineFlags() ) &&
201 !rDoc
.getIDocumentRedlineAccess().GetRedlineTable().empty() )
203 SwPaM
aPam( *pSectNd
->EndOfSectionNode(), *pSectNd
, 1 );
204 rDoc
.getIDocumentRedlineAccess().SplitRedline( aPam
);
209 // initiate formatting
210 SwEditShell
* pESh
= rDoc
.GetEditShell();
214 // insert page numbers
215 const_cast<SwTOXBaseSection
*>(pUpdateTOX
)->UpdatePageNum();
219 void SwUndoInsSection::RepeatImpl(::sw::RepeatContext
& rContext
)
221 SwDoc
& rDoc
= rContext
.GetDoc();
222 if (m_pTOXBase
.get())
224 rDoc
.InsertTableOf(*rContext
.GetRepeatPaM().GetPoint(),
225 *m_pTOXBase
, m_pAttrSet
.get(), true);
229 rDoc
.InsertSwSection(rContext
.GetRepeatPaM(),
230 *m_pSectionData
, nullptr, m_pAttrSet
.get());
234 void SwUndoInsSection::Join( SwDoc
& rDoc
, sal_uLong nNode
)
236 SwNodeIndex
aIdx( rDoc
.GetNodes(), nNode
);
237 SwTextNode
* pTextNd
= aIdx
.GetNode().GetTextNode();
238 OSL_ENSURE( pTextNd
, "Where is my TextNode?" );
243 SwPosition( aIdx
, SwIndex( pTextNd
, pTextNd
->GetText().getLength() ) ) );
247 if (m_pHistory
.get())
249 SwIndex
aCntIdx( pTextNd
, 0 );
250 pTextNd
->RstTextAttr( aCntIdx
, pTextNd
->Len(), 0, nullptr, true );
255 SwUndoInsSection::SaveSplitNode(SwTextNode
*const pTextNd
, bool const bAtStart
)
257 if( pTextNd
->GetpSwpHints() )
259 if (!m_pHistory
.get())
261 m_pHistory
.reset( new SwHistory
);
263 m_pHistory
->CopyAttr( pTextNd
->GetpSwpHints(), pTextNd
->GetIndex(), 0,
264 pTextNd
->GetText().getLength(), false );
269 m_bSplitAtStart
= true;
273 m_bSplitAtEnd
= true;
277 class SwUndoDelSection
281 std::unique_ptr
<SwSectionData
> const m_pSectionData
; /// section not TOX
282 std::unique_ptr
<SwTOXBase
> const m_pTOXBase
; /// set iff section is TOX
283 std::unique_ptr
<SfxItemSet
> const m_pAttrSet
;
284 std::shared_ptr
< ::sfx2::MetadatableUndo
> const m_pMetadataUndo
;
285 sal_uLong
const m_nStartNode
;
286 sal_uLong
const m_nEndNode
;
290 SwSectionFormat
const&, SwSection
const&, SwNodeIndex
const*const);
292 virtual void UndoImpl( ::sw::UndoRedoContext
& ) override
;
293 virtual void RedoImpl( ::sw::UndoRedoContext
& ) override
;
296 SwUndo
* MakeUndoDelSection(SwSectionFormat
const& rFormat
)
298 return new SwUndoDelSection(rFormat
, *rFormat
.GetSection(),
299 rFormat
.GetContent().GetContentIdx());
302 SwUndoDelSection::SwUndoDelSection(
303 SwSectionFormat
const& rSectionFormat
, SwSection
const& rSection
,
304 SwNodeIndex
const*const pIndex
)
305 : SwUndo( SwUndoId::DELSECTION
, rSectionFormat
.GetDoc() )
306 , m_pSectionData( new SwSectionData(rSection
) )
307 , m_pTOXBase( dynamic_cast<const SwTOXBaseSection
*>( &rSection
) != nullptr
308 ? new SwTOXBase(static_cast<SwTOXBaseSection
const&>(rSection
))
310 , m_pAttrSet( ::lcl_GetAttrSet(rSection
) )
311 , m_pMetadataUndo( rSectionFormat
.CreateUndo() )
312 , m_nStartNode( pIndex
->GetIndex() )
313 , m_nEndNode( pIndex
->GetNode().EndOfSectionIndex() )
317 void SwUndoDelSection::UndoImpl(::sw::UndoRedoContext
& rContext
)
319 SwDoc
& rDoc
= rContext
.GetDoc();
321 if (m_pTOXBase
.get())
323 rDoc
.InsertTableOf(m_nStartNode
, m_nEndNode
-2, *m_pTOXBase
,
328 SwNodeIndex
aStt( rDoc
.GetNodes(), m_nStartNode
);
329 SwNodeIndex
aEnd( rDoc
.GetNodes(), m_nEndNode
-2 );
330 SwSectionFormat
* pFormat
= rDoc
.MakeSectionFormat();
331 if (m_pAttrSet
.get())
333 pFormat
->SetFormatAttr( *m_pAttrSet
);
336 /// OD 04.10.2002 #102894#
337 /// remember inserted section node for further calculations
338 SwSectionNode
* pInsertedSectNd
= rDoc
.GetNodes().InsertTextSection(
339 aStt
, *pFormat
, *m_pSectionData
, nullptr, & aEnd
);
341 if( SfxItemState::SET
== pFormat
->GetItemState( RES_FTN_AT_TXTEND
) ||
342 SfxItemState::SET
== pFormat
->GetItemState( RES_END_AT_TXTEND
))
344 rDoc
.GetFootnoteIdxs().UpdateFootnote( aStt
);
347 /// OD 04.10.2002 #102894#
348 /// consider that section is hidden by condition.
349 /// If section is hidden by condition,
350 /// recalculate condition and update hidden condition flag.
351 /// Recalculation is necessary, because fields, on which the hide
352 /// condition depends, can be changed - fields changes aren't undoable.
353 /// NOTE: setting hidden condition flag also creates/deletes corresponding
354 /// frames, if the hidden condition flag changes.
355 SwSection
& aInsertedSect
= pInsertedSectNd
->GetSection();
356 if ( aInsertedSect
.IsHidden() &&
357 !aInsertedSect
.GetCondition().isEmpty() )
359 SwCalc
aCalc( rDoc
);
360 rDoc
.getIDocumentFieldsAccess().FieldsToCalc(aCalc
, pInsertedSectNd
->GetIndex(), USHRT_MAX
);
361 bool bRecalcCondHidden
=
362 aCalc
.Calculate( aInsertedSect
.GetCondition() ).GetBool();
363 aInsertedSect
.SetCondHidden( bRecalcCondHidden
);
366 pFormat
->RestoreMetadata(m_pMetadataUndo
);
370 void SwUndoDelSection::RedoImpl(::sw::UndoRedoContext
& rContext
)
372 SwDoc
& rDoc
= rContext
.GetDoc();
374 SwSectionNode
*const pNd
=
375 rDoc
.GetNodes()[ m_nStartNode
]->GetSectionNode();
376 OSL_ENSURE( pNd
, "Where is my SectionNode?" );
377 // just delete format, rest happens automatically
378 rDoc
.DelSectionFormat( pNd
->GetSection().GetFormat() );
381 class SwUndoUpdateSection
385 std::unique_ptr
<SwSectionData
> m_pSectionData
;
386 std::unique_ptr
<SfxItemSet
> m_pAttrSet
;
387 sal_uLong
const m_nStartNode
;
388 bool const m_bOnlyAttrChanged
;
392 SwSection
const&, SwNodeIndex
const*const, bool const bOnlyAttr
);
394 virtual void UndoImpl( ::sw::UndoRedoContext
& ) override
;
395 virtual void RedoImpl( ::sw::UndoRedoContext
& ) override
;
399 MakeUndoUpdateSection(SwSectionFormat
const& rFormat
, bool const bOnlyAttr
)
401 return new SwUndoUpdateSection(*rFormat
.GetSection(),
402 rFormat
.GetContent().GetContentIdx(), bOnlyAttr
);
405 SwUndoUpdateSection::SwUndoUpdateSection(
406 SwSection
const& rSection
, SwNodeIndex
const*const pIndex
,
407 bool const bOnlyAttr
)
408 : SwUndo( SwUndoId::CHGSECTION
, pIndex
->GetNode().GetDoc() )
409 , m_pSectionData( new SwSectionData(rSection
) )
410 , m_pAttrSet( ::lcl_GetAttrSet(rSection
) )
411 , m_nStartNode( pIndex
->GetIndex() )
412 , m_bOnlyAttrChanged( bOnlyAttr
)
416 void SwUndoUpdateSection::UndoImpl(::sw::UndoRedoContext
& rContext
)
418 SwDoc
& rDoc
= rContext
.GetDoc();
419 SwSectionNode
*const pSectNd
=
420 rDoc
.GetNodes()[ m_nStartNode
]->GetSectionNode();
421 OSL_ENSURE( pSectNd
, "Where is my SectionNode?" );
423 SwSection
& rNdSect
= pSectNd
->GetSection();
424 SwFormat
* pFormat
= rNdSect
.GetFormat();
426 SfxItemSet
* pCur
= ::lcl_GetAttrSet( rNdSect
);
427 if (m_pAttrSet
.get())
429 // The Content and Protect items must persist
430 const SfxPoolItem
* pItem
;
431 m_pAttrSet
->Put( pFormat
->GetFormatAttr( RES_CNTNT
));
432 if( SfxItemState::SET
== pFormat
->GetItemState( RES_PROTECT
, true, &pItem
))
434 m_pAttrSet
->Put( *pItem
);
436 pFormat
->DelDiffs( *m_pAttrSet
);
437 m_pAttrSet
->ClearItem( RES_CNTNT
);
438 pFormat
->SetFormatAttr( *m_pAttrSet
);
442 // than the old ones need to be deleted
443 pFormat
->ResetFormatAttr( RES_FRMATR_BEGIN
, RES_BREAK
);
444 pFormat
->ResetFormatAttr( RES_HEADER
, RES_OPAQUE
);
445 pFormat
->ResetFormatAttr( RES_SURROUND
, RES_FRMATR_END
-1 );
447 m_pAttrSet
.reset(pCur
);
449 if (!m_bOnlyAttrChanged
)
452 (!rNdSect
.IsLinkType() && m_pSectionData
->IsLinkType())
453 || ( !m_pSectionData
->GetLinkFileName().isEmpty()
454 && (m_pSectionData
->GetLinkFileName() !=
455 rNdSect
.GetLinkFileName()));
457 // swap stored section data with live section data
458 SwSectionData
*const pOld( new SwSectionData(rNdSect
) );
459 rNdSect
.SetSectionData(*m_pSectionData
);
460 m_pSectionData
.reset(pOld
);
463 rNdSect
.CreateLink( CREATE_UPDATE
);
464 else if( CONTENT_SECTION
== rNdSect
.GetType() && rNdSect
.IsConnected() )
466 rNdSect
.Disconnect();
467 rDoc
.getIDocumentLinksAdministration().GetLinkManager().Remove( &rNdSect
.GetBaseLink() );
472 void SwUndoUpdateSection::RedoImpl(::sw::UndoRedoContext
& rContext
)
477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */