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 <config_wasm_strip.h>
21 #include <libxml/xmlwriter.h>
22 #include <hintids.hxx>
23 #include <osl/diagnose.h>
24 #include <sfx2/linkmgr.hxx>
25 #include <svl/itemiter.hxx>
26 #include <sal/log.hxx>
27 #include <fmtcntnt.hxx>
30 #include <IDocumentUndoRedo.hxx>
31 #include <IDocumentLinksAdministration.hxx>
32 #include <IDocumentLayoutAccess.hxx>
33 #include <IDocumentFieldsAccess.hxx>
34 #include <IDocumentRedlineAccess.hxx>
35 #include <IDocumentState.hxx>
36 #include <rootfrm.hxx>
39 #include <section.hxx>
40 #include <UndoSection.hxx>
41 #include <UndoDelete.hxx>
44 #include <swtable.hxx>
47 #include <frmtool.hxx>
50 #include <redline.hxx>
51 #include <sectfrm.hxx>
53 #include <node2lay.hxx>
55 #include <fmtftntx.hxx>
56 #include <strings.hrc>
60 #include <tools/datetimeutils.hxx>
61 #include <o3tl/string_view.hxx>
63 // #i21457# - new implementation of local method <lcl_IsInSameTableBox(..)>.
64 // Method now determines the previous/next on its own. Thus, it can be controlled,
65 // for which previous/next is checked, if it's visible.
66 static bool lcl_IsInSameTableBox(const SwNode
& _rNd
, const bool _bPrev
)
68 const SwTableNode
* pTableNd
= _rNd
.FindTableNode();
74 // determine index to be checked. Its assumed that a previous/next exist.
75 SwNodeIndex
aChkIdx( _rNd
);
77 // determine index of previous/next - skip hidden ones, which are
79 // If found one is before/after table, this one isn't in the same
80 // table box as <_rNd>.
84 ? !SwNodes::GoPrevSection( &aChkIdx
, false, false )
85 : !SwNodes::GoNextSection( &aChkIdx
, false, false ) )
87 OSL_FAIL( "<lcl_IsInSameTableBox(..)> - no previous/next!" );
91 if ( aChkIdx
< pTableNd
->GetIndex() ||
92 aChkIdx
> pTableNd
->EndOfSectionNode()->GetIndex() )
97 // check, if found one isn't inside a hidden section, which
98 // is also inside the table.
99 SwSectionNode
* pSectNd
= aChkIdx
.GetNode().FindSectionNode();
101 pSectNd
->GetIndex() < pTableNd
->GetIndex() ||
102 !pSectNd
->GetSection().IsHiddenFlag() )
108 // Find the Box's StartNode
109 const SwTableSortBoxes
& rSortBoxes
= pTableNd
->GetTable().GetTabSortBoxes();
110 SwNodeOffset nIdx
= _rNd
.GetIndex();
111 for (size_t n
= 0; n
< rSortBoxes
.size(); ++n
)
113 const SwStartNode
* pNd
= rSortBoxes
[ n
]->GetSttNd();
114 if ( pNd
->GetIndex() < nIdx
&& nIdx
< pNd
->EndOfSectionIndex() )
116 // The other index needs to be within the same Section
117 nIdx
= aChkIdx
.GetIndex();
118 return pNd
->GetIndex() < nIdx
&& nIdx
< pNd
->EndOfSectionIndex();
125 static void lcl_CheckEmptyLayFrame( SwSectionData
& rSectionData
,
126 const SwNode
& rStt
, const SwNode
& rEnd
)
128 SwNodeIndex
aIdx( rStt
);
129 if( !SwNodes::GoPrevSection( &aIdx
, true, false ) ||
130 !CheckNodesRange( rStt
, aIdx
.GetNode(), true ) ||
132 !lcl_IsInSameTableBox( rStt
, true ))
135 if( !SwNodes::GoNextSection( &aIdx
, true, false ) ||
136 !CheckNodesRange( rEnd
, aIdx
.GetNode(), true ) ||
138 !lcl_IsInSameTableBox( rEnd
, false ))
140 rSectionData
.SetHidden( false );
146 SwDoc::InsertSwSection(SwPaM
const& rRange
, SwSectionData
& rNewData
,
147 std::tuple
<SwTOXBase
const*, sw::RedlineMode
, sw::FieldmarkMode
, sw::ParagraphBreakMode
> const*const pTOXBaseAndMode
,
148 SfxItemSet
const*const pAttr
, bool const bUpdate
)
150 const SwNode
* pPrvNd
= nullptr;
151 sal_uInt16 nRegionRet
= 0;
152 if( rRange
.HasMark() )
154 nRegionRet
= IsInsRegionAvailable( rRange
, &pPrvNd
);
155 if( 0 == nRegionRet
)
157 // demoted to info because this is called from SwXTextSection::attach,
158 // so it could be invalid input
159 SAL_INFO("sw.core" , "InsertSwSection: rRange overlaps other sections");
164 // See if the whole Document should be hidden, which we currently are not able to do.
165 if (rNewData
.IsHidden() && rRange
.HasMark())
167 auto [pStart
, pEnd
] = rRange
.StartEnd(); // SwPosition*
168 if( !pStart
->GetContentIndex() &&
169 pEnd
->GetNode().GetContentNode()->Len() ==
170 pEnd
->GetContentIndex() )
172 ::lcl_CheckEmptyLayFrame(
179 SwUndoInsSection
* pUndoInsSect
= nullptr;
180 bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
183 pUndoInsSect
= new SwUndoInsSection(rRange
, rNewData
, pAttr
, pTOXBaseAndMode
);
184 GetIDocumentUndoRedo().AppendUndo( std::unique_ptr
<SwUndo
>(pUndoInsSect
) );
185 GetIDocumentUndoRedo().DoUndo(false);
188 SwSectionFormat
* const pFormat
= MakeSectionFormat();
189 pFormat
->SetFormatName(rNewData
.GetSectionName());
192 pFormat
->SetFormatAttr( *pAttr
);
195 SwTOXBase
const*const pTOXBase(pTOXBaseAndMode
? std::get
<0>(*pTOXBaseAndMode
) : nullptr);
196 SwSectionNode
* pNewSectNode
= nullptr;
198 RedlineFlags eOld
= getIDocumentRedlineAccess().GetRedlineFlags();
199 getIDocumentRedlineAccess().SetRedlineFlags_intern( (eOld
& ~RedlineFlags::ShowMask
) | RedlineFlags::Ignore
);
201 if( rRange
.HasMark() )
203 auto [pSttPos
, pEndPos
] = const_cast<SwPaM
&>(rRange
).StartEnd(); // SwPosition*
204 if( pPrvNd
&& 3 == nRegionRet
)
206 OSL_ENSURE( pPrvNd
, "The SectionNode is missing" );
207 SwNodeIndex
aStt( pSttPos
->GetNode() ), aEnd( pEndPos
->GetNode(), +1 );
208 while( pPrvNd
!= aStt
.GetNode().StartOfSectionNode() )
210 while( pPrvNd
!= aEnd
.GetNode().StartOfSectionNode() )
213 --aEnd
; // End is inclusive in the InsertSection
214 pNewSectNode
= GetNodes().InsertTextSection(
215 aStt
.GetNode(), *pFormat
, rNewData
, pTOXBase
, & aEnd
.GetNode());
221 if( !( pPrvNd
&& 1 == nRegionRet
) &&
222 pSttPos
->GetContentIndex() )
224 SwTextNode
* const pTNd
=
225 pSttPos
->GetNode().GetTextNode();
228 pUndoInsSect
->SaveSplitNode( pTNd
, true );
232 if ( !( pPrvNd
&& 2 == nRegionRet
) )
234 SwTextNode
*const pTNd
=
235 pEndPos
->GetNode().GetTextNode();
236 if (pTNd
&& (pTNd
->GetText().getLength()
237 != pEndPos
->GetContentIndex()))
239 pUndoInsSect
->SaveSplitNode( pTNd
, false );
244 if( pPrvNd
&& 1 == nRegionRet
)
246 pSttPos
->Assign( *pPrvNd
);
248 else if( pSttPos
->GetContentIndex() )
250 getIDocumentContentOperations().SplitNode( *pSttPos
, false );
253 if( pPrvNd
&& 2 == nRegionRet
)
255 pEndPos
->Assign( *pPrvNd
);
259 const SwContentNode
* pCNd
= pEndPos
->GetNode().GetContentNode();
260 if( pCNd
&& pCNd
->Len() != pEndPos
->GetContentIndex() )
262 sal_Int32 nContent
= pSttPos
->GetContentIndex();
263 getIDocumentContentOperations().SplitNode( *pEndPos
, false );
266 if( pEndPos
->GetNodeIndex() == pSttPos
->GetNodeIndex() )
268 pSttPos
->Adjust(SwNodeOffset(-1));
269 pEndPos
->Adjust(SwNodeOffset(-1));
270 pTNd
= pSttPos
->GetNode().GetTextNode();
271 pSttPos
->SetContent( nContent
);
275 // Set to the end of the previous
276 pEndPos
->Adjust(SwNodeOffset(-1));
277 pTNd
= pEndPos
->GetNode().GetTextNode();
279 nContent
= pTNd
? pTNd
->GetText().getLength() : 0;
280 pEndPos
->SetContent( nContent
);
283 pNewSectNode
= GetNodes().InsertTextSection(
284 pSttPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, &pEndPos
->GetNode());
289 const SwPosition
* pPos
= rRange
.GetPoint();
290 const SwContentNode
* pCNd
= pPos
->GetNode().GetContentNode();
291 if( !pPos
->GetContentIndex() )
293 pNewSectNode
= GetNodes().InsertTextSection(
294 pPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, nullptr);
296 else if( pPos
->GetContentIndex() == pCNd
->Len() )
298 pNewSectNode
= GetNodes().InsertTextSection(
299 pPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, nullptr, false);
304 if (const SwTextNode
* pTextNode
= pCNd
->GetTextNode())
305 pUndoInsSect
->SaveSplitNode(pTextNode
, true);
306 getIDocumentContentOperations().SplitNode( *pPos
, false );
307 pNewSectNode
= GetNodes().InsertTextSection(
308 pPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, nullptr);
312 pNewSectNode
->CheckSectionCondColl();
314 getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
316 // To-Do - add 'SwExtraRedlineTable' also ?
317 if( getIDocumentRedlineAccess().IsRedlineOn() || (!getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() ))
319 SwPaM
aPam( *pNewSectNode
->EndOfSectionNode(), *pNewSectNode
, SwNodeOffset(1) );
320 if( getIDocumentRedlineAccess().IsRedlineOn() )
322 getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Insert
, aPam
), true);
326 getIDocumentRedlineAccess().SplitRedline( aPam
);
330 // Is a Condition set?
331 if (rNewData
.IsHidden() && !rNewData
.GetCondition().isEmpty())
333 // The calculate up to that position
334 SwCalc
aCalc( *this );
335 if( ! IsInReading() )
337 getIDocumentFieldsAccess().FieldsToCalc(aCalc
, pNewSectNode
->GetIndex(), SAL_MAX_INT32
);
339 SwSection
& rNewSect
= pNewSectNode
->GetSection();
340 rNewSect
.SetCondHidden( aCalc
.Calculate( rNewSect
.GetCondition() ).GetBool() );
343 bool bUpdateFootnote
= false;
344 if( !GetFootnoteIdxs().empty() && pAttr
)
346 sal_uInt16 nVal
= pAttr
->Get( RES_FTN_AT_TXTEND
).GetValue();
347 if( ( FTNEND_ATTXTEND_OWNNUMSEQ
== nVal
||
348 FTNEND_ATTXTEND_OWNNUMANDFMT
== nVal
) ||
349 ( FTNEND_ATTXTEND_OWNNUMSEQ
== ( nVal
= pAttr
->Get( RES_END_AT_TXTEND
).GetValue() ) ||
350 FTNEND_ATTXTEND_OWNNUMANDFMT
== nVal
))
352 bUpdateFootnote
= true;
358 pUndoInsSect
->SetSectNdPos( pNewSectNode
->GetIndex() );
359 pUndoInsSect
->SetUpdateFootnoteFlag( bUpdateFootnote
);
360 GetIDocumentUndoRedo().DoUndo(bUndo
);
363 if (rNewData
.IsLinkType())
365 pNewSectNode
->GetSection().CreateLink( bUpdate
? LinkCreateType::Update
: LinkCreateType::Connect
);
368 if( bUpdateFootnote
)
370 GetFootnoteIdxs().UpdateFootnote( *pNewSectNode
);
373 getIDocumentState().SetModified();
374 return &pNewSectNode
->GetSection();
377 sal_uInt16
SwDoc::IsInsRegionAvailable( const SwPaM
& rRange
,
378 const SwNode
** ppSttNd
)
381 if( rRange
.HasMark() )
383 // See if we have a valid Section
384 auto [pStart
, pEnd
] = rRange
.StartEnd(); // SwPosition*
386 const SwContentNode
* pCNd
= pEnd
->GetNode().GetContentNode();
387 const SwNode
* pNd
= &pStart
->GetNode();
388 const SwSectionNode
* pSectNd
= pNd
->FindSectionNode();
389 const SwSectionNode
* pEndSectNd
= pCNd
? pCNd
->FindSectionNode() : nullptr;
390 if( pSectNd
&& pEndSectNd
&& pSectNd
!= pEndSectNd
)
392 // Try to create an enclosing Section, but only if Start is
393 // located at the Section's beginning and End at it's end
395 if( !pStart
->GetContentIndex()
396 && pSectNd
->GetIndex() == pStart
->GetNodeIndex() - 1
397 && pEnd
->GetContentIndex() == pCNd
->Len() )
399 SwNodeIndex
aIdx( pStart
->GetNode(), -1 );
400 SwNodeOffset nCmp
= pEnd
->GetNodeIndex();
401 const SwStartNode
* pPrvNd
;
402 const SwEndNode
* pNxtNd
;
403 while( nullptr != ( pPrvNd
= (pNd
= &aIdx
.GetNode())->GetSectionNode() ) &&
404 ( aIdx
.GetIndex() >= nCmp
||
405 nCmp
>= pPrvNd
->EndOfSectionIndex() ) )
410 pPrvNd
= pNd
->IsStartNode() ? static_cast<const SwStartNode
*>(pNd
)
411 : pNd
->StartOfSectionNode();
413 aIdx
= pEnd
->GetNodeIndex() + 1;
414 nCmp
= pStart
->GetNodeIndex();
415 while( nullptr != ( pNxtNd
= (pNd
= &aIdx
.GetNode())->GetEndNode() ) &&
416 pNxtNd
->StartOfSectionNode()->IsSectionNode() &&
417 ( pNxtNd
->StartOfSectionIndex() >= nCmp
||
418 nCmp
>= aIdx
.GetIndex() ) )
423 pNxtNd
= pNd
->EndOfSectionNode();
425 if( pPrvNd
&& pNxtNd
&& pPrvNd
== pNxtNd
->StartOfSectionNode() )
434 else if( !pSectNd
&& pEndSectNd
)
436 // Try to create an enclosing Section, but only if the End
437 // is at the Section's end.
439 if( pEnd
->GetContentIndex() == pCNd
->Len() )
441 SwNodeIndex
aIdx( pEnd
->GetNode(), 1 );
442 if( aIdx
.GetNode().IsEndNode() &&
443 nullptr != aIdx
.GetNode().FindSectionNode() )
447 } while( aIdx
.GetNode().IsEndNode() &&
448 nullptr != aIdx
.GetNode().FindSectionNode() );
454 *ppSttNd
= &aIdx
.GetNode();
460 else if( pSectNd
&& !pEndSectNd
)
462 // Try to create an enclosing Section, but only if Start
463 // is at the Section's start.
465 if( !pStart
->GetContentIndex() )
467 SwNodeIndex
aIdx( pStart
->GetNode(), -1 );
468 if( aIdx
.GetNode().IsSectionNode() )
472 } while( aIdx
.GetNode().IsSectionNode() );
473 if( !aIdx
.GetNode().IsSectionNode() )
479 *ppSttNd
= &aIdx
.GetNode();
489 SwSection
* SwDoc::GetCurrSection( const SwPosition
& rPos
)
491 SwSectionNode
* pSectNd
= rPos
.GetNode().FindSectionNode();
493 return &pSectNd
->GetSection();
497 SwSectionFormat
* SwDoc::MakeSectionFormat()
499 SwSectionFormat
* pNew
= new SwSectionFormat( mpDfltFrameFormat
.get(), this );
500 mpSectionFormatTable
->push_back( pNew
);
504 void SwDoc::DelSectionFormat( SwSectionFormat
*pFormat
, bool bDelNodes
)
506 SwSectionFormats::iterator itFormatPos
= std::find( mpSectionFormatTable
->begin(), mpSectionFormatTable
->end(), pFormat
);
508 GetIDocumentUndoRedo().StartUndo(SwUndoId::DELSECTION
, nullptr);
510 if( mpSectionFormatTable
->end() != itFormatPos
)
512 const SwNodeIndex
* pIdx
= pFormat
->GetContent( false ).GetContentIdx();
513 const SfxPoolItem
* pFootnoteEndAtTextEnd
= pFormat
->GetItemIfSet(
515 if( !pFootnoteEndAtTextEnd
)
516 pFootnoteEndAtTextEnd
= pFormat
->GetItemIfSet(RES_END_AT_TXTEND
);
518 SwSectionNode
* pSectNd
;
520 if( GetIDocumentUndoRedo().DoesUndo() )
522 if( bDelNodes
&& pIdx
&& &GetNodes() == &pIdx
->GetNodes() &&
523 nullptr != (pSectNd
= pIdx
->GetNode().GetSectionNode() ))
525 SwNodeIndex
aUpdIdx( *pIdx
);
526 SwPaM
aPaM( *pSectNd
->EndOfSectionNode(), *pSectNd
);
527 GetIDocumentUndoRedo().AppendUndo(std::make_unique
<SwUndoDelete
>(aPaM
, SwDeleteFlags::Default
));
528 if( pFootnoteEndAtTextEnd
)
529 GetFootnoteIdxs().UpdateFootnote( aUpdIdx
.GetNode() );
530 getIDocumentState().SetModified();
531 //#126178# start/end undo have to be pairs!
532 GetIDocumentUndoRedo().EndUndo(SwUndoId::DELSECTION
, nullptr);
535 GetIDocumentUndoRedo().AppendUndo( MakeUndoDelSection( *pFormat
) );
537 else if( bDelNodes
&& pIdx
&& &GetNodes() == &pIdx
->GetNodes() &&
538 nullptr != (pSectNd
= pIdx
->GetNode().GetSectionNode() ))
540 SwNodeIndex
aUpdIdx( *pIdx
);
541 getIDocumentContentOperations().DeleteSection(pSectNd
);
542 if( pFootnoteEndAtTextEnd
)
543 GetFootnoteIdxs().UpdateFootnote( aUpdIdx
.GetNode() );
544 getIDocumentState().SetModified();
545 //#126178# start/end undo have to be pairs!
546 GetIDocumentUndoRedo().EndUndo(SwUndoId::DELSECTION
, nullptr);
550 pFormat
->RemoveAllUnos();
552 // A ClearRedo could result in a recursive call of this function and delete some section
553 // formats, thus the position inside the SectionFormatTable could have changed
554 itFormatPos
= std::find( mpSectionFormatTable
->begin(), mpSectionFormatTable
->end(), pFormat
);
556 // WARNING: First remove from the array and then delete,
557 // as the Section DTOR tries to delete it's format itself.
558 mpSectionFormatTable
->erase( itFormatPos
);
560 SwNodeOffset
nCnt(0), nSttNd(0);
561 if( pIdx
&& &GetNodes() == &pIdx
->GetNodes() &&
562 nullptr != (pSectNd
= pIdx
->GetNode().GetSectionNode() ))
564 nSttNd
= pSectNd
->GetIndex();
565 nCnt
= pSectNd
->EndOfSectionIndex() - nSttNd
- 1;
570 if( nSttNd
&& pFootnoteEndAtTextEnd
)
572 SwNodeIndex
aUpdIdx( GetNodes(), nSttNd
);
573 GetFootnoteIdxs().UpdateFootnote( aUpdIdx
.GetNode() );
577 for( ; nCnt
--; ++nSttNd
)
578 if( nullptr != (pCNd
= GetNodes()[ nSttNd
]->GetContentNode() ) &&
579 RES_CONDTXTFMTCOLL
== pCNd
->GetFormatColl()->Which() )
583 GetIDocumentUndoRedo().EndUndo(SwUndoId::DELSECTION
, nullptr);
585 if (GetIDocumentUndoRedo().DoesUndo())
586 { // TODO is this ever needed?
587 getIDocumentState().SetModified();
591 void SwDoc::UpdateSection( size_t const nPos
, SwSectionData
& rNewData
,
592 SfxItemSet
const*const pAttr
, bool const bPreventLinkUpdate
)
594 SwSectionFormat
* pFormat
= (*mpSectionFormatTable
)[ nPos
];
595 SwSection
* pSection
= pFormat
->GetSection();
597 /// remember hidden condition flag of SwSection before changes
598 bool bOldCondHidden
= pSection
->IsCondHidden();
600 if (pSection
->DataEquals(rNewData
))
603 bool bOnlyAttrChg
= false;
604 if( pAttr
&& pAttr
->Count() )
606 SfxItemIter
aIter( *pAttr
);
607 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
610 if (pFormat
->GetFormatAttr(pItem
->Which()) != *pItem
)
616 pItem
= aIter
.NextItem();
622 if (GetIDocumentUndoRedo().DoesUndo())
624 GetIDocumentUndoRedo().AppendUndo(
625 MakeUndoUpdateSection( *pFormat
, true ) );
627 // #i32968# Inserting columns in the section causes MakeFrameFormat
628 // to put two objects of type SwUndoFrameFormat on the undo stack.
629 // We don't want them.
630 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
631 pFormat
->SetFormatAttr( *pAttr
);
632 getIDocumentState().SetModified();
637 // Test if the whole Content Section (Document/TableBox/Fly) should be hidden,
638 // which we're currently not able to do.
639 const SwNodeIndex
* pIdx
= nullptr;
641 if (rNewData
.IsHidden())
643 pIdx
= pFormat
->GetContent().GetContentIdx();
646 const SwSectionNode
* pSectNd
=
647 pIdx
->GetNode().GetSectionNode();
650 ::lcl_CheckEmptyLayFrame( rNewData
,
651 *pSectNd
, *pSectNd
->EndOfSectionNode() );
657 if (GetIDocumentUndoRedo().DoesUndo())
659 GetIDocumentUndoRedo().AppendUndo(MakeUndoUpdateSection(*pFormat
, false));
661 // #i32968# Inserting columns in the section causes MakeFrameFormat to put two
662 // objects of type SwUndoFrameFormat on the undo stack. We don't want them.
663 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
665 // The LinkFileName could only consist of separators
666 OUString sCompareString
= OUStringChar(sfx2::cTokenSeparator
) + OUStringChar(sfx2::cTokenSeparator
);
668 (!pSection
->IsLinkType() && rNewData
.IsLinkType())
669 || (!rNewData
.GetLinkFileName().isEmpty()
670 && (rNewData
.GetLinkFileName() != sCompareString
)
671 && (rNewData
.GetLinkFileName() != pSection
->GetLinkFileName()));
673 OUString
sSectName( rNewData
.GetSectionName() );
674 if (sSectName
!= pSection
->GetSectionName())
675 sSectName
= GetUniqueSectionName( &sSectName
);
679 /// In SwSection::operator=(..) class member m_bCondHiddenFlag is always set to true.
680 /// IMHO this have to be changed, but I can't estimate the consequences:
681 /// Either it is set to true using corresponding method <SwSection.SetCondHidden(..)>,
682 /// or it is set to the value of SwSection which is assigned to it.
683 /// Discussion with AMA results that the adjustment to the assignment operator
684 /// could be very risky.
685 pSection
->SetSectionData(rNewData
);
688 pSection
->GetFormat()->SetFormatAttr( *pAttr
);
690 if( !sSectName
.isEmpty() )
692 pSection
->SetSectionName( sSectName
);
695 // Is a Condition set
696 if( pSection
->IsHidden() && !pSection
->GetCondition().isEmpty() )
698 // Then calculate up to that position
699 SwCalc
aCalc( *this );
701 pIdx
= pFormat
->GetContent().GetContentIdx();
702 getIDocumentFieldsAccess().FieldsToCalc(aCalc
, pIdx
->GetIndex(), SAL_MAX_INT32
);
704 /// Because on using SwSection::operator=() to set up <pSection>
705 /// with <rNewData> and the above given note, the hidden condition flag
706 /// has to be set to false, if hidden condition flag of <pFormat->GetSection()>
707 /// (SwSection before the changes) is false (already saved in <bOldCondHidden>)
708 /// and new calculated condition is true.
709 /// This is necessary, because otherwise the <SetCondHidden> would have
711 bool bCalculatedCondHidden
=
712 aCalc
.Calculate( pSection
->GetCondition() ).GetBool();
713 if ( bCalculatedCondHidden
&& !bOldCondHidden
)
715 pSection
->SetCondHidden( false );
717 pSection
->SetCondHidden( bCalculatedCondHidden
);
721 pSection
->CreateLink( bPreventLinkUpdate
? LinkCreateType::Connect
: LinkCreateType::Update
);
722 else if( !pSection
->IsLinkType() && pSection
->IsConnected() )
724 pSection
->Disconnect();
725 getIDocumentLinksAdministration().GetLinkManager().Remove( &pSection
->GetBaseLink() );
728 getIDocumentState().SetModified();
731 void sw_DeleteFootnote( SwSectionNode
*pNd
, SwNodeOffset nStt
, SwNodeOffset nEnd
)
733 SwFootnoteIdxs
& rFootnoteArr
= pNd
->GetDoc().GetFootnoteIdxs();
734 if( rFootnoteArr
.empty() )
738 rFootnoteArr
.SeekEntry( *pNd
, &nPos
);
740 // Delete all succeeding Footnotes
741 while (nPos
< rFootnoteArr
.size())
743 SwTextFootnote
* pSrch
= rFootnoteArr
[nPos
];
744 if (SwTextFootnote_GetIndex(pSrch
) > nEnd
)
746 // If the Nodes are not deleted, they need to deregister at the Pages
747 // (delete Frames) or else they will remain there (Undo does not delete them!)
748 pSrch
->DelFrames(nullptr);
755 SwTextFootnote
* pSrch
= rFootnoteArr
[nPos
];
756 if (SwTextFootnote_GetIndex(pSrch
) < nStt
)
758 // If the Nodes are not deleted, they need to deregister at the Pages
759 // (delete Frames) or else they will remain there (Undo does not delete them!)
760 pSrch
->DelFrames(nullptr);
764 static bool lcl_IsTOXSection(SwSectionData
const& rSectionData
)
766 return (SectionType::ToxContent
== rSectionData
.GetType())
767 || (SectionType::ToxHeader
== rSectionData
.GetType());
770 SwSectionNode
* SwNodes::InsertTextSection(SwNode
& rNd
,
771 SwSectionFormat
& rSectionFormat
,
772 SwSectionData
const& rSectionData
,
773 SwTOXBase
const*const pTOXBase
,
774 SwNode
const*const pEndNd
,
775 bool const bInsAtStart
, bool const bCreateFrames
)
777 SwNodeIndex
aInsPos( rNd
);
778 if( !pEndNd
) // No Area, thus create a new Section before/after it
781 OSL_ENSURE(!pEndNd
|| rNd
.GetIndex() <= pEndNd
->GetIndex(),
782 "Section start and end in wrong order!");
786 if (!lcl_IsTOXSection(rSectionData
))
790 } while( aInsPos
.GetNode().IsSectionNode() );
797 if (!lcl_IsTOXSection(rSectionData
))
800 while( aInsPos
.GetIndex() < Count() - 1 &&
801 ( pNd
= &aInsPos
.GetNode())->IsEndNode() &&
802 pNd
->StartOfSectionNode()->IsSectionNode())
810 SwSectionNode
*const pSectNd
=
811 new SwSectionNode(aInsPos
.GetNode(), rSectionFormat
, pTOXBase
);
813 if (lcl_IsTOXSection(rSectionData
))
815 // We're inserting a ToX. Make sure that if a redline ends right before the ToX start, then
816 // that end now doesn't cross a section start node.
817 SwRedlineTable
& rRedlines
= GetDoc().getIDocumentRedlineAccess().GetRedlineTable();
818 for (SwRedlineTable::size_type nIndex
= 0; nIndex
< rRedlines
.size(); ++nIndex
)
820 SwRangeRedline
* pRedline
= rRedlines
[nIndex
];
821 if ( RedlineType::Delete
!= pRedline
->GetType() ||
822 !pRedline
->HasMark() || pRedline
->GetMark()->GetNode() != aInsPos
.GetNode() )
827 // The redline ends at the new section content start, so it originally ended before the
828 // section start: move it back.
829 SwPaM
aRedlineEnd(*pRedline
->GetMark());
830 aRedlineEnd
.Move(fnMoveBackward
);
831 *pRedline
->GetMark() = *aRedlineEnd
.GetPoint();
838 // Special case for the Reader/Writer
839 if( *pEndNd
!= GetEndOfContent() )
840 aInsPos
= pEndNd
->GetIndex()+1;
841 // #i58710: We created a RTF document with a section break inside a table cell
842 // We are not able to handle a section start inside a table and the section end outside.
843 const SwNode
* pLastNode
= pSectNd
->StartOfSectionNode()->EndOfSectionNode();
844 if( aInsPos
> pLastNode
->GetIndex() )
845 aInsPos
= pLastNode
->GetIndex();
846 // Another way round: if the section starts outside a table but the end is inside...
847 // aInsPos is at the moment the Position where my EndNode will be inserted
848 const SwStartNode
* pStartNode
= aInsPos
.GetNode().StartOfSectionNode();
849 // This StartNode should be in front of me, but if not, I want to survive
850 SwNodeOffset nMyIndex
= pSectNd
->GetIndex();
851 if( pStartNode
->GetIndex() > nMyIndex
) // Suspicious!
856 pTemp
= pStartNode
; // pTemp is a suspicious one
857 pStartNode
= pStartNode
->StartOfSectionNode();
859 while( pStartNode
->GetIndex() > nMyIndex
);
860 pTemp
= pTemp
->EndOfSectionNode();
861 // If it starts behind me but ends behind my end...
862 if( pTemp
->GetIndex() >= aInsPos
.GetIndex() )
863 aInsPos
= pTemp
->GetIndex()+1; // ...I have to correct my end position
868 SwTextNode
* pCpyTNd
= rNd
.GetTextNode();
871 SwTextNode
* pTNd
= new SwTextNode( aInsPos
.GetNode(), pCpyTNd
->GetTextColl() );
872 if( pCpyTNd
->HasSwAttrSet() )
874 // Move PageDesc/Break to the first Node of the section
875 const SfxItemSet
& rSet
= *pCpyTNd
->GetpSwAttrSet();
876 if( SfxItemState::SET
== rSet
.GetItemState( RES_BREAK
) ||
877 SfxItemState::SET
== rSet
.GetItemState( RES_PAGEDESC
))
879 SfxItemSet
aSet( rSet
);
881 pCpyTNd
->ResetAttr( RES_PAGEDESC
, RES_BREAK
);
884 aSet
.ClearItem( RES_PAGEDESC
);
885 aSet
.ClearItem( RES_BREAK
);
887 pTNd
->SetAttr( aSet
);
890 pTNd
->SetAttr( rSet
);
892 // Do not forget to create the Frame!
893 pCpyTNd
->MakeFramesForAdjacentContentNode(*pTNd
);
896 new SwTextNode( aInsPos
.GetNode(), GetDoc().GetDfltTextFormatColl() );
898 new SwEndNode( aInsPos
.GetNode(), *pSectNd
);
900 pSectNd
->GetSection().SetSectionData(rSectionData
);
901 SwSectionFormat
* pSectFormat
= pSectNd
->GetSection().GetFormat();
903 // We could optimize this, by not removing already contained Frames and recreating them,
904 // but by simply rewiring them
905 bool bInsFrame
= bCreateFrames
&& !pSectNd
->GetSection().IsHiddenFlag() &&
906 GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
907 std::optional
<SwNode2LayoutSaveUpperFrames
> oNode2Layout
;
910 if( !pSectNd
->GetNodes().FindPrvNxtFrameNode( *pSectNd
, pSectNd
->EndOfSectionNode() ) )
911 // Collect all Uppers
912 oNode2Layout
.emplace(*pSectNd
);
915 // Set the right StartNode for all in this Area
916 SwNodeOffset nEnd
= pSectNd
->EndOfSectionIndex();
917 SwNodeOffset nStart
= pSectNd
->GetIndex()+1;
918 SwNodeOffset nSkipIdx
= NODE_OFFSET_MAX
;
919 for( SwNodeOffset n
= nStart
; n
< nEnd
; ++n
)
921 SwNode
* pNd
= (*this)[n
];
923 // Attach all Sections in the NodeSection underneath the new one
924 if( NODE_OFFSET_MAX
== nSkipIdx
)
925 pNd
->m_pStartOfSection
= pSectNd
;
926 else if( n
>= nSkipIdx
)
927 nSkipIdx
= NODE_OFFSET_MAX
;
929 if( pNd
->IsStartNode() )
931 // Make up the Format's nesting
932 if( pNd
->IsSectionNode() )
934 static_cast<SwSectionNode
*>(pNd
)->GetSection().GetFormat()->
935 SetDerivedFrom( pSectFormat
);
936 static_cast<SwSectionNode
*>(pNd
)->DelFrames();
937 n
= pNd
->EndOfSectionIndex();
941 if( pNd
->IsTableNode() )
942 static_cast<SwTableNode
*>(pNd
)->DelFrames();
944 if( NODE_OFFSET_MAX
== nSkipIdx
)
945 nSkipIdx
= pNd
->EndOfSectionIndex();
948 else if( pNd
->IsContentNode() )
949 static_cast<SwContentNode
*>(pNd
)->DelFrames(nullptr);
952 sw_DeleteFootnote( pSectNd
, nStart
, nEnd
);
958 SwNodeOffset nIdx
= pSectNd
->GetIndex();
959 oNode2Layout
->RestoreUpperFrames( pSectNd
->GetNodes(), nIdx
, nIdx
+ 1 );
960 oNode2Layout
.reset();
963 pSectNd
->MakeOwnFrames(&aInsPos
);
969 SwSectionNode
* SwNode::FindSectionNode()
971 for (SwNode
* tmp
= this;; tmp
= tmp
->StartOfSectionNode())
972 if (SwSectionNode
* sectNode
= tmp
->GetSectionNode(); sectNode
|| !tmp
->GetIndex())
978 // ugly hack to make m_pSection const
979 static SwSectionFormat
&
980 lcl_initParent(SwSectionNode
& rThis
, SwSectionFormat
& rFormat
)
982 SwSectionNode
*const pParent
=
983 rThis
.StartOfSectionNode()->FindSectionNode();
986 // Register the Format at the right Parent
987 rFormat
.SetDerivedFrom( pParent
->GetSection().GetFormat() );
992 SwSectionNode::SwSectionNode(const SwNode
& rWhere
,
993 SwSectionFormat
& rFormat
, SwTOXBase
const*const pTOXBase
)
994 : SwStartNode( rWhere
, SwNodeType::Section
)
995 , m_pSection( pTOXBase
996 ? new SwTOXBaseSection(*pTOXBase
, lcl_initParent(*this, rFormat
))
997 : new SwSection( SectionType::Content
, rFormat
.GetName(),
998 lcl_initParent(*this, rFormat
) ) )
1000 // Set the connection from Format to Node
1001 // Suppress Modify; no one's interested anyway
1002 rFormat
.LockModify();
1003 rFormat
.SetFormatAttr( SwFormatContent( this ) );
1004 rFormat
.UnlockModify();
1007 SwSectionNode::~SwSectionNode()
1009 // mba: test if iteration works as clients will be removed in callback
1010 // use hint which allows to specify, if the content shall be saved or not
1011 m_pSection
->GetFormat()->CallSwClientNotify( SwSectionFrameMoveAndDeleteHint( true ) );
1012 SwSectionFormat
* pFormat
= m_pSection
->GetFormat();
1015 // Remove the Attribute, because the Section deletes it's Format
1016 // and it will neutralize the Section, if the Content Attribute is set
1017 pFormat
->LockModify();
1018 pFormat
->ResetFormatAttr( RES_CNTNT
);
1019 pFormat
->UnlockModify();
1023 SwFrame
* SwSectionNode::MakeFrame(SwFrame
* pSib
, bool bHidden
)
1025 m_pSection
->m_Data
.SetHiddenFlag(bHidden
);
1026 return new SwSectionFrame( *m_pSection
, pSib
);
1029 // Creates all Document Views for the preceding Node.
1030 // The created ContentFrames are attached to the corresponding Layout
1031 void SwSectionNode::MakeFramesForAdjacentContentNode(const SwNodeIndex
& rIdx
)
1033 // Take my successive or preceding ContentFrame
1034 SwNodes
& rNds
= GetNodes();
1035 if( !(rNds
.IsDocNodes() && rNds
.GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell()) )
1038 if (GetSection().IsHiddenFlag() || IsContentHidden())
1040 SwNodeIndex
aIdx( *EndOfSectionNode() );
1041 SwContentNode
* pCNd
= SwNodes::GoNextSection(&aIdx
, true, false);
1045 pCNd
= SwNodes::GoPrevSection(&aIdx
, true, false);
1049 pCNd
= aIdx
.GetNode().GetContentNode();
1050 pCNd
->MakeFramesForAdjacentContentNode(static_cast<SwContentNode
&>(rIdx
.GetNode()));
1054 SwNode2Layout
aNode2Layout( *this, rIdx
.GetIndex() );
1056 while( nullptr != (pFrame
= aNode2Layout
.NextFrame()) )
1058 OSL_ENSURE( pFrame
->IsSctFrame(), "Depend of Section not a Section." );
1059 if (pFrame
->getRootFrame()->HasMergedParas()
1060 && !rIdx
.GetNode().IsCreateFrameWhenHidingRedlines())
1064 SwFrame
*pNew
= rIdx
.GetNode().GetContentNode()->MakeFrame( pFrame
);
1066 SwSectionNode
* pS
= rIdx
.GetNode().FindSectionNode();
1068 // Assure that node is not inside a table, which is inside the
1072 SwTableNode
* pTableNode
= rIdx
.GetNode().FindTableNode();
1074 pTableNode
->GetIndex() > pS
->GetIndex() )
1080 // if the node is in a section, the sectionframe now
1081 // has to be created...
1082 // boolean to control <Init()> of a new section frame.
1083 bool bInitNewSect
= false;
1086 SwSectionFrame
*pSct
= new SwSectionFrame( pS
->GetSection(), pFrame
);
1087 // prepare <Init()> of new section frame.
1088 bInitNewSect
= true;
1089 SwLayoutFrame
* pUp
= pSct
;
1090 while( pUp
->Lower() ) // for columned sections
1092 OSL_ENSURE( pUp
->Lower()->IsLayoutFrame(),"Who's in there?" );
1093 pUp
= static_cast<SwLayoutFrame
*>(pUp
->Lower());
1097 // notify accessibility paragraphs objects about changed
1098 // CONTENT_FLOWS_FROM/_TO relation.
1099 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1100 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1101 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1102 if ( pNew
->IsTextFrame() )
1104 SwViewShell
* pViewShell( pNew
->getRootFrame()->GetCurrShell() );
1105 if ( pViewShell
&& pViewShell
->GetLayout() &&
1106 pViewShell
->GetLayout()->IsAnyShellAccessible() )
1108 auto pNext
= pNew
->FindNextCnt( true );
1109 auto pPrev
= pNew
->FindPrevCnt();
1110 pViewShell
->InvalidateAccessibleParaFlowRelation(
1111 pNext
? pNext
->DynCastTextFrame() : nullptr,
1112 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1119 // If a Node got Frames attached before or after
1120 if ( rIdx
< GetIndex() )
1121 // the new one precedes me
1122 pNew
->Paste( pFrame
->GetUpper(), pFrame
);
1124 // the new one succeeds me
1125 pNew
->Paste( pFrame
->GetUpper(), pFrame
->GetNext() );
1127 // notify accessibility paragraphs objects about changed
1128 // CONTENT_FLOWS_FROM/_TO relation.
1129 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1130 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1131 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1132 if ( pNew
->IsTextFrame() )
1134 SwViewShell
* pViewShell( pNew
->getRootFrame()->GetCurrShell() );
1135 if ( pViewShell
&& pViewShell
->GetLayout() &&
1136 pViewShell
->GetLayout()->IsAnyShellAccessible() )
1138 auto pNext
= pNew
->FindNextCnt( true );
1139 auto pPrev
= pNew
->FindPrevCnt();
1140 pViewShell
->InvalidateAccessibleParaFlowRelation(
1141 pNext
? pNext
->DynCastTextFrame() : nullptr,
1142 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1147 static_cast<SwSectionFrame
*>(pNew
)->Init();
1152 // Create a new SectionFrame for every occurrence in the Layout and insert before
1153 // the corresponding ContentFrame
1154 void SwSectionNode::MakeOwnFrames(SwNodeIndex
* pIdxBehind
, SwNodeIndex
* pEndIdx
)
1156 assert(pIdxBehind
&& "no Index");
1157 SwNodes
& rNds
= GetNodes();
1158 SwDoc
& rDoc
= rNds
.GetDoc();
1160 *pIdxBehind
= *this;
1162 m_pSection
->m_Data
.SetHiddenFlag(true);
1164 if( rNds
.IsDocNodes() )
1167 ::MakeFrames( &rDoc
, pIdxBehind
->GetNode(), pEndIdx
->GetNode() );
1169 ::MakeFrames( &rDoc
, pIdxBehind
->GetNode(), SwNodeIndex( *EndOfSectionNode(), 1 ).GetNode() );
1173 void SwSectionNode::DelFrames(SwRootFrame
const*const /*FIXME TODO*/, bool const bForce
)
1175 SwNodeOffset nStt
= GetIndex()+1, nEnd
= EndOfSectionIndex();
1181 m_pSection
->GetFormat()->DelFrames();
1184 m_pSection
->m_Data
.SetHiddenFlag(true);
1186 // If the Area is within a Fly or TableBox, we can only hide it if
1187 // there is more Content which has Frames.
1188 // Or else the Fly/TableBox Frame does not have a Lower!
1192 SwNodeIndex
aIdx( *this );
1193 if( !SwNodes::GoPrevSection( &aIdx
, true, false ) ||
1194 !CheckNodesRange( *this, aIdx
.GetNode(), true ) ||
1196 !lcl_IsInSameTableBox( *this, true ))
1198 aIdx
= *EndOfSectionNode();
1199 if( !SwNodes::GoNextSection( &aIdx
, true, false ) ||
1200 !CheckNodesRange( *EndOfSectionNode(), aIdx
.GetNode(), true ) ||
1202 !lcl_IsInSameTableBox( *EndOfSectionNode(), false ))
1204 m_pSection
->m_Data
.SetHiddenFlag(false);
1209 SwSectionNode
* SwSectionNode::MakeCopy( SwDoc
& rDoc
, const SwNodeIndex
& rIdx
) const
1211 // In which array am I: Nodes, UndoNodes?
1212 const SwNodes
& rNds
= GetNodes();
1214 // Copy the SectionFrameFormat
1215 SwSectionFormat
* pSectFormat
= rDoc
.MakeSectionFormat();
1216 pSectFormat
->CopyAttrs( *GetSection().GetFormat() );
1218 std::unique_ptr
<SwTOXBase
> pTOXBase
;
1219 if (SectionType::ToxContent
== GetSection().GetType())
1221 assert( dynamic_cast< const SwTOXBaseSection
* >( &GetSection() ) && "no TOXBaseSection!" );
1222 SwTOXBaseSection
const& rTBS(
1223 dynamic_cast<SwTOXBaseSection
const&>(GetSection()));
1224 pTOXBase
.reset( new SwTOXBase(rTBS
, &rDoc
) );
1227 SwSectionNode
*const pSectNd
=
1228 new SwSectionNode(rIdx
.GetNode(), *pSectFormat
, pTOXBase
.get());
1229 SwEndNode
* pEndNd
= new SwEndNode( rIdx
.GetNode(), *pSectNd
);
1230 SwNodeIndex
aInsPos( *pEndNd
);
1233 SwSection
*const pNewSect
= pSectNd
->m_pSection
.get();
1235 if (SectionType::ToxContent
!= GetSection().GetType())
1237 // Keep the Name for Move
1238 if( &rNds
.GetDoc() == &rDoc
&& rDoc
.IsCopyIsMove() )
1240 pNewSect
->SetSectionName( GetSection().GetSectionName() );
1244 const OUString
sSectionName(GetSection().GetSectionName());
1245 pNewSect
->SetSectionName(rDoc
.GetUniqueSectionName( &sSectionName
));
1249 pNewSect
->SetType( GetSection().GetType() );
1250 pNewSect
->SetCondition( GetSection().GetCondition() );
1251 pNewSect
->SetCondHidden( GetSection().IsCondHidden() );
1252 pNewSect
->SetLinkFileName( GetSection().GetLinkFileName() );
1253 if( !pNewSect
->IsHiddenFlag() && GetSection().IsHidden() )
1254 pNewSect
->SetHidden();
1255 if( !pNewSect
->IsProtectFlag() && GetSection().IsProtect() )
1256 pNewSect
->SetProtect();
1257 // edit in readonly sections
1258 if( !pNewSect
->IsEditInReadonlyFlag() && GetSection().IsEditInReadonly() )
1259 pNewSect
->SetEditInReadonly();
1261 SwNodeRange
aRg( *this, SwNodeOffset(+1), *EndOfSectionNode() ); // Where am I?
1262 rNds
.Copy_( aRg
, aInsPos
.GetNode(), false );
1264 // Delete all Frames from the copied Area. They are created when creating
1265 // the SectionFrames.
1266 pSectNd
->DelFrames();
1268 // Copy the Links/Server
1269 if( pNewSect
->IsLinkType() ) // Add the Link
1270 pNewSect
->CreateLink( rDoc
.getIDocumentLayoutAccess().GetCurrentViewShell() ? LinkCreateType::Connect
: LinkCreateType::NONE
);
1272 // If we copy from the Undo as Server, enter it again
1273 if (m_pSection
->IsServer()
1274 && rDoc
.GetIDocumentUndoRedo().IsUndoNodes(rNds
))
1276 pNewSect
->SetRefObject( m_pSection
->GetObject() );
1277 rDoc
.getIDocumentLinksAdministration().GetLinkManager().InsertServer( pNewSect
->GetObject() );
1280 // METADATA: copy xml:id; must be done after insertion of node
1281 pSectFormat
->RegisterAsCopyOf(*GetSection().GetFormat());
1286 bool SwSectionNode::IsContentHidden() const
1288 OSL_ENSURE( !m_pSection
->IsHidden(),
1289 "That's simple: Hidden Section => Hidden Content" );
1290 SwNodeIndex
aTmp( *this, 1 );
1291 SwNodeOffset nEnd
= EndOfSectionIndex();
1292 while( aTmp
< nEnd
)
1294 if( aTmp
.GetNode().IsSectionNode() )
1296 const SwSection
& rSect
= static_cast<SwSectionNode
&>(aTmp
.GetNode()).GetSection();
1297 if( rSect
.IsHiddenFlag() )
1298 // Skip this Section
1299 aTmp
= *aTmp
.GetNode().EndOfSectionNode();
1303 if( aTmp
.GetNode().IsContentNode() || aTmp
.GetNode().IsTableNode() )
1304 return false; // We found non-hidden content
1305 OSL_ENSURE( aTmp
.GetNode().IsEndNode(), "EndNode expected" );
1309 return true; // Hide everything
1312 void SwSectionNode::dumpAsXml(xmlTextWriterPtr pWriter
) const
1314 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("section"));
1315 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1316 (void)xmlTextWriterWriteAttribute(
1317 pWriter
, BAD_CAST("type"),
1318 BAD_CAST(OString::number(static_cast<sal_uInt8
>(GetNodeType())).getStr()));
1319 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("index"),
1320 BAD_CAST(OString::number(sal_Int32(GetIndex())).getStr()));
1324 m_pSection
->dumpAsXml(pWriter
);
1327 // (void)xmlTextWriterEndElement(pWriter); - it is a start node, so don't end, will make xml better nested
1330 void SwSectionNode::NodesArrChgd()
1332 SwSectionFormat
*const pFormat
= m_pSection
->GetFormat();
1336 SwNodes
& rNds
= GetNodes();
1337 SwDoc
* pDoc
= pFormat
->GetDoc();
1339 if( !rNds
.IsDocNodes() )
1341 pFormat
->RemoveAllUnos();
1344 pFormat
->LockModify();
1345 pFormat
->SetFormatAttr( SwFormatContent( this ));
1346 pFormat
->UnlockModify();
1348 SwSectionNode
* pSectNd
= StartOfSectionNode()->FindSectionNode();
1349 // set the correct parent from the new section
1350 pFormat
->SetDerivedFrom( pSectNd
? pSectNd
->GetSection().GetFormat()
1351 : pDoc
->GetDfltFrameFormat() );
1353 // Set the right StartNode for all in this Area
1354 SwNodeOffset nStart
= GetIndex()+1, nEnd
= EndOfSectionIndex();
1355 for( SwNodeOffset n
= nStart
; n
< nEnd
; ++n
)
1357 // Make up the Format's nesting
1358 pSectNd
= rNds
[ n
]->GetSectionNode();
1359 if( nullptr != pSectNd
)
1361 pSectNd
->GetSection().GetFormat()->SetDerivedFrom( pFormat
);
1362 n
= pSectNd
->EndOfSectionIndex();
1366 // Moving Nodes to the UndoNodes array?
1367 if( rNds
.IsDocNodes() )
1369 OSL_ENSURE( pDoc
== &GetDoc(),
1370 "Moving to different Documents?" );
1371 if( m_pSection
->IsLinkType() ) // Remove the Link
1372 m_pSection
->CreateLink( pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() ? LinkCreateType::Connect
: LinkCreateType::NONE
);
1374 if (m_pSection
->IsServer())
1375 pDoc
->getIDocumentLinksAdministration().GetLinkManager().InsertServer( m_pSection
->GetObject() );
1379 if (SectionType::Content
!= m_pSection
->GetType()
1380 && m_pSection
->IsConnected())
1382 pDoc
->getIDocumentLinksAdministration().GetLinkManager().Remove( &m_pSection
->GetBaseLink() );
1384 if (m_pSection
->IsServer())
1385 pDoc
->getIDocumentLinksAdministration().GetLinkManager().RemoveServer( m_pSection
->GetObject() );
1390 OUString
SwDoc::GetUniqueSectionName( const OUString
* pChkStr
) const
1392 if( IsInMailMerge())
1394 OUString newName
= "MailMergeSection"
1395 + DateTimeToOUString( DateTime( DateTime::SYSTEM
) )
1396 + OUString::number( mpSectionFormatTable
->size() + 1 );
1398 newName
+= *pChkStr
;
1402 const OUString
aName(SwResId(STR_REGION_DEFNAME
));
1404 SwSectionFormats::size_type nNum
= 0;
1405 const SwSectionFormats::size_type nFlagSize
= ( mpSectionFormatTable
->size() / 8 ) + 2;
1406 std::unique_ptr
<sal_uInt8
[]> pSetFlags(new sal_uInt8
[ nFlagSize
]);
1407 memset( pSetFlags
.get(), 0, nFlagSize
);
1409 for( auto pFormat
: *mpSectionFormatTable
)
1411 const SwSectionNode
*const pSectNd
= pFormat
->GetSectionNode();
1412 if( pSectNd
!= nullptr )
1414 const OUString
& rNm
= pSectNd
->GetSection().GetSectionName();
1415 if (rNm
.startsWith( aName
))
1417 // Calculate the Number and reset the Flag
1418 nNum
= o3tl::toInt32(rNm
.subView( aName
.getLength() ));
1422 if (nNum
< mpSectionFormatTable
->size())
1424 pSetFlags
[ nNum
/ 8 ] |= (0x01 << ( nNum
& 0x07 ));
1428 if( pChkStr
&& *pChkStr
==rNm
)
1435 // Flagged all Numbers accordingly, so get the right Number
1436 nNum
= mpSectionFormatTable
->size();
1437 for( SwSectionFormats::size_type n
= 0; n
< nFlagSize
; ++n
)
1439 auto nTmp
= pSetFlags
[ n
];
1442 // Calculate the Number
1456 return aName
+ OUString::number( ++nNum
);
1459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */