Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sw / source / core / undo / unsect.cxx
blobf17cae6303162de11ec540edfd6b6bccff7dde72
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
21 #include <UndoSection.hxx>
23 #include <sfx2/linkmgr.hxx>
24 #include <fmtcntnt.hxx>
25 #include <doc.hxx>
26 #include <IDocumentLinksAdministration.hxx>
27 #include <IDocumentRedlineAccess.hxx>
28 #include <IDocumentFieldsAccess.hxx>
29 #include <docary.hxx>
30 #include <swundo.hxx>
31 #include <pam.hxx>
32 #include <ndtxt.hxx>
33 #include <UndoCore.hxx>
34 #include <section.hxx>
35 #include <rolbck.hxx>
36 #include <redline.hxx>
37 #include <doctxm.hxx>
38 #include <ftnidx.hxx>
39 #include <editsh.hxx>
40 /// OD 04.10.2002 #102894#
41 /// class Calc needed for calculation of the hidden condition of a section.
42 #include <calc.hxx>
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() )
52 sal_uInt16 nCnt = 1;
53 if( rSect.IsProtect() )
54 ++nCnt;
56 if( nCnt < rSect.GetFormat()->GetAttrSet().Count() )
58 pAttr = new SfxItemSet( rSect.GetFormat()->GetAttrSet() );
59 pAttr->ClearItem( RES_PROTECT );
60 pAttr->ClearItem( RES_CNTNT );
61 if( !pAttr->Count() )
63 delete pAttr;
64 pAttr = nullptr;
68 return pAttr;
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 );
94 if( !rPam.HasMark() )
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 );
129 // no selection?
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() -
135 aIdx.GetIndex() );
136 else
137 // just delete format, rest happens automatically
138 rDoc.DelSectionFormat( pNd->GetSection().GetFormat() );
140 // do we need to consolidate?
141 if (m_bSplitAtStart)
143 Join( rDoc, nSttNode );
146 if (m_bSplitAtEnd)
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);
178 else
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 );
207 if( pUpdateTOX )
209 // initiate formatting
210 SwEditShell* pESh = rDoc.GetEditShell();
211 if( pESh )
212 pESh->CalcLayout();
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);
227 else
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?" );
241 RemoveIdxRel(
242 nNode + 1,
243 SwPosition( aIdx, SwIndex( pTextNd, pTextNd->GetText().getLength() ) ) );
245 pTextNd->JoinNext();
247 if (m_pHistory.get())
249 SwIndex aCntIdx( pTextNd, 0 );
250 pTextNd->RstTextAttr( aCntIdx, pTextNd->Len(), 0, nullptr, true );
254 void
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 );
267 if (bAtStart)
269 m_bSplitAtStart = true;
271 else
273 m_bSplitAtEnd = true;
277 class SwUndoDelSection
278 : public SwUndo
280 private:
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;
288 public:
289 SwUndoDelSection(
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))
309 : nullptr )
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,
324 m_pAttrSet.get());
326 else
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
382 : public SwUndo
384 private:
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;
390 public:
391 SwUndoUpdateSection(
392 SwSection const&, SwNodeIndex const*const, bool const bOnlyAttr);
394 virtual void UndoImpl( ::sw::UndoRedoContext & ) override;
395 virtual void RedoImpl( ::sw::UndoRedoContext & ) override;
398 SwUndo *
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 );
440 else
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)
451 const bool bUpdate =
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);
462 if( bUpdate )
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)
474 UndoImpl(rContext);
477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */