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( SwNodes
const & _rNds
,
70 const SwTableNode
* pTableNd
= _rNd
.FindTableNode();
76 // determine index to be checked. Its assumed that a previous/next exist.
77 SwNodeIndex
aChkIdx( _rNd
);
79 // determine index of previous/next - skip hidden ones, which are
81 // If found one is before/after table, this one isn't in the same
82 // table box as <_rNd>.
86 ? !SwNodes::GoPrevSection( &aChkIdx
, false, false )
87 : !_rNds
.GoNextSection( &aChkIdx
, false, false ) )
89 OSL_FAIL( "<lcl_IsInSameTableBox(..)> - no previous/next!" );
93 if ( aChkIdx
< pTableNd
->GetIndex() ||
94 aChkIdx
> pTableNd
->EndOfSectionNode()->GetIndex() )
99 // check, if found one isn't inside a hidden section, which
100 // is also inside the table.
101 SwSectionNode
* pSectNd
= aChkIdx
.GetNode().FindSectionNode();
103 pSectNd
->GetIndex() < pTableNd
->GetIndex() ||
104 !pSectNd
->GetSection().IsHiddenFlag() )
110 // Find the Box's StartNode
111 const SwTableSortBoxes
& rSortBoxes
= pTableNd
->GetTable().GetTabSortBoxes();
112 SwNodeOffset nIdx
= _rNd
.GetIndex();
113 for (size_t n
= 0; n
< rSortBoxes
.size(); ++n
)
115 const SwStartNode
* pNd
= rSortBoxes
[ n
]->GetSttNd();
116 if ( pNd
->GetIndex() < nIdx
&& nIdx
< pNd
->EndOfSectionIndex() )
118 // The other index needs to be within the same Section
119 nIdx
= aChkIdx
.GetIndex();
120 return pNd
->GetIndex() < nIdx
&& nIdx
< pNd
->EndOfSectionIndex();
127 static void lcl_CheckEmptyLayFrame( SwNodes
const & rNds
, SwSectionData
& rSectionData
,
128 const SwNode
& rStt
, const SwNode
& rEnd
)
130 SwNodeIndex
aIdx( rStt
);
131 if( !SwNodes::GoPrevSection( &aIdx
, true, false ) ||
132 !CheckNodesRange( rStt
, aIdx
.GetNode(), true ) ||
134 !lcl_IsInSameTableBox( rNds
, rStt
, true ))
137 if( !rNds
.GoNextSection( &aIdx
, true, false ) ||
138 !CheckNodesRange( rEnd
, aIdx
.GetNode(), true ) ||
140 !lcl_IsInSameTableBox( rNds
, rEnd
, false ))
142 rSectionData
.SetHidden( false );
148 SwDoc::InsertSwSection(SwPaM
const& rRange
, SwSectionData
& rNewData
,
149 std::tuple
<SwTOXBase
const*, sw::RedlineMode
, sw::FieldmarkMode
, sw::ParagraphBreakMode
> const*const pTOXBaseAndMode
,
150 SfxItemSet
const*const pAttr
, bool const bUpdate
)
152 const SwNode
* pPrvNd
= nullptr;
153 sal_uInt16 nRegionRet
= 0;
154 if( rRange
.HasMark() )
156 nRegionRet
= IsInsRegionAvailable( rRange
, &pPrvNd
);
157 if( 0 == nRegionRet
)
159 // demoted to info because this is called from SwXTextSection::attach,
160 // so it could be invalid input
161 SAL_INFO("sw.core" , "InsertSwSection: rRange overlaps other sections");
166 // See if the whole Document should be hidden, which we currently are not able to do.
167 if (rNewData
.IsHidden() && rRange
.HasMark())
169 auto [pStt
, pEnd
] = rRange
.StartEnd(); // SwPosition*
170 if( !pStt
->GetContentIndex() &&
171 pEnd
->GetNode().GetContentNode()->Len() ==
172 pEnd
->GetContentIndex() )
174 ::lcl_CheckEmptyLayFrame( GetNodes(),
181 SwUndoInsSection
* pUndoInsSect
= nullptr;
182 bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
185 pUndoInsSect
= new SwUndoInsSection(rRange
, rNewData
, pAttr
, pTOXBaseAndMode
);
186 GetIDocumentUndoRedo().AppendUndo( std::unique_ptr
<SwUndo
>(pUndoInsSect
) );
187 GetIDocumentUndoRedo().DoUndo(false);
190 SwSectionFormat
* const pFormat
= MakeSectionFormat();
191 pFormat
->SetFormatName(rNewData
.GetSectionName());
194 pFormat
->SetFormatAttr( *pAttr
);
197 SwTOXBase
const*const pTOXBase(pTOXBaseAndMode
? std::get
<0>(*pTOXBaseAndMode
) : nullptr);
198 SwSectionNode
* pNewSectNode
= nullptr;
200 RedlineFlags eOld
= getIDocumentRedlineAccess().GetRedlineFlags();
201 getIDocumentRedlineAccess().SetRedlineFlags_intern( (eOld
& ~RedlineFlags::ShowMask
) | RedlineFlags::Ignore
);
203 if( rRange
.HasMark() )
205 auto [pSttPos
, pEndPos
] = const_cast<SwPaM
&>(rRange
).StartEnd(); // SwPosition*
206 if( pPrvNd
&& 3 == nRegionRet
)
208 OSL_ENSURE( pPrvNd
, "The SectionNode is missing" );
209 SwNodeIndex
aStt( pSttPos
->GetNode() ), aEnd( pEndPos
->GetNode(), +1 );
210 while( pPrvNd
!= aStt
.GetNode().StartOfSectionNode() )
212 while( pPrvNd
!= aEnd
.GetNode().StartOfSectionNode() )
215 --aEnd
; // End is inclusive in the InsertSection
216 pNewSectNode
= GetNodes().InsertTextSection(
217 aStt
.GetNode(), *pFormat
, rNewData
, pTOXBase
, & aEnd
.GetNode());
223 if( !( pPrvNd
&& 1 == nRegionRet
) &&
224 pSttPos
->GetContentIndex() )
226 SwTextNode
* const pTNd
=
227 pSttPos
->GetNode().GetTextNode();
230 pUndoInsSect
->SaveSplitNode( pTNd
, true );
234 if ( !( pPrvNd
&& 2 == nRegionRet
) )
236 SwTextNode
*const pTNd
=
237 pEndPos
->GetNode().GetTextNode();
238 if (pTNd
&& (pTNd
->GetText().getLength()
239 != pEndPos
->GetContentIndex()))
241 pUndoInsSect
->SaveSplitNode( pTNd
, false );
246 if( pPrvNd
&& 1 == nRegionRet
)
248 pSttPos
->Assign( *pPrvNd
);
250 else if( pSttPos
->GetContentIndex() )
252 getIDocumentContentOperations().SplitNode( *pSttPos
, false );
255 if( pPrvNd
&& 2 == nRegionRet
)
257 pEndPos
->Assign( *pPrvNd
);
261 const SwContentNode
* pCNd
= pEndPos
->GetNode().GetContentNode();
262 if( pCNd
&& pCNd
->Len() != pEndPos
->GetContentIndex() )
264 sal_Int32 nContent
= pSttPos
->GetContentIndex();
265 getIDocumentContentOperations().SplitNode( *pEndPos
, false );
268 if( pEndPos
->GetNodeIndex() == pSttPos
->GetNodeIndex() )
270 pSttPos
->Adjust(SwNodeOffset(-1));
271 pEndPos
->Adjust(SwNodeOffset(-1));
272 pTNd
= pSttPos
->GetNode().GetTextNode();
273 pSttPos
->SetContent( nContent
);
277 // Set to the end of the previous
278 pEndPos
->Adjust(SwNodeOffset(-1));
279 pTNd
= pEndPos
->GetNode().GetTextNode();
281 nContent
= pTNd
? pTNd
->GetText().getLength() : 0;
282 pEndPos
->SetContent( nContent
);
285 pNewSectNode
= GetNodes().InsertTextSection(
286 pSttPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, &pEndPos
->GetNode());
291 const SwPosition
* pPos
= rRange
.GetPoint();
292 const SwContentNode
* pCNd
= pPos
->GetNode().GetContentNode();
293 if( !pPos
->GetContentIndex() )
295 pNewSectNode
= GetNodes().InsertTextSection(
296 pPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, nullptr);
298 else if( pPos
->GetContentIndex() == pCNd
->Len() )
300 pNewSectNode
= GetNodes().InsertTextSection(
301 pPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, nullptr, false);
305 if( pUndoInsSect
&& pCNd
->IsTextNode() )
307 pUndoInsSect
->SaveSplitNode( const_cast<SwTextNode
*>(static_cast<const SwTextNode
*>(pCNd
)), true );
309 getIDocumentContentOperations().SplitNode( *pPos
, false );
310 pNewSectNode
= GetNodes().InsertTextSection(
311 pPos
->GetNode(), *pFormat
, rNewData
, pTOXBase
, nullptr);
315 pNewSectNode
->CheckSectionCondColl();
317 getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
319 // To-Do - add 'SwExtraRedlineTable' also ?
320 if( getIDocumentRedlineAccess().IsRedlineOn() || (!getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() ))
322 SwPaM
aPam( *pNewSectNode
->EndOfSectionNode(), *pNewSectNode
, SwNodeOffset(1) );
323 if( getIDocumentRedlineAccess().IsRedlineOn() )
325 getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Insert
, aPam
), true);
329 getIDocumentRedlineAccess().SplitRedline( aPam
);
333 // Is a Condition set?
334 if (rNewData
.IsHidden() && !rNewData
.GetCondition().isEmpty())
336 // The calculate up to that position
337 SwCalc
aCalc( *this );
338 if( ! IsInReading() )
340 getIDocumentFieldsAccess().FieldsToCalc(aCalc
, pNewSectNode
->GetIndex(), SAL_MAX_INT32
);
342 SwSection
& rNewSect
= pNewSectNode
->GetSection();
343 rNewSect
.SetCondHidden( aCalc
.Calculate( rNewSect
.GetCondition() ).GetBool() );
346 bool bUpdateFootnote
= false;
347 if( !GetFootnoteIdxs().empty() && pAttr
)
349 sal_uInt16 nVal
= pAttr
->Get( RES_FTN_AT_TXTEND
).GetValue();
350 if( ( FTNEND_ATTXTEND_OWNNUMSEQ
== nVal
||
351 FTNEND_ATTXTEND_OWNNUMANDFMT
== nVal
) ||
352 ( FTNEND_ATTXTEND_OWNNUMSEQ
== ( nVal
= pAttr
->Get( RES_END_AT_TXTEND
).GetValue() ) ||
353 FTNEND_ATTXTEND_OWNNUMANDFMT
== nVal
))
355 bUpdateFootnote
= true;
361 pUndoInsSect
->SetSectNdPos( pNewSectNode
->GetIndex() );
362 pUndoInsSect
->SetUpdateFootnoteFlag( bUpdateFootnote
);
363 GetIDocumentUndoRedo().DoUndo(bUndo
);
366 if (rNewData
.IsLinkType())
368 pNewSectNode
->GetSection().CreateLink( bUpdate
? LinkCreateType::Update
: LinkCreateType::Connect
);
371 if( bUpdateFootnote
)
373 GetFootnoteIdxs().UpdateFootnote( *pNewSectNode
);
376 getIDocumentState().SetModified();
377 return &pNewSectNode
->GetSection();
380 sal_uInt16
SwDoc::IsInsRegionAvailable( const SwPaM
& rRange
,
381 const SwNode
** ppSttNd
)
384 if( rRange
.HasMark() )
386 // See if we have a valid Section
387 auto [pStt
, pEnd
] = rRange
.StartEnd(); // SwPosition*
389 const SwContentNode
* pCNd
= pEnd
->GetNode().GetContentNode();
390 const SwNode
* pNd
= &pStt
->GetNode();
391 const SwSectionNode
* pSectNd
= pNd
->FindSectionNode();
392 const SwSectionNode
* pEndSectNd
= pCNd
? pCNd
->FindSectionNode() : nullptr;
393 if( pSectNd
&& pEndSectNd
&& pSectNd
!= pEndSectNd
)
395 // Try to create an enclosing Section, but only if Start is
396 // located at the Section's beginning and End at it's end
398 if( !pStt
->GetContentIndex()
399 && pSectNd
->GetIndex() == pStt
->GetNodeIndex() - 1
400 && pEnd
->GetContentIndex() == pCNd
->Len() )
402 SwNodeIndex
aIdx( pStt
->GetNode(), -1 );
403 SwNodeOffset nCmp
= pEnd
->GetNodeIndex();
404 const SwStartNode
* pPrvNd
;
405 const SwEndNode
* pNxtNd
;
406 while( nullptr != ( pPrvNd
= (pNd
= &aIdx
.GetNode())->GetSectionNode() ) &&
407 ( aIdx
.GetIndex() >= nCmp
||
408 nCmp
>= pPrvNd
->EndOfSectionIndex() ) )
413 pPrvNd
= pNd
->IsStartNode() ? static_cast<const SwStartNode
*>(pNd
)
414 : pNd
->StartOfSectionNode();
416 aIdx
= pEnd
->GetNodeIndex() + 1;
417 nCmp
= pStt
->GetNodeIndex();
418 while( nullptr != ( pNxtNd
= (pNd
= &aIdx
.GetNode())->GetEndNode() ) &&
419 pNxtNd
->StartOfSectionNode()->IsSectionNode() &&
420 ( pNxtNd
->StartOfSectionIndex() >= nCmp
||
421 nCmp
>= aIdx
.GetIndex() ) )
426 pNxtNd
= pNd
->EndOfSectionNode();
428 if( pPrvNd
&& pNxtNd
&& pPrvNd
== pNxtNd
->StartOfSectionNode() )
437 else if( !pSectNd
&& pEndSectNd
)
439 // Try to create an enclosing Section, but only if the End
440 // is at the Section's end.
442 if( pEnd
->GetContentIndex() == pCNd
->Len() )
444 SwNodeIndex
aIdx( pEnd
->GetNode(), 1 );
445 if( aIdx
.GetNode().IsEndNode() &&
446 nullptr != aIdx
.GetNode().FindSectionNode() )
450 } while( aIdx
.GetNode().IsEndNode() &&
451 nullptr != aIdx
.GetNode().FindSectionNode() );
457 *ppSttNd
= &aIdx
.GetNode();
463 else if( pSectNd
&& !pEndSectNd
)
465 // Try to create an enclosing Section, but only if Start
466 // is at the Section's start.
468 if( !pStt
->GetContentIndex() )
470 SwNodeIndex
aIdx( pStt
->GetNode(), -1 );
471 if( aIdx
.GetNode().IsSectionNode() )
475 } while( aIdx
.GetNode().IsSectionNode() );
476 if( !aIdx
.GetNode().IsSectionNode() )
482 *ppSttNd
= &aIdx
.GetNode();
492 SwSection
* SwDoc::GetCurrSection( const SwPosition
& rPos
)
494 const SwSectionNode
* pSectNd
= rPos
.GetNode().FindSectionNode();
496 return const_cast<SwSection
*>(&pSectNd
->GetSection());
500 SwSectionFormat
* SwDoc::MakeSectionFormat()
502 SwSectionFormat
* pNew
= new SwSectionFormat( mpDfltFrameFormat
.get(), this );
503 mpSectionFormatTable
->push_back( pNew
);
507 void SwDoc::DelSectionFormat( SwSectionFormat
*pFormat
, bool bDelNodes
)
509 SwSectionFormats::iterator itFormatPos
= std::find( mpSectionFormatTable
->begin(), mpSectionFormatTable
->end(), pFormat
);
511 GetIDocumentUndoRedo().StartUndo(SwUndoId::DELSECTION
, nullptr);
513 if( mpSectionFormatTable
->end() != itFormatPos
)
515 const SwNodeIndex
* pIdx
= pFormat
->GetContent( false ).GetContentIdx();
516 const SfxPoolItem
* pFootnoteEndAtTextEnd
= pFormat
->GetItemIfSet(
518 if( !pFootnoteEndAtTextEnd
)
519 pFootnoteEndAtTextEnd
= pFormat
->GetItemIfSet(RES_END_AT_TXTEND
);
521 const SwSectionNode
* pSectNd
;
523 if( GetIDocumentUndoRedo().DoesUndo() )
525 if( bDelNodes
&& pIdx
&& &GetNodes() == &pIdx
->GetNodes() &&
526 nullptr != (pSectNd
= pIdx
->GetNode().GetSectionNode() ))
528 SwNodeIndex
aUpdIdx( *pIdx
);
529 SwPaM
aPaM( *pSectNd
->EndOfSectionNode(), *pSectNd
);
530 GetIDocumentUndoRedo().AppendUndo(std::make_unique
<SwUndoDelete
>(aPaM
, SwDeleteFlags::Default
));
531 if( pFootnoteEndAtTextEnd
)
532 GetFootnoteIdxs().UpdateFootnote( aUpdIdx
.GetNode() );
533 getIDocumentState().SetModified();
534 //#126178# start/end undo have to be pairs!
535 GetIDocumentUndoRedo().EndUndo(SwUndoId::DELSECTION
, nullptr);
538 GetIDocumentUndoRedo().AppendUndo( MakeUndoDelSection( *pFormat
) );
540 else if( bDelNodes
&& pIdx
&& &GetNodes() == &pIdx
->GetNodes() &&
541 nullptr != (pSectNd
= pIdx
->GetNode().GetSectionNode() ))
543 SwNodeIndex
aUpdIdx( *pIdx
);
544 getIDocumentContentOperations().DeleteSection( const_cast<SwNode
*>(static_cast<SwNode
const *>(pSectNd
)) );
545 if( pFootnoteEndAtTextEnd
)
546 GetFootnoteIdxs().UpdateFootnote( aUpdIdx
.GetNode() );
547 getIDocumentState().SetModified();
548 //#126178# start/end undo have to be pairs!
549 GetIDocumentUndoRedo().EndUndo(SwUndoId::DELSECTION
, nullptr);
553 pFormat
->RemoveAllUnos();
555 // A ClearRedo could result in a recursive call of this function and delete some section
556 // formats, thus the position inside the SectionFormatTable could have changed
557 itFormatPos
= std::find( mpSectionFormatTable
->begin(), mpSectionFormatTable
->end(), pFormat
);
559 // WARNING: First remove from the array and then delete,
560 // as the Section DTOR tries to delete it's format itself.
561 mpSectionFormatTable
->erase( itFormatPos
);
563 SwNodeOffset
nCnt(0), nSttNd(0);
564 if( pIdx
&& &GetNodes() == &pIdx
->GetNodes() &&
565 nullptr != (pSectNd
= pIdx
->GetNode().GetSectionNode() ))
567 nSttNd
= pSectNd
->GetIndex();
568 nCnt
= pSectNd
->EndOfSectionIndex() - nSttNd
- 1;
573 if( nSttNd
&& pFootnoteEndAtTextEnd
)
575 SwNodeIndex
aUpdIdx( GetNodes(), nSttNd
);
576 GetFootnoteIdxs().UpdateFootnote( aUpdIdx
.GetNode() );
580 for( ; nCnt
--; ++nSttNd
)
581 if( nullptr != (pCNd
= GetNodes()[ nSttNd
]->GetContentNode() ) &&
582 RES_CONDTXTFMTCOLL
== pCNd
->GetFormatColl()->Which() )
586 GetIDocumentUndoRedo().EndUndo(SwUndoId::DELSECTION
, nullptr);
588 if (GetIDocumentUndoRedo().DoesUndo())
589 { // TODO is this ever needed?
590 getIDocumentState().SetModified();
594 void SwDoc::UpdateSection( size_t const nPos
, SwSectionData
& rNewData
,
595 SfxItemSet
const*const pAttr
, bool const bPreventLinkUpdate
)
597 SwSectionFormat
* pFormat
= (*mpSectionFormatTable
)[ nPos
];
598 SwSection
* pSection
= pFormat
->GetSection();
600 /// remember hidden condition flag of SwSection before changes
601 bool bOldCondHidden
= pSection
->IsCondHidden();
603 if (pSection
->DataEquals(rNewData
))
606 bool bOnlyAttrChg
= false;
607 if( pAttr
&& pAttr
->Count() )
609 SfxItemIter
aIter( *pAttr
);
610 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
613 if (pFormat
->GetFormatAttr(pItem
->Which()) != *pItem
)
619 pItem
= aIter
.NextItem();
625 if (GetIDocumentUndoRedo().DoesUndo())
627 GetIDocumentUndoRedo().AppendUndo(
628 MakeUndoUpdateSection( *pFormat
, true ) );
630 // #i32968# Inserting columns in the section causes MakeFrameFormat
631 // to put two objects of type SwUndoFrameFormat on the undo stack.
632 // We don't want them.
633 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
634 pFormat
->SetFormatAttr( *pAttr
);
635 getIDocumentState().SetModified();
640 // Test if the whole Content Section (Document/TableBox/Fly) should be hidden,
641 // which we're currently not able to do.
642 const SwNodeIndex
* pIdx
= nullptr;
644 if (rNewData
.IsHidden())
646 pIdx
= pFormat
->GetContent().GetContentIdx();
649 const SwSectionNode
* pSectNd
=
650 pIdx
->GetNode().GetSectionNode();
653 ::lcl_CheckEmptyLayFrame( GetNodes(), rNewData
,
654 *pSectNd
, *pSectNd
->EndOfSectionNode() );
660 if (GetIDocumentUndoRedo().DoesUndo())
662 GetIDocumentUndoRedo().AppendUndo(MakeUndoUpdateSection(*pFormat
, false));
664 // #i32968# Inserting columns in the section causes MakeFrameFormat to put two
665 // objects of type SwUndoFrameFormat on the undo stack. We don't want them.
666 ::sw::UndoGuard
const undoGuard(GetIDocumentUndoRedo());
668 // The LinkFileName could only consist of separators
669 OUString sCompareString
= OUStringChar(sfx2::cTokenSeparator
) + OUStringChar(sfx2::cTokenSeparator
);
671 (!pSection
->IsLinkType() && rNewData
.IsLinkType())
672 || (!rNewData
.GetLinkFileName().isEmpty()
673 && (rNewData
.GetLinkFileName() != sCompareString
)
674 && (rNewData
.GetLinkFileName() != pSection
->GetLinkFileName()));
676 OUString
sSectName( rNewData
.GetSectionName() );
677 if (sSectName
!= pSection
->GetSectionName())
678 sSectName
= GetUniqueSectionName( &sSectName
);
682 /// In SwSection::operator=(..) class member m_bCondHiddenFlag is always set to true.
683 /// IMHO this have to be changed, but I can't estimate the consequences:
684 /// Either it is set to true using corresponding method <SwSection.SetCondHidden(..)>,
685 /// or it is set to the value of SwSection which is assigned to it.
686 /// Discussion with AMA results that the adjustment to the assignment operator
687 /// could be very risky.
688 pSection
->SetSectionData(rNewData
);
691 pSection
->GetFormat()->SetFormatAttr( *pAttr
);
693 if( !sSectName
.isEmpty() )
695 pSection
->SetSectionName( sSectName
);
698 // Is a Condition set
699 if( pSection
->IsHidden() && !pSection
->GetCondition().isEmpty() )
701 // Then calculate up to that position
702 SwCalc
aCalc( *this );
704 pIdx
= pFormat
->GetContent().GetContentIdx();
705 getIDocumentFieldsAccess().FieldsToCalc(aCalc
, pIdx
->GetIndex(), SAL_MAX_INT32
);
707 /// Because on using SwSection::operator=() to set up <pSection>
708 /// with <rNewData> and the above given note, the hidden condition flag
709 /// has to be set to false, if hidden condition flag of <pFormat->GetSection()>
710 /// (SwSection before the changes) is false (already saved in <bOldCondHidden>)
711 /// and new calculated condition is true.
712 /// This is necessary, because otherwise the <SetCondHidden> would have
714 bool bCalculatedCondHidden
=
715 aCalc
.Calculate( pSection
->GetCondition() ).GetBool();
716 if ( bCalculatedCondHidden
&& !bOldCondHidden
)
718 pSection
->SetCondHidden( false );
720 pSection
->SetCondHidden( bCalculatedCondHidden
);
724 pSection
->CreateLink( bPreventLinkUpdate
? LinkCreateType::Connect
: LinkCreateType::Update
);
725 else if( !pSection
->IsLinkType() && pSection
->IsConnected() )
727 pSection
->Disconnect();
728 getIDocumentLinksAdministration().GetLinkManager().Remove( &pSection
->GetBaseLink() );
731 getIDocumentState().SetModified();
734 void sw_DeleteFootnote( SwSectionNode
*pNd
, SwNodeOffset nStt
, SwNodeOffset nEnd
)
736 SwFootnoteIdxs
& rFootnoteArr
= pNd
->GetDoc().GetFootnoteIdxs();
737 if( rFootnoteArr
.empty() )
741 rFootnoteArr
.SeekEntry( *pNd
, &nPos
);
742 SwTextFootnote
* pSrch
;
744 // Delete all succeeding Footnotes
745 while( nPos
< rFootnoteArr
.size() &&
746 SwTextFootnote_GetIndex( (pSrch
= rFootnoteArr
[ nPos
]) ) <= nEnd
)
748 // If the Nodes are not deleted, they need to deregister at the Pages
749 // (delete Frames) or else they will remain there (Undo does not delete them!)
750 pSrch
->DelFrames(nullptr);
755 SwTextFootnote_GetIndex( (pSrch
= rFootnoteArr
[ nPos
]) ) >= nStt
)
757 // If the Nodes are not deleted, they need to deregister at the Pages
758 // (delete Frames) or else they will remain there (Undo does not delete them!)
759 pSrch
->DelFrames(nullptr);
763 static bool lcl_IsTOXSection(SwSectionData
const& rSectionData
)
765 return (SectionType::ToxContent
== rSectionData
.GetType())
766 || (SectionType::ToxHeader
== rSectionData
.GetType());
769 SwSectionNode
* SwNodes::InsertTextSection(SwNode
& rNd
,
770 SwSectionFormat
& rSectionFormat
,
771 SwSectionData
const& rSectionData
,
772 SwTOXBase
const*const pTOXBase
,
773 SwNode
const*const pEndNd
,
774 bool const bInsAtStart
, bool const bCreateFrames
)
776 SwNodeIndex
aInsPos( rNd
);
777 if( !pEndNd
) // No Area, thus create a new Section before/after it
780 OSL_ENSURE(!pEndNd
|| rNd
.GetIndex() <= pEndNd
->GetIndex(),
781 "Section start and end in wrong order!");
785 if (!lcl_IsTOXSection(rSectionData
))
789 } while( aInsPos
.GetNode().IsSectionNode() );
796 if (!lcl_IsTOXSection(rSectionData
))
799 while( aInsPos
.GetIndex() < Count() - 1 &&
800 ( pNd
= &aInsPos
.GetNode())->IsEndNode() &&
801 pNd
->StartOfSectionNode()->IsSectionNode())
809 SwSectionNode
*const pSectNd
=
810 new SwSectionNode(aInsPos
.GetNode(), rSectionFormat
, pTOXBase
);
812 if (lcl_IsTOXSection(rSectionData
))
814 // We're inserting a ToX. Make sure that if a redline ends right before the ToX start, then
815 // that end now doesn't cross a section start node.
816 SwRedlineTable
& rRedlines
= GetDoc().getIDocumentRedlineAccess().GetRedlineTable();
817 for (SwRedlineTable::size_type nIndex
= 0; nIndex
< rRedlines
.size(); ++nIndex
)
819 SwRangeRedline
* pRedline
= rRedlines
[nIndex
];
820 if ( RedlineType::Delete
!= pRedline
->GetType() ||
821 !pRedline
->HasMark() || pRedline
->GetMark()->GetNode() != aInsPos
.GetNode() )
826 // The redline ends at the new section content start, so it originally ended before the
827 // section start: move it back.
828 SwPaM
aRedlineEnd(*pRedline
->GetMark());
829 aRedlineEnd
.Move(fnMoveBackward
);
830 *pRedline
->GetMark() = *aRedlineEnd
.GetPoint();
837 // Special case for the Reader/Writer
838 if( *pEndNd
!= GetEndOfContent() )
839 aInsPos
= pEndNd
->GetIndex()+1;
840 // #i58710: We created a RTF document with a section break inside a table cell
841 // We are not able to handle a section start inside a table and the section end outside.
842 const SwNode
* pLastNode
= pSectNd
->StartOfSectionNode()->EndOfSectionNode();
843 if( aInsPos
> pLastNode
->GetIndex() )
844 aInsPos
= pLastNode
->GetIndex();
845 // Another way round: if the section starts outside a table but the end is inside...
846 // aInsPos is at the moment the Position where my EndNode will be inserted
847 const SwStartNode
* pStartNode
= aInsPos
.GetNode().StartOfSectionNode();
848 // This StartNode should be in front of me, but if not, I want to survive
849 SwNodeOffset nMyIndex
= pSectNd
->GetIndex();
850 if( pStartNode
->GetIndex() > nMyIndex
) // Suspicious!
855 pTemp
= pStartNode
; // pTemp is a suspicious one
856 pStartNode
= pStartNode
->StartOfSectionNode();
858 while( pStartNode
->GetIndex() > nMyIndex
);
859 pTemp
= pTemp
->EndOfSectionNode();
860 // If it starts behind me but ends behind my end...
861 if( pTemp
->GetIndex() >= aInsPos
.GetIndex() )
862 aInsPos
= pTemp
->GetIndex()+1; // ...I have to correct my end position
867 SwTextNode
* pCpyTNd
= rNd
.GetTextNode();
870 SwTextNode
* pTNd
= new SwTextNode( aInsPos
.GetNode(), pCpyTNd
->GetTextColl() );
871 if( pCpyTNd
->HasSwAttrSet() )
873 // Move PageDesc/Break to the first Node of the section
874 const SfxItemSet
& rSet
= *pCpyTNd
->GetpSwAttrSet();
875 if( SfxItemState::SET
== rSet
.GetItemState( RES_BREAK
) ||
876 SfxItemState::SET
== rSet
.GetItemState( RES_PAGEDESC
))
878 SfxItemSet
aSet( rSet
);
880 pCpyTNd
->ResetAttr( RES_PAGEDESC
, RES_BREAK
);
883 aSet
.ClearItem( RES_PAGEDESC
);
884 aSet
.ClearItem( RES_BREAK
);
886 pTNd
->SetAttr( aSet
);
889 pTNd
->SetAttr( rSet
);
891 // Do not forget to create the Frame!
892 pCpyTNd
->MakeFramesForAdjacentContentNode(*pTNd
);
895 new SwTextNode( aInsPos
.GetNode(), GetDoc().GetDfltTextFormatColl() );
897 new SwEndNode( aInsPos
.GetNode(), *pSectNd
);
899 pSectNd
->GetSection().SetSectionData(rSectionData
);
900 SwSectionFormat
* pSectFormat
= pSectNd
->GetSection().GetFormat();
902 // We could optimize this, by not removing already contained Frames and recreating them,
903 // but by simply rewiring them
904 bool bInsFrame
= bCreateFrames
&& !pSectNd
->GetSection().IsHiddenFlag() &&
905 GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
906 std::optional
<SwNode2LayoutSaveUpperFrames
> oNode2Layout
;
909 if( !pSectNd
->GetNodes().FindPrvNxtFrameNode( *pSectNd
, pSectNd
->EndOfSectionNode() ) )
910 // Collect all Uppers
911 oNode2Layout
.emplace(*pSectNd
);
914 // Set the right StartNode for all in this Area
915 SwNodeOffset nEnd
= pSectNd
->EndOfSectionIndex();
916 SwNodeOffset nStart
= pSectNd
->GetIndex()+1;
917 SwNodeOffset nSkipIdx
= NODE_OFFSET_MAX
;
918 for( SwNodeOffset n
= nStart
; n
< nEnd
; ++n
)
920 SwNode
* pNd
= (*this)[n
];
922 // Attach all Sections in the NodeSection underneath the new one
923 if( NODE_OFFSET_MAX
== nSkipIdx
)
924 pNd
->m_pStartOfSection
= pSectNd
;
925 else if( n
>= nSkipIdx
)
926 nSkipIdx
= NODE_OFFSET_MAX
;
928 if( pNd
->IsStartNode() )
930 // Make up the Format's nesting
931 if( pNd
->IsSectionNode() )
933 static_cast<SwSectionNode
*>(pNd
)->GetSection().GetFormat()->
934 SetDerivedFrom( pSectFormat
);
935 static_cast<SwSectionNode
*>(pNd
)->DelFrames();
936 n
= pNd
->EndOfSectionIndex();
940 if( pNd
->IsTableNode() )
941 static_cast<SwTableNode
*>(pNd
)->DelFrames();
943 if( NODE_OFFSET_MAX
== nSkipIdx
)
944 nSkipIdx
= pNd
->EndOfSectionIndex();
947 else if( pNd
->IsContentNode() )
948 static_cast<SwContentNode
*>(pNd
)->DelFrames(nullptr);
951 sw_DeleteFootnote( pSectNd
, nStart
, nEnd
);
957 SwNodeOffset nIdx
= pSectNd
->GetIndex();
958 oNode2Layout
->RestoreUpperFrames( pSectNd
->GetNodes(), nIdx
, nIdx
+ 1 );
959 oNode2Layout
.reset();
962 pSectNd
->MakeOwnFrames(&aInsPos
);
968 SwSectionNode
* SwNode::FindSectionNode()
970 if( IsSectionNode() )
971 return GetSectionNode();
972 SwStartNode
* pTmp
= m_pStartOfSection
;
973 while( !pTmp
->IsSectionNode() && pTmp
->GetIndex() )
974 pTmp
= pTmp
->m_pStartOfSection
;
975 return pTmp
->GetSectionNode();
980 // ugly hack to make m_pSection const
981 static SwSectionFormat
&
982 lcl_initParent(SwSectionNode
& rThis
, SwSectionFormat
& rFormat
)
984 SwSectionNode
*const pParent
=
985 rThis
.StartOfSectionNode()->FindSectionNode();
988 // Register the Format at the right Parent
989 rFormat
.SetDerivedFrom( pParent
->GetSection().GetFormat() );
994 SwSectionNode::SwSectionNode(const SwNode
& rWhere
,
995 SwSectionFormat
& rFormat
, SwTOXBase
const*const pTOXBase
)
996 : SwStartNode( rWhere
, SwNodeType::Section
)
997 , m_pSection( pTOXBase
998 ? new SwTOXBaseSection(*pTOXBase
, lcl_initParent(*this, rFormat
))
999 : new SwSection( SectionType::Content
, rFormat
.GetName(),
1000 lcl_initParent(*this, rFormat
) ) )
1002 // Set the connection from Format to Node
1003 // Suppress Modify; no one's interested anyway
1004 rFormat
.LockModify();
1005 rFormat
.SetFormatAttr( SwFormatContent( this ) );
1006 rFormat
.UnlockModify();
1009 SwSectionNode::~SwSectionNode()
1011 // mba: test if iteration works as clients will be removed in callback
1012 // use hint which allows to specify, if the content shall be saved or not
1013 m_pSection
->GetFormat()->CallSwClientNotify( SwSectionFrameMoveAndDeleteHint( true ) );
1014 SwSectionFormat
* pFormat
= m_pSection
->GetFormat();
1017 // Remove the Attribute, because the Section deletes it's Format
1018 // and it will neutralize the Section, if the Content Attribute is set
1019 pFormat
->LockModify();
1020 pFormat
->ResetFormatAttr( RES_CNTNT
);
1021 pFormat
->UnlockModify();
1025 SwFrame
*SwSectionNode::MakeFrame( SwFrame
*pSib
)
1027 m_pSection
->m_Data
.SetHiddenFlag(false);
1028 return new SwSectionFrame( *m_pSection
, pSib
);
1031 // Creates all Document Views for the preceding Node.
1032 // The created ContentFrames are attached to the corresponding Layout
1033 void SwSectionNode::MakeFramesForAdjacentContentNode(const SwNodeIndex
& rIdx
)
1035 // Take my successive or preceding ContentFrame
1036 SwNodes
& rNds
= GetNodes();
1037 if( !(rNds
.IsDocNodes() && rNds
.GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell()) )
1040 if (GetSection().IsHiddenFlag() || IsContentHidden())
1042 SwNodeIndex
aIdx( *EndOfSectionNode() );
1043 SwContentNode
* pCNd
= rNds
.GoNextSection( &aIdx
, true, false );
1047 pCNd
= SwNodes::GoPrevSection(&aIdx
, true, false);
1051 pCNd
= aIdx
.GetNode().GetContentNode();
1052 pCNd
->MakeFramesForAdjacentContentNode(static_cast<SwContentNode
&>(rIdx
.GetNode()));
1056 SwNode2Layout
aNode2Layout( *this, rIdx
.GetIndex() );
1058 while( nullptr != (pFrame
= aNode2Layout
.NextFrame()) )
1060 OSL_ENSURE( pFrame
->IsSctFrame(), "Depend of Section not a Section." );
1061 if (pFrame
->getRootFrame()->HasMergedParas()
1062 && !rIdx
.GetNode().IsCreateFrameWhenHidingRedlines())
1066 SwFrame
*pNew
= rIdx
.GetNode().GetContentNode()->MakeFrame( pFrame
);
1068 SwSectionNode
* pS
= rIdx
.GetNode().FindSectionNode();
1070 // Assure that node is not inside a table, which is inside the
1074 SwTableNode
* pTableNode
= rIdx
.GetNode().FindTableNode();
1076 pTableNode
->GetIndex() > pS
->GetIndex() )
1082 // if the node is in a section, the sectionframe now
1083 // has to be created...
1084 // boolean to control <Init()> of a new section frame.
1085 bool bInitNewSect
= false;
1088 SwSectionFrame
*pSct
= new SwSectionFrame( pS
->GetSection(), pFrame
);
1089 // prepare <Init()> of new section frame.
1090 bInitNewSect
= true;
1091 SwLayoutFrame
* pUp
= pSct
;
1092 while( pUp
->Lower() ) // for columned sections
1094 OSL_ENSURE( pUp
->Lower()->IsLayoutFrame(),"Who's in there?" );
1095 pUp
= static_cast<SwLayoutFrame
*>(pUp
->Lower());
1099 // notify accessibility paragraphs objects about changed
1100 // CONTENT_FLOWS_FROM/_TO relation.
1101 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1102 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1103 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1104 if ( pNew
->IsTextFrame() )
1106 SwViewShell
* pViewShell( pNew
->getRootFrame()->GetCurrShell() );
1107 if ( pViewShell
&& pViewShell
->GetLayout() &&
1108 pViewShell
->GetLayout()->IsAnyShellAccessible() )
1110 auto pNext
= pNew
->FindNextCnt( true );
1111 auto pPrev
= pNew
->FindPrevCnt();
1112 pViewShell
->InvalidateAccessibleParaFlowRelation(
1113 pNext
? pNext
->DynCastTextFrame() : nullptr,
1114 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1121 // If a Node got Frames attached before or after
1122 if ( rIdx
< GetIndex() )
1123 // the new one precedes me
1124 pNew
->Paste( pFrame
->GetUpper(), pFrame
);
1126 // the new one succeeds me
1127 pNew
->Paste( pFrame
->GetUpper(), pFrame
->GetNext() );
1129 // notify accessibility paragraphs objects about changed
1130 // CONTENT_FLOWS_FROM/_TO relation.
1131 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1132 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1133 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1134 if ( pNew
->IsTextFrame() )
1136 SwViewShell
* pViewShell( pNew
->getRootFrame()->GetCurrShell() );
1137 if ( pViewShell
&& pViewShell
->GetLayout() &&
1138 pViewShell
->GetLayout()->IsAnyShellAccessible() )
1140 auto pNext
= pNew
->FindNextCnt( true );
1141 auto pPrev
= pNew
->FindPrevCnt();
1142 pViewShell
->InvalidateAccessibleParaFlowRelation(
1143 pNext
? pNext
->DynCastTextFrame() : nullptr,
1144 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1149 static_cast<SwSectionFrame
*>(pNew
)->Init();
1154 // Create a new SectionFrame for every occurrence in the Layout and insert before
1155 // the corresponding ContentFrame
1156 void SwSectionNode::MakeOwnFrames(SwNodeIndex
* pIdxBehind
, SwNodeIndex
* pEndIdx
)
1158 OSL_ENSURE( pIdxBehind
, "no Index" );
1159 SwNodes
& rNds
= GetNodes();
1160 SwDoc
& rDoc
= rNds
.GetDoc();
1162 *pIdxBehind
= *this;
1164 m_pSection
->m_Data
.SetHiddenFlag(true);
1166 if( rNds
.IsDocNodes() )
1169 ::MakeFrames( &rDoc
, pIdxBehind
->GetNode(), pEndIdx
->GetNode() );
1171 ::MakeFrames( &rDoc
, pIdxBehind
->GetNode(), SwNodeIndex( *EndOfSectionNode(), 1 ).GetNode() );
1175 void SwSectionNode::DelFrames(SwRootFrame
const*const /*FIXME TODO*/, bool const bForce
)
1177 SwNodeOffset nStt
= GetIndex()+1, nEnd
= EndOfSectionIndex();
1183 SwNodes
& rNds
= GetNodes();
1184 m_pSection
->GetFormat()->DelFrames();
1187 m_pSection
->m_Data
.SetHiddenFlag(true);
1189 // If the Area is within a Fly or TableBox, we can only hide it if
1190 // there is more Content which has Frames.
1191 // Or else the Fly/TableBox Frame does not have a Lower!
1195 SwNodeIndex
aIdx( *this );
1196 if( !SwNodes::GoPrevSection( &aIdx
, true, false ) ||
1197 !CheckNodesRange( *this, aIdx
.GetNode(), true ) ||
1199 !lcl_IsInSameTableBox( rNds
, *this, true ))
1201 aIdx
= *EndOfSectionNode();
1202 if( !rNds
.GoNextSection( &aIdx
, true, false ) ||
1203 !CheckNodesRange( *EndOfSectionNode(), aIdx
.GetNode(), true ) ||
1205 !lcl_IsInSameTableBox( rNds
, *EndOfSectionNode(), false ))
1207 m_pSection
->m_Data
.SetHiddenFlag(false);
1212 SwSectionNode
* SwSectionNode::MakeCopy( SwDoc
& rDoc
, const SwNodeIndex
& rIdx
) const
1214 // In which array am I: Nodes, UndoNodes?
1215 const SwNodes
& rNds
= GetNodes();
1217 // Copy the SectionFrameFormat
1218 SwSectionFormat
* pSectFormat
= rDoc
.MakeSectionFormat();
1219 pSectFormat
->CopyAttrs( *GetSection().GetFormat() );
1221 std::unique_ptr
<SwTOXBase
> pTOXBase
;
1222 if (SectionType::ToxContent
== GetSection().GetType())
1224 assert( dynamic_cast< const SwTOXBaseSection
* >( &GetSection() ) && "no TOXBaseSection!" );
1225 SwTOXBaseSection
const& rTBS(
1226 dynamic_cast<SwTOXBaseSection
const&>(GetSection()));
1227 pTOXBase
.reset( new SwTOXBase(rTBS
, &rDoc
) );
1230 SwSectionNode
*const pSectNd
=
1231 new SwSectionNode(rIdx
.GetNode(), *pSectFormat
, pTOXBase
.get());
1232 SwEndNode
* pEndNd
= new SwEndNode( rIdx
.GetNode(), *pSectNd
);
1233 SwNodeIndex
aInsPos( *pEndNd
);
1236 SwSection
*const pNewSect
= pSectNd
->m_pSection
.get();
1238 if (SectionType::ToxContent
!= GetSection().GetType())
1240 // Keep the Name for Move
1241 if( &rNds
.GetDoc() == &rDoc
&& rDoc
.IsCopyIsMove() )
1243 pNewSect
->SetSectionName( GetSection().GetSectionName() );
1247 const OUString
sSectionName(GetSection().GetSectionName());
1248 pNewSect
->SetSectionName(rDoc
.GetUniqueSectionName( &sSectionName
));
1252 pNewSect
->SetType( GetSection().GetType() );
1253 pNewSect
->SetCondition( GetSection().GetCondition() );
1254 pNewSect
->SetCondHidden( GetSection().IsCondHidden() );
1255 pNewSect
->SetLinkFileName( GetSection().GetLinkFileName() );
1256 if( !pNewSect
->IsHiddenFlag() && GetSection().IsHidden() )
1257 pNewSect
->SetHidden();
1258 if( !pNewSect
->IsProtectFlag() && GetSection().IsProtect() )
1259 pNewSect
->SetProtect();
1260 // edit in readonly sections
1261 if( !pNewSect
->IsEditInReadonlyFlag() && GetSection().IsEditInReadonly() )
1262 pNewSect
->SetEditInReadonly();
1264 SwNodeRange
aRg( *this, SwNodeOffset(+1), *EndOfSectionNode() ); // Where am I?
1265 rNds
.Copy_( aRg
, aInsPos
.GetNode(), false );
1267 // Delete all Frames from the copied Area. They are created when creating
1268 // the SectionFrames.
1269 pSectNd
->DelFrames();
1271 // Copy the Links/Server
1272 if( pNewSect
->IsLinkType() ) // Add the Link
1273 pNewSect
->CreateLink( rDoc
.getIDocumentLayoutAccess().GetCurrentViewShell() ? LinkCreateType::Connect
: LinkCreateType::NONE
);
1275 // If we copy from the Undo as Server, enter it again
1276 if (m_pSection
->IsServer()
1277 && rDoc
.GetIDocumentUndoRedo().IsUndoNodes(rNds
))
1279 pNewSect
->SetRefObject( m_pSection
->GetObject() );
1280 rDoc
.getIDocumentLinksAdministration().GetLinkManager().InsertServer( pNewSect
->GetObject() );
1283 // METADATA: copy xml:id; must be done after insertion of node
1284 pSectFormat
->RegisterAsCopyOf(*GetSection().GetFormat());
1289 bool SwSectionNode::IsContentHidden() const
1291 OSL_ENSURE( !m_pSection
->IsHidden(),
1292 "That's simple: Hidden Section => Hidden Content" );
1293 SwNodeIndex
aTmp( *this, 1 );
1294 SwNodeOffset nEnd
= EndOfSectionIndex();
1295 while( aTmp
< nEnd
)
1297 if( aTmp
.GetNode().IsSectionNode() )
1299 const SwSection
& rSect
= static_cast<SwSectionNode
&>(aTmp
.GetNode()).GetSection();
1300 if( rSect
.IsHiddenFlag() )
1301 // Skip this Section
1302 aTmp
= *aTmp
.GetNode().EndOfSectionNode();
1306 if( aTmp
.GetNode().IsContentNode() || aTmp
.GetNode().IsTableNode() )
1307 return false; // We found non-hidden content
1308 OSL_ENSURE( aTmp
.GetNode().IsEndNode(), "EndNode expected" );
1312 return true; // Hide everything
1315 void SwSectionNode::dumpAsXml(xmlTextWriterPtr pWriter
) const
1317 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("section"));
1318 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1319 (void)xmlTextWriterWriteAttribute(
1320 pWriter
, BAD_CAST("type"),
1321 BAD_CAST(OString::number(static_cast<sal_uInt8
>(GetNodeType())).getStr()));
1322 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("index"),
1323 BAD_CAST(OString::number(sal_Int32(GetIndex())).getStr()));
1327 m_pSection
->dumpAsXml(pWriter
);
1330 // (void)xmlTextWriterEndElement(pWriter); - it is a start node, so don't end, will make xml better nested
1333 void SwSectionNode::NodesArrChgd()
1335 SwSectionFormat
*const pFormat
= m_pSection
->GetFormat();
1339 SwNodes
& rNds
= GetNodes();
1340 SwDoc
* pDoc
= pFormat
->GetDoc();
1342 if( !rNds
.IsDocNodes() )
1344 pFormat
->RemoveAllUnos();
1347 pFormat
->LockModify();
1348 pFormat
->SetFormatAttr( SwFormatContent( this ));
1349 pFormat
->UnlockModify();
1351 SwSectionNode
* pSectNd
= StartOfSectionNode()->FindSectionNode();
1352 // set the correct parent from the new section
1353 pFormat
->SetDerivedFrom( pSectNd
? pSectNd
->GetSection().GetFormat()
1354 : pDoc
->GetDfltFrameFormat() );
1356 // Set the right StartNode for all in this Area
1357 SwNodeOffset nStart
= GetIndex()+1, nEnd
= EndOfSectionIndex();
1358 for( SwNodeOffset n
= nStart
; n
< nEnd
; ++n
)
1360 // Make up the Format's nesting
1361 pSectNd
= rNds
[ n
]->GetSectionNode();
1362 if( nullptr != pSectNd
)
1364 pSectNd
->GetSection().GetFormat()->SetDerivedFrom( pFormat
);
1365 n
= pSectNd
->EndOfSectionIndex();
1369 // Moving Nodes to the UndoNodes array?
1370 if( rNds
.IsDocNodes() )
1372 OSL_ENSURE( pDoc
== &GetDoc(),
1373 "Moving to different Documents?" );
1374 if( m_pSection
->IsLinkType() ) // Remove the Link
1375 m_pSection
->CreateLink( pDoc
->getIDocumentLayoutAccess().GetCurrentViewShell() ? LinkCreateType::Connect
: LinkCreateType::NONE
);
1377 if (m_pSection
->IsServer())
1378 pDoc
->getIDocumentLinksAdministration().GetLinkManager().InsertServer( m_pSection
->GetObject() );
1382 if (SectionType::Content
!= m_pSection
->GetType()
1383 && m_pSection
->IsConnected())
1385 pDoc
->getIDocumentLinksAdministration().GetLinkManager().Remove( &m_pSection
->GetBaseLink() );
1387 if (m_pSection
->IsServer())
1388 pDoc
->getIDocumentLinksAdministration().GetLinkManager().RemoveServer( m_pSection
->GetObject() );
1393 OUString
SwDoc::GetUniqueSectionName( const OUString
* pChkStr
) const
1395 if( IsInMailMerge())
1397 OUString newName
= "MailMergeSection"
1398 + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM
)), RTL_TEXTENCODING_ASCII_US
)
1399 + OUString::number( mpSectionFormatTable
->size() + 1 );
1401 newName
+= *pChkStr
;
1405 const OUString
aName(SwResId(STR_REGION_DEFNAME
));
1407 SwSectionFormats::size_type nNum
= 0;
1408 const SwSectionFormats::size_type nFlagSize
= ( mpSectionFormatTable
->size() / 8 ) + 2;
1409 std::unique_ptr
<sal_uInt8
[]> pSetFlags(new sal_uInt8
[ nFlagSize
]);
1410 memset( pSetFlags
.get(), 0, nFlagSize
);
1412 for( auto pFormat
: *mpSectionFormatTable
)
1414 const SwSectionNode
*const pSectNd
= pFormat
->GetSectionNode();
1415 if( pSectNd
!= nullptr )
1417 const OUString
& rNm
= pSectNd
->GetSection().GetSectionName();
1418 if (rNm
.startsWith( aName
))
1420 // Calculate the Number and reset the Flag
1421 nNum
= o3tl::toInt32(rNm
.subView( aName
.getLength() ));
1422 if( nNum
-- && nNum
< mpSectionFormatTable
->size() )
1423 pSetFlags
[ nNum
/ 8 ] |= (0x01 << ( nNum
& 0x07 ));
1425 if( pChkStr
&& *pChkStr
==rNm
)
1432 // Flagged all Numbers accordingly, so get the right Number
1433 nNum
= mpSectionFormatTable
->size();
1434 for( SwSectionFormats::size_type n
= 0; n
< nFlagSize
; ++n
)
1436 auto nTmp
= pSetFlags
[ n
];
1439 // Calculate the Number
1453 return aName
+ OUString::number( ++nNum
);
1456 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */