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 <hintids.hxx>
22 #include <editeng/protitem.hxx>
23 #include <osl/diagnose.h>
24 #include <tools/gen.hxx>
25 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
26 #include <com/sun/star/i18n/XBreakIterator.hpp>
27 #include <fmtcntnt.hxx>
28 #include <fmtanchr.hxx>
34 #include <ndindex.hxx>
35 #include <numrule.hxx>
36 #include <swtable.hxx>
39 #include <section.hxx>
48 #include <fmthdft.hxx>
50 #include <fmtautofmt.hxx>
51 #include <frmtool.hxx>
52 #include <pagefrm.hxx>
53 #include <node2lay.hxx>
54 #include <pagedesc.hxx>
55 #include <fmtpdsc.hxx>
56 #include <breakit.hxx>
57 #include <SwStyleNameMapper.hxx>
58 #include <scriptinfo.hxx>
59 #include <rootfrm.hxx>
60 #include <istyleaccess.hxx>
61 #include <IDocumentListItems.hxx>
62 #include <DocumentSettingManager.hxx>
63 #include <IDocumentLinksAdministration.hxx>
64 #include <IDocumentRedlineAccess.hxx>
65 #include <IDocumentLayoutAccess.hxx>
71 #include <frameformats.hxx>
72 #include <OnlineAccessibilityCheck.hxx>
74 #include <sal/backtrace.hxx>
77 using namespace ::com::sun::star::i18n
;
82 void AccessibilityCheckStatus::reset()
90 * Some local helper functions for the attribute set handle of a content node.
91 * Since the attribute set of a content node may not be modified directly,
92 * we always have to create a new SwAttrSet, do the modifications, and get
93 * a new handle from the style access
96 namespace AttrSetHandleHelper
99 static void GetNewAutoStyle( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
,
100 const SwContentNode
& rNode
,
101 SwAttrSet
const & rNewAttrSet
)
103 const SwAttrSet
* pAttrSet
= static_cast<const SwAttrSet
*>(rpAttrSet
.get());
104 if( rNode
.GetModifyAtAttr() )
105 const_cast<SwAttrSet
*>(pAttrSet
)->SetModifyAtAttr( nullptr );
106 IStyleAccess
& rSA
= pAttrSet
->GetPool()->GetDoc()->GetIStyleAccess();
107 rpAttrSet
= rSA
.getAutomaticStyle( rNewAttrSet
, rNode
.IsTextNode() ?
108 IStyleAccess::AUTO_STYLE_PARA
:
109 IStyleAccess::AUTO_STYLE_NOTXT
);
110 const bool bSetModifyAtAttr
= const_cast<SwAttrSet
*>(static_cast<const SwAttrSet
*>(rpAttrSet
.get()))->SetModifyAtAttr( &rNode
);
111 rNode
.SetModifyAtAttr( bSetModifyAtAttr
);
114 static void SetParent( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
,
115 const SwContentNode
& rNode
,
116 const SwFormat
* pParentFormat
,
117 const SwFormat
* pConditionalFormat
)
119 const SwAttrSet
* pAttrSet
= static_cast<const SwAttrSet
*>(rpAttrSet
.get());
120 OSL_ENSURE( pAttrSet
, "no SwAttrSet" );
121 OSL_ENSURE( pParentFormat
|| !pConditionalFormat
, "ConditionalFormat without ParentFormat?" );
123 const SwAttrSet
* pParentSet
= pParentFormat
? &pParentFormat
->GetAttrSet() : nullptr;
125 if ( pParentSet
== pAttrSet
->GetParent() )
128 SwAttrSet
aNewSet( *pAttrSet
);
129 aNewSet
.SetParent( pParentSet
);
130 aNewSet
.ClearItem( RES_FRMATR_STYLE_NAME
);
131 aNewSet
.ClearItem( RES_FRMATR_CONDITIONAL_STYLE_NAME
);
136 SwStyleNameMapper::FillProgName( pParentFormat
->GetName(), sVal
, SwGetPoolIdFromName::TxtColl
);
137 const SfxStringItem
aAnyFormatColl( RES_FRMATR_STYLE_NAME
, sVal
);
138 aNewSet
.Put( aAnyFormatColl
);
140 if ( pConditionalFormat
!= pParentFormat
)
141 SwStyleNameMapper::FillProgName( pConditionalFormat
->GetName(), sVal
, SwGetPoolIdFromName::TxtColl
);
143 const SfxStringItem
aFormatColl( RES_FRMATR_CONDITIONAL_STYLE_NAME
, sVal
);
144 aNewSet
.Put( aFormatColl
);
147 GetNewAutoStyle( rpAttrSet
, rNode
, aNewSet
);
150 static const SfxPoolItem
* Put( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
,
151 const SwContentNode
& rNode
,
152 const SfxPoolItem
& rAttr
)
154 SwAttrSet
aNewSet( static_cast<const SwAttrSet
&>(*rpAttrSet
) );
155 const SfxPoolItem
* pRet
= aNewSet
.Put( rAttr
);
157 GetNewAutoStyle( rpAttrSet
, rNode
, aNewSet
);
161 static bool Put( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
, const SwContentNode
& rNode
,
162 const SfxItemSet
& rSet
)
164 SwAttrSet
aNewSet( static_cast<const SwAttrSet
&>(*rpAttrSet
) );
167 std::optional
<SfxItemSetFixed
<RES_FRMATR_STYLE_NAME
, RES_FRMATR_CONDITIONAL_STYLE_NAME
>> pStyleNames
;
168 if ( SfxItemState::SET
== rSet
.GetItemState( RES_FRMATR_STYLE_NAME
, false ) )
170 pStyleNames
.emplace( *aNewSet
.GetPool() );
171 pStyleNames
->Put( aNewSet
);
174 const bool bRet
= aNewSet
.Put( rSet
);
179 aNewSet
.Put( *pStyleNames
);
183 GetNewAutoStyle( rpAttrSet
, rNode
, aNewSet
);
188 static bool Put_BC( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
,
189 const SwContentNode
& rNode
, const SfxPoolItem
& rAttr
,
190 SwAttrSet
* pOld
, SwAttrSet
* pNew
)
192 SwAttrSet
aNewSet( static_cast<const SwAttrSet
&>(*rpAttrSet
) );
194 // for a correct broadcast, we need to do a SetModifyAtAttr with the items
195 // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
196 if( rNode
.GetModifyAtAttr() )
197 aNewSet
.SetModifyAtAttr( &rNode
);
199 const bool bRet
= aNewSet
.Put_BC( rAttr
, pOld
, pNew
);
202 GetNewAutoStyle( rpAttrSet
, rNode
, aNewSet
);
207 static bool Put_BC( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
,
208 const SwContentNode
& rNode
, const SfxItemSet
& rSet
,
209 SwAttrSet
* pOld
, SwAttrSet
* pNew
)
211 SwAttrSet
aNewSet( static_cast<const SwAttrSet
&>(*rpAttrSet
) );
214 std::optional
<SfxItemSetFixed
<RES_FRMATR_STYLE_NAME
, RES_FRMATR_CONDITIONAL_STYLE_NAME
>> pStyleNames
;
215 if ( SfxItemState::SET
== rSet
.GetItemState( RES_FRMATR_STYLE_NAME
, false ) )
217 pStyleNames
.emplace( *aNewSet
.GetPool() );
218 pStyleNames
->Put( aNewSet
);
221 // for a correct broadcast, we need to do a SetModifyAtAttr with the items
222 // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
223 if( rNode
.GetModifyAtAttr() )
224 aNewSet
.SetModifyAtAttr( &rNode
);
226 const bool bRet
= aNewSet
.Put_BC( rSet
, pOld
, pNew
);
231 aNewSet
.Put( *pStyleNames
);
235 GetNewAutoStyle( rpAttrSet
, rNode
, aNewSet
);
240 static sal_uInt16
ClearItem_BC( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
,
241 const SwContentNode
& rNode
, sal_uInt16 nWhich
,
242 SwAttrSet
* pOld
, SwAttrSet
* pNew
)
244 SwAttrSet
aNewSet( static_cast<const SwAttrSet
&>(*rpAttrSet
) );
245 if( rNode
.GetModifyAtAttr() )
246 aNewSet
.SetModifyAtAttr( &rNode
);
247 const sal_uInt16 nRet
= aNewSet
.ClearItem_BC( nWhich
, pOld
, pNew
);
249 GetNewAutoStyle( rpAttrSet
, rNode
, aNewSet
);
253 static sal_uInt16
ClearItem_BC( std::shared_ptr
<const SfxItemSet
>& rpAttrSet
,
254 const SwContentNode
& rNode
,
255 sal_uInt16 nWhich1
, sal_uInt16 nWhich2
,
256 SwAttrSet
* pOld
, SwAttrSet
* pNew
)
258 SwAttrSet
aNewSet( static_cast<const SwAttrSet
&>(*rpAttrSet
) );
259 if( rNode
.GetModifyAtAttr() )
260 aNewSet
.SetModifyAtAttr( &rNode
);
261 const sal_uInt16 nRet
= aNewSet
.ClearItem_BC( nWhich1
, nWhich2
, pOld
, pNew
);
263 GetNewAutoStyle( rpAttrSet
, rNode
, aNewSet
);
269 /** Returns the section level at the position given by aIndex.
271 * We use the following logic:
272 * S = Start, E = End, C = ContentNode
277 * All EndNodes of the BaseSection have level 0
278 * All StartNodes of the BaseSection have level 1
280 sal_uInt16
SwNode::GetSectionLevel() const
282 // EndNode of a BaseSection? They are always 0!
283 if( IsEndNode() && SwNodeOffset(0) == m_pStartOfSection
->StartOfSectionIndex() )
287 const SwNode
* pNode
= IsStartNode() ? this : m_pStartOfSection
;
288 for( nLevel
= 1; SwNodeOffset(0) != pNode
->StartOfSectionIndex(); ++nLevel
)
289 pNode
= pNode
->m_pStartOfSection
;
290 return IsEndNode() ? nLevel
-1 : nLevel
;
294 tools::Long
SwNode::s_nSerial
= 0;
297 /// only used by SwContentNodeTmp in SwTextNode::Update
299 : m_nNodeType( SwNodeType::Start
)
300 , m_nAFormatNumLvl( 0 )
301 , m_bIgnoreDontExpand( false)
302 , m_eMerge(Merge::None
)
304 , m_nSerial( s_nSerial
++)
306 , m_pStartOfSection( nullptr )
309 SwNode::SwNode( const SwNode
& rWhere
, const SwNodeType nNdType
)
310 : m_nNodeType( nNdType
)
311 , m_nAFormatNumLvl( 0 )
312 , m_bIgnoreDontExpand( false)
313 , m_eMerge(Merge::None
)
315 , m_nSerial( s_nSerial
++)
317 , m_pStartOfSection( nullptr )
319 SwNodeOffset nWhereOffset
= rWhere
.GetIndex();
323 SwNodes
& rNodes
= const_cast<SwNodes
&> (rWhere
.GetNodes());
324 SwNode
* pNd
= rNodes
[ nWhereOffset
-1 ];
325 rNodes
.InsertNode( this, nWhereOffset
);
326 m_pStartOfSection
= pNd
->GetStartNode();
327 if( nullptr == m_pStartOfSection
)
329 m_pStartOfSection
= pNd
->m_pStartOfSection
;
330 if( pNd
->GetEndNode() ) // Skip EndNode ? Section
332 pNd
= m_pStartOfSection
;
333 m_pStartOfSection
= pNd
->m_pStartOfSection
;
338 /** Inserts a node into the rNodes array at the rWhere position
340 * @param rNodes the variable array in that the node will be inserted
341 * @param nPos position within the array where the node will be inserted
342 * @param nNdType the type of node to insert
344 SwNode::SwNode( SwNodes
& rNodes
, SwNodeOffset nPos
, const SwNodeType nNdType
)
345 : m_nNodeType( nNdType
)
346 , m_nAFormatNumLvl( 0 )
347 , m_bIgnoreDontExpand( false)
348 , m_eMerge(Merge::None
)
350 , m_nSerial( s_nSerial
++)
352 , m_pStartOfSection( nullptr )
357 SwNode
* pNd
= rNodes
[ nPos
- 1 ];
358 rNodes
.InsertNode( this, nPos
);
359 m_pStartOfSection
= pNd
->GetStartNode();
360 if( nullptr == m_pStartOfSection
)
362 m_pStartOfSection
= pNd
->m_pStartOfSection
;
363 if( pNd
->GetEndNode() ) // Skip EndNode ? Section!
365 pNd
= m_pStartOfSection
;
366 m_pStartOfSection
= pNd
->m_pStartOfSection
;
373 assert(m_aAnchoredFlys
.empty() || GetDoc().IsInDtor()); // must all be deleted
374 InvalidateInSwCache(RES_OBJECTDYING
);
375 assert(!IsInCache());
378 /// Find the TableNode in which it is located.
379 /// If we're not in a table: return 0
380 SwTableNode
* SwNode::FindTableNode()
383 return GetTableNode();
384 SwStartNode
* pTmp
= m_pStartOfSection
;
385 while( !pTmp
->IsTableNode() && pTmp
->GetIndex() )
386 pTmp
= pTmp
->m_pStartOfSection
;
387 return pTmp
->GetTableNode();
390 /// Is the node located in the visible area of the Shell?
391 bool SwNode::IsInVisibleArea( SwViewShell
const * pSh
) const
394 const SwContentNode
* pNd
;
396 if( SwNodeType::Start
& m_nNodeType
)
398 SwNodeIndex
aIdx( *this );
399 pNd
= GetNodes().GoNext( &aIdx
);
401 else if( SwNodeType::End
& m_nNodeType
)
403 SwNodeIndex
aIdx( *EndOfSectionNode() );
404 pNd
= SwNodes::GoPrevious( &aIdx
);
407 pNd
= GetContentNode();
410 // Get the Shell from the Doc
411 pSh
= GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
415 const SwFrame
* pFrame
;
416 if (pNd
&& nullptr != (pFrame
= pNd
->getLayoutFrame(pSh
->GetLayout(), nullptr, nullptr)))
419 if ( pFrame
->IsInTab() )
420 pFrame
= pFrame
->FindTabFrame();
422 if( !pFrame
->isFrameAreaDefinitionValid() )
426 pFrame
= pFrame
->FindPrev();
428 while ( pFrame
&& !pFrame
->isFrameAreaDefinitionValid() );
431 if( !pFrame
|| pSh
->VisArea().Overlaps( pFrame
->getFrameArea() ) )
439 bool SwNode::IsInProtectSect() const
441 const SwNode
* pNd
= SwNodeType::Section
== m_nNodeType
? m_pStartOfSection
: this;
442 const SwSectionNode
* pSectNd
= pNd
->FindSectionNode();
443 return pSectNd
&& pSectNd
->GetSection().IsProtectFlag();
446 /// Does the node contain anything protected?
447 /// I.e.: Area/Frame/Table rows/... including the Anchor for
448 /// Frames/Footnotes/...
449 bool SwNode::IsProtect() const
451 const SwNode
* pNd
= SwNodeType::Section
== m_nNodeType
? m_pStartOfSection
: this;
452 const SwStartNode
* pSttNd
= pNd
->FindSectionNode();
453 if( pSttNd
&& static_cast<const SwSectionNode
*>(pSttNd
)->GetSection().IsProtectFlag() )
456 pSttNd
= FindTableBoxStartNode();
457 if( nullptr != pSttNd
)
459 SwContentFrame
* pCFrame
;
460 if( IsContentNode() && nullptr != (pCFrame
= static_cast<const SwContentNode
*>(this)->getLayoutFrame( GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) ))
461 return pCFrame
->IsProtected();
463 const SwTableBox
* pBox
= pSttNd
->FindTableNode()->GetTable().
464 GetTableBox( pSttNd
->GetIndex() );
466 if( pBox
&& pBox
->GetFrameFormat()->GetProtect().IsContentProtected() )
470 SwFrameFormat
* pFlyFormat
= GetFlyFormat();
473 if (pFlyFormat
->GetProtect().IsContentProtected())
475 const SwFormatAnchor
& rAnchor
= pFlyFormat
->GetAnchor();
476 const SwNode
* pAnchorNode
= rAnchor
.GetAnchorNode();
479 return pAnchorNode
!= this && pAnchorNode
->IsProtect();
482 pSttNd
= FindFootnoteStartNode();
483 if( nullptr != pSttNd
)
485 const SwTextFootnote
* pTFootnote
= GetDoc().GetFootnoteIdxs().SeekEntry(
488 return pTFootnote
->GetTextNode().IsProtect();
494 /// Find the PageDesc that is used to format this node. If the Layout is available,
495 /// we search through that. Else we can only do it the hard way by searching onwards through the nodes.
496 const SwPageDesc
* SwNode::FindPageDesc( SwNodeOffset
* pPgDescNdIdx
) const
498 if ( !GetNodes().IsDocNodes() )
503 const SwPageDesc
* pPgDesc
= nullptr;
505 const SwContentNode
* pNode
;
506 if( SwNodeType::Start
& m_nNodeType
)
508 SwNodeIndex
aIdx( *this );
509 pNode
= GetNodes().GoNext( &aIdx
);
511 else if( SwNodeType::End
& m_nNodeType
)
513 SwNodeIndex
aIdx( *EndOfSectionNode() );
514 pNode
= SwNodes::GoPrevious( &aIdx
);
518 pNode
= GetContentNode();
520 pPgDesc
= pNode
->GetAttr( RES_PAGEDESC
).GetPageDesc();
523 // Are we going through the layout?
526 const SwFrame
* pFrame
;
527 const SwPageFrame
* pPage
;
528 if (pNode
&& nullptr != (pFrame
= pNode
->getLayoutFrame(pNode
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, nullptr)) &&
529 nullptr != ( pPage
= pFrame
->FindPageFrame() ) )
531 pPgDesc
= pPage
->GetPageDesc();
534 *pPgDescNdIdx
= pNode
->GetIndex();
541 // Thus via the nodes array
542 const SwDoc
& rDoc
= GetDoc();
543 const SwNode
* pNd
= this;
544 const SwStartNode
* pSttNd
;
545 if( pNd
->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() &&
546 nullptr != ( pSttNd
= pNd
->FindFlyStartNode() ) )
548 // Find the right Anchor first
549 const SwFrameFormat
* pFormat
= nullptr;
550 const sw::SpzFrameFormats
& rFormats
= *rDoc
.GetSpzFrameFormats();
552 for(sw::SpzFrameFormat
* pSpz
: rFormats
)
554 const SwFormatContent
& rContent
= pSpz
->GetContent();
555 if( rContent
.GetContentIdx() &&
556 &rContent
.GetContentIdx()->GetNode() == static_cast<SwNode
const *>(pSttNd
) )
565 const SwFormatAnchor
* pAnchor
= &pFormat
->GetAnchor();
566 if ((RndStdIds::FLY_AT_PAGE
!= pAnchor
->GetAnchorId()) &&
567 pAnchor
->GetAnchorNode() )
569 pNd
= pAnchor
->GetAnchorNode();
570 const SwNode
* pFlyNd
= pNd
->FindFlyStartNode();
573 // Get up through the Anchor
575 for( n
= 0; n
< rFormats
.size(); ++n
)
577 const SwFrameFormat
* pFrameFormat
= rFormats
[ n
];
578 const SwNodeIndex
* pIdx
= pFrameFormat
->GetContent().
580 if( pIdx
&& pFlyNd
== &pIdx
->GetNode() )
582 if( pFormat
== pFrameFormat
)
588 pAnchor
= &pFrameFormat
->GetAnchor();
589 if ((RndStdIds::FLY_AT_PAGE
== pAnchor
->GetAnchorId()) ||
590 !pAnchor
->GetAnchorNode() )
596 pFlyNd
= pAnchor
->GetAnchorNode()->FindFlyStartNode();
600 if( n
>= rFormats
.size() )
602 OSL_ENSURE( false, "FlySection, but no Format found" );
608 // pNd should now contain the correct Anchor or it's still this
611 if( pNd
->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
613 if( pNd
->GetIndex() > GetNodes().GetEndOfAutotext().GetIndex() )
615 pPgDesc
= &rDoc
.GetPageDesc( 0 );
620 // Find the Body text node
621 if( nullptr != ( pSttNd
= pNd
->FindHeaderStartNode() ) ||
622 nullptr != ( pSttNd
= pNd
->FindFooterStartNode() ))
624 // Then find this StartNode in the PageDescs
627 if( SwHeaderStartNode
== pSttNd
->GetStartNodeType())
630 eAskUse
= UseOnPage::HeaderShare
;
635 eAskUse
= UseOnPage::FooterShare
;
638 for( size_t n
= rDoc
.GetPageDescCnt(); n
&& !pPgDesc
; )
640 const SwPageDesc
& rPgDsc
= rDoc
.GetPageDesc( --n
);
641 const SwFrameFormat
* pFormat
= &rPgDsc
.GetMaster();
642 int nStt
= 0, nLast
= 1;
643 if( !( eAskUse
& rPgDsc
.ReadUseOn() )) ++nLast
;
645 for( ; nStt
< nLast
; ++nStt
, pFormat
= &rPgDsc
.GetLeft() )
647 const SwFrameFormat
* pHdFtFormat
= nId
== RES_HEADER
648 ? static_cast<SwFormatHeader
const &>(
649 pFormat
->GetFormatAttr(nId
)).GetHeaderFormat()
650 : static_cast<SwFormatFooter
const &>(
651 pFormat
->GetFormatAttr(nId
)).GetFooterFormat();
654 const SwFormatContent
& rContent
= pHdFtFormat
->GetContent();
655 if( rContent
.GetContentIdx() &&
656 &rContent
.GetContentIdx()->GetNode() ==
657 static_cast<SwNode
const *>(pSttNd
) )
667 pPgDesc
= &rDoc
.GetPageDesc( 0 );
670 else if( nullptr != ( pSttNd
= pNd
->FindFootnoteStartNode() ))
672 // the Anchor can only be in the Body text
673 const SwTextFootnote
* pTextFootnote
;
674 const SwFootnoteIdxs
& rFootnoteArr
= rDoc
.GetFootnoteIdxs();
675 for( size_t n
= 0; n
< rFootnoteArr
.size(); ++n
)
676 if( nullptr != ( pTextFootnote
= rFootnoteArr
[ n
])->GetStartNode() &&
677 static_cast<SwNode
const *>(pSttNd
) ==
678 &pTextFootnote
->GetStartNode()->GetNode() )
680 pNd
= &pTextFootnote
->GetTextNode();
686 // Can only be a page-bound Fly (or something newer).
687 // we can only return the standard here
688 OSL_ENSURE( pNd
->FindFlyStartNode(),
689 "Where is this Node?" );
691 pPgDesc
= &rDoc
.GetPageDesc( 0 );
699 SwFindNearestNode
aInfo( *pNd
);
700 // Over all Nodes of all PageDescs
701 for (const SfxPoolItem
* pItem
: rDoc
.GetAttrPool().GetItemSurrogates(RES_PAGEDESC
))
703 auto pPageDescItem
= dynamic_cast<const SwFormatPageDesc
*>(pItem
);
704 if( pPageDescItem
&& pPageDescItem
->GetDefinedIn() )
706 const sw::BroadcastingModify
* pMod
= pPageDescItem
->GetDefinedIn();
707 if( auto pContentNode
= dynamic_cast<const SwContentNode
*>( pMod
) )
708 aInfo
.CheckNode( *pContentNode
);
709 else if( auto pFormat
= dynamic_cast<const SwFormat
*>( pMod
) )
710 pFormat
->GetInfo( aInfo
);
714 pNd
= aInfo
.GetFoundNode();
717 if( pNd
->IsContentNode() )
718 pPgDesc
= pNd
->GetContentNode()->GetAttr( RES_PAGEDESC
).GetPageDesc();
719 else if( pNd
->IsTableNode() )
720 pPgDesc
= pNd
->GetTableNode()->GetTable().
721 GetFrameFormat()->GetPageDesc().GetPageDesc();
722 else if( pNd
->IsSectionNode() )
723 pPgDesc
= pNd
->GetSectionNode()->GetSection().
724 GetFormat()->GetPageDesc().GetPageDesc();
727 *pPgDescNdIdx
= pNd
->GetIndex();
731 pPgDesc
= &rDoc
.GetPageDesc( 0 );
737 /// If the node is located in a Fly, we return it formatted accordingly
738 SwFrameFormat
* SwNode::GetFlyFormat() const
740 SwFrameFormat
* pRet
= nullptr;
741 const SwNode
* pSttNd
= FindFlyStartNode();
744 if( IsContentNode() )
746 SwContentFrame
* pFrame
= SwIterator
<SwContentFrame
, SwContentNode
, sw::IteratorMode::UnwrapMulti
>(*static_cast<const SwContentNode
*>(this)).First();
747 if( pFrame
&& pFrame
->FindFlyFrame())
748 pRet
= pFrame
->FindFlyFrame()->GetFormat();
752 // The hard way through the Doc is our last way out
753 const sw::SpzFrameFormats
& rSpzs
= *GetDoc().GetSpzFrameFormats();
754 for(sw::SpzFrameFormat
* pSpz
: rSpzs
)
756 // Only Writer fly frames can contain Writer nodes.
757 if (pSpz
->Which() != RES_FLYFRMFMT
)
759 const SwFormatContent
& rContent
= pSpz
->GetContent();
760 if( rContent
.GetContentIdx() &&
761 &rContent
.GetContentIdx()->GetNode() == pSttNd
)
772 SwTableBox
* SwNode::GetTableBox() const
774 SwTableBox
* pBox
= nullptr;
775 const SwNode
* pSttNd
= FindTableBoxStartNode();
777 pBox
= const_cast<SwTableBox
*>(pSttNd
->FindTableNode()->GetTable().GetTableBox(
778 pSttNd
->GetIndex() ));
782 SwStartNode
* SwNode::FindSttNodeByType( SwStartNodeType eTyp
)
784 SwStartNode
* pTmp
= IsStartNode() ? static_cast<SwStartNode
*>(this) : m_pStartOfSection
;
786 while( eTyp
!= pTmp
->GetStartNodeType() && pTmp
->GetIndex() )
787 pTmp
= pTmp
->m_pStartOfSection
;
788 return eTyp
== pTmp
->GetStartNodeType() ? pTmp
: nullptr;
791 const SwTextNode
* SwNode::FindOutlineNodeOfLevel(sal_uInt8
const nLvl
,
792 SwRootFrame
const*const pLayout
) const
794 const SwTextNode
* pRet
= nullptr;
795 const SwOutlineNodes
& rONds
= GetNodes().GetOutLineNds();
796 if( MAXLEVEL
> nLvl
&& !rONds
.empty() )
798 SwOutlineNodes::size_type nPos
;
799 SwNode
* pNd
= const_cast<SwNode
*>(this);
800 bool bCheckFirst
= false;
801 if( !rONds
.Seek_Entry( pNd
, &nPos
))
813 // The first OutlineNode comes after the one asking.
814 // Test if both are on the same page.
815 // If not it's invalid.
816 for (nPos
= 0; nPos
< rONds
.size(); ++nPos
)
818 pRet
= rONds
[nPos
]->GetTextNode();
819 if (!pLayout
|| sw::IsParaPropsNode(*pLayout
, *pRet
))
824 if (nPos
== rONds
.size())
829 const SwContentNode
* pCNd
= GetContentNode();
832 std::pair
<Point
, bool> const tmp(aPt
, false);
833 const SwFrame
* pFrame
= pRet
->getLayoutFrame(pRet
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp
),
834 * pMyFrame
= pCNd
? pCNd
->getLayoutFrame(pCNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp
) : nullptr;
835 const SwPageFrame
* pPgFrame
= pFrame
? pFrame
->FindPageFrame() : nullptr;
836 if( pPgFrame
&& pMyFrame
&&
837 pPgFrame
->getFrameArea().Top() > pMyFrame
->getFrameArea().Top() )
839 // The one asking precedes the Page, thus its invalid
845 for ( ; 0 < nPos
; --nPos
)
847 SwTextNode
const*const pNode
= rONds
[nPos
- 1]->GetTextNode();
848 if ((nPos
== 1 /*as before*/ || pNode
->GetAttrOutlineLevel() - 1 <= nLvl
)
849 && (!pLayout
|| sw::IsParaPropsNode(*pLayout
, *pNode
)))
860 static bool IsValidNextPrevNd( const SwNode
& rNd
)
862 return SwNodeType::Table
== rNd
.GetNodeType() ||
863 ( SwNodeType::ContentMask
& rNd
.GetNodeType() ) ||
864 ( SwNodeType::End
== rNd
.GetNodeType() && rNd
.StartOfSectionNode() &&
865 SwNodeType::Table
== rNd
.StartOfSectionNode()->GetNodeType() );
868 sal_uInt8
SwNode::HasPrevNextLayNode() const
870 // assumption: <this> node is a node inside the document nodes array section.
873 if( IsValidNextPrevNd( *this ))
875 SwNodeIndex
aIdx( *this, -1 );
876 // #i77805# - skip section start and end nodes
877 while ( aIdx
.GetNode().IsSectionNode() ||
878 ( aIdx
.GetNode().IsEndNode() &&
879 aIdx
.GetNode().StartOfSectionNode()->IsSectionNode() ) )
883 if( IsValidNextPrevNd( aIdx
.GetNode() ))
884 nRet
|= ND_HAS_PREV_LAYNODE
;
885 // #i77805# - skip section start and end nodes
886 aIdx
.Assign(*this, +1);
887 while ( aIdx
.GetNode().IsSectionNode() ||
888 ( aIdx
.GetNode().IsEndNode() &&
889 aIdx
.GetNode().StartOfSectionNode()->IsSectionNode() ) )
893 if( IsValidNextPrevNd( aIdx
.GetNode() ))
894 nRet
|= ND_HAS_NEXT_LAYNODE
;
899 void SwNode::dumpAsXml(xmlTextWriterPtr pWriter
) const
901 const char* pName
= "???";
902 switch (GetNodeType())
904 case SwNodeType::End
:
907 case SwNodeType::Start
:
908 case SwNodeType::Text
:
909 case SwNodeType::Ole
:
910 abort(); // overridden
911 case SwNodeType::Table
:
914 case SwNodeType::Grf
:
919 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST(pName
));
921 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
922 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("type"), BAD_CAST(OString::number(static_cast<sal_uInt8
>(GetNodeType())).getStr()));
923 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("index"), BAD_CAST(OString::number(sal_Int32(GetIndex())).getStr()));
925 switch (GetNodeType())
927 case SwNodeType::Grf
:
929 auto pNoTextNode
= static_cast<const SwNoTextNode
*>(this);
930 const tools::PolyPolygon
* pContour
= pNoTextNode
->HasContour();
933 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("pContour"));
934 for (sal_uInt16 i
= 0; i
< pContour
->Count(); ++i
)
936 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("polygon"));
937 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("index"),
938 BAD_CAST(OString::number(i
).getStr()));
939 const tools::Polygon
& rPolygon
= pContour
->GetObject(i
);
940 for (sal_uInt16 j
= 0; j
< rPolygon
.GetSize(); ++j
)
942 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("point"));
943 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("index"),
944 BAD_CAST(OString::number(j
).getStr()));
945 const Point
& rPoint
= rPolygon
.GetPoint(j
);
946 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("x"),
947 BAD_CAST(OString::number(rPoint
.X()).getStr()));
948 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("y"),
949 BAD_CAST(OString::number(rPoint
.Y()).getStr()));
950 (void)xmlTextWriterEndElement(pWriter
);
952 (void)xmlTextWriterEndElement(pWriter
);
954 (void)xmlTextWriterEndElement(pWriter
);
962 (void)xmlTextWriterEndElement(pWriter
);
963 if (GetNodeType() == SwNodeType::End
)
964 (void)xmlTextWriterEndElement(pWriter
); // end start node
967 SwStartNode::SwStartNode( const SwNode
& rWhere
, const SwNodeType nNdType
,
968 SwStartNodeType eSttNd
)
969 : SwNode( rWhere
, nNdType
), m_eStartNodeType( eSttNd
)
971 if( !rWhere
.GetIndex() )
973 SwNodes
& rNodes
= const_cast<SwNodes
&> (rWhere
.GetNodes());
974 rNodes
.InsertNode( this, rWhere
.GetIndex() );
975 m_pStartOfSection
= this;
977 // Just do this temporarily until the EndNode is inserted
978 m_pEndOfSection
= reinterpret_cast<SwEndNode
*>(this);
981 SwStartNode::SwStartNode( SwNodes
& rNodes
, SwNodeOffset nPos
)
982 : SwNode( rNodes
, nPos
, SwNodeType::Start
), m_eStartNodeType( SwNormalStartNode
)
986 rNodes
.InsertNode( this, nPos
);
987 m_pStartOfSection
= this;
989 // Just do this temporarily until the EndNode is inserted
990 m_pEndOfSection
= reinterpret_cast<SwEndNode
*>(this);
993 void SwStartNode::CheckSectionCondColl() const
995 SwNodeIndex
aIdx( *this );
996 SwNodeOffset nEndIdx
= EndOfSectionIndex();
997 const SwNodes
& rNds
= GetNodes();
999 while( nullptr != ( pCNd
= rNds
.GoNext( &aIdx
)) && pCNd
->GetIndex() < nEndIdx
)
1000 pCNd
->ChkCondColl();
1003 void SwStartNode::dumpAsXml(xmlTextWriterPtr pWriter
) const
1005 const char* pName
= "???";
1006 switch (GetNodeType())
1008 case SwNodeType::Table
:
1012 switch(GetStartNodeType())
1014 case SwNormalStartNode
:
1017 case SwTableBoxStartNode
:
1020 case SwFlyStartNode
:
1023 case SwFootnoteStartNode
:
1026 case SwHeaderStartNode
:
1029 case SwFooterStartNode
:
1036 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST(pName
));
1037 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
1038 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("type"), BAD_CAST(OString::number(static_cast<sal_uInt8
>(GetNodeType())).getStr()));
1039 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("index"), BAD_CAST(OString::number(sal_Int32(GetIndex())).getStr()));
1041 if (GetStartNodeType() == SwTableBoxStartNode
)
1043 if (SwTableBox
* pBox
= GetTableBox())
1044 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("rowspan"), BAD_CAST(OString::number(pBox
->getRowSpan()).getStr()));
1045 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("attrset"));
1046 if (SwTableBox
* pBox
= GetTableBox())
1047 pBox
->GetFrameFormat()->GetAttrSet().dumpAsXml(pWriter
);
1048 (void)xmlTextWriterEndElement(pWriter
);
1051 // (void)xmlTextWriterEndElement(pWriter); - it is a start node, so don't end, will make xml better nested
1055 /** Insert a node into the array
1057 * The StartOfSection pointer is set to the given node.
1059 * The EndOfSection pointer of the corresponding start node is set to this node.
1061 * @param rWhere position where the node should be inserted
1062 * @param rSttNd the start note of the section
1065 SwEndNode::SwEndNode( const SwNode
& rWhere
, SwStartNode
& rSttNd
)
1066 : SwNode( rWhere
, SwNodeType::End
)
1068 m_pStartOfSection
= &rSttNd
;
1069 m_pStartOfSection
->m_pEndOfSection
= this;
1072 SwEndNode::SwEndNode( SwNodes
& rNds
, SwNodeOffset nPos
, SwStartNode
& rSttNd
)
1073 : SwNode( rNds
, nPos
, SwNodeType::End
)
1075 m_pStartOfSection
= &rSttNd
;
1076 m_pStartOfSection
->m_pEndOfSection
= this;
1079 /// only used by SwContentNodeTmp in SwTextNode::Update
1080 SwContentNode::SwContentNode()
1082 , m_aCondCollListener( *this )
1083 , m_pCondColl( nullptr )
1084 , mbSetModifyAtAttr( false )
1087 SwContentNode::SwContentNode( const SwNode
& rWhere
, const SwNodeType nNdType
,
1088 SwFormatColl
*pColl
)
1089 : SwNode( rWhere
, nNdType
)
1090 , m_aCondCollListener( *this )
1091 , m_pCondColl( nullptr )
1092 , mbSetModifyAtAttr( false )
1098 SwContentNode::~SwContentNode()
1100 // The base class SwClient of SwFrame excludes itself from the dependency list!
1101 // Thus, we need to delete all Frames in the dependency list.
1102 if (!IsTextNode()) // see ~SwTextNode
1107 m_aCondCollListener
.EndListeningAll();
1108 m_pCondColl
= nullptr;
1110 if ( mpAttrSet
&& mbSetModifyAtAttr
)
1111 const_cast<SwAttrSet
*>(static_cast<const SwAttrSet
*>(mpAttrSet
.get()))->SetModifyAtAttr( nullptr );
1112 InvalidateInSwCache(RES_OBJECTDYING
);
1114 void SwContentNode::UpdateAttr(const SwUpdateAttr
& rUpdate
)
1116 if (GetNodes().IsDocNodes()
1118 && RES_ATTRSET_CHG
== rUpdate
.getWhichAttr())
1119 static_cast<SwTextNode
*>(this)->SetCalcHiddenCharFlags();
1120 CallSwClientNotify(sw::LegacyModifyHint(&rUpdate
, &rUpdate
));
1123 void SwContentNode::SwClientNotify( const SwModify
&, const SfxHint
& rHint
)
1125 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
1127 auto pLegacyHint
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
1128 const sal_uInt16 nWhich
= pLegacyHint
->GetWhich();
1129 InvalidateInSwCache(nWhich
);
1131 bool bSetParent
= false;
1132 bool bCalcHidden
= false;
1133 SwFormatColl
* pFormatColl
= nullptr;
1136 case RES_OBJECTDYING
:
1138 SwFormat
* pFormat
= pLegacyHint
->m_pNew
1139 ? static_cast<SwFormat
*>(static_cast<const SwPtrMsgPoolItem
*>(pLegacyHint
->m_pNew
)->pObject
)
1141 // Do not mangle pointers if it is the upper-most format!
1142 if(pFormat
&& GetRegisteredIn() == pFormat
)
1144 // As ~SwFormat calls CheckRegistrationFormat before
1145 // ~SwModify, which sends the RES_OBJECTDYING, we should never
1146 // reach this point.
1153 // If the Format parent was switched, register the Attrset at the new one
1156 && pLegacyHint
->m_pNew
1157 && static_cast<const SwFormatChg
*>(pLegacyHint
->m_pNew
)->pChangedFormat
== GetRegisteredIn())
1159 pFormatColl
= GetFormatColl();
1164 case RES_ATTRSET_CHG
:
1165 if (GetNodes().IsDocNodes()
1167 && pLegacyHint
->m_pOld
1168 && SfxItemState::SET
== pLegacyHint
->m_pOld
->StaticWhichCast(RES_ATTRSET_CHG
).GetChgSet()->GetItemState(RES_CHRATR_HIDDEN
, false))
1172 case RES_UPDATE_ATTR
:
1173 // RES_UPDATE_ATTR _should_ always contain a SwUpdateAttr hint in old and new.
1174 // However, faking one with just a basic SfxPoolItem setting a WhichId has been observed.
1175 // This makes the crude "WhichId" type divert from the true type, which is bad.
1176 // Thus we are asserting here, but falling back to an proper
1177 // hint instead. so that we at least will not spread such poison further.
1179 if(pLegacyHint
->m_pNew
!= pLegacyHint
->m_pOld
)
1181 auto pBT
= sal::backtrace_get(20);
1182 SAL_WARN("sw.core", "UpdateAttr not matching! " << sal::backtrace_to_string(pBT
.get()));
1185 assert(pLegacyHint
->m_pNew
== pLegacyHint
->m_pOld
);
1186 assert(dynamic_cast<const SwUpdateAttr
*>(pLegacyHint
->m_pNew
));
1187 const SwUpdateAttr
aFallbackHint(0,0,0);
1188 const SwUpdateAttr
& rUpdateAttr
= pLegacyHint
->m_pNew
? *static_cast<const SwUpdateAttr
*>(pLegacyHint
->m_pNew
) : aFallbackHint
;
1189 UpdateAttr(rUpdateAttr
);
1192 if(bSetParent
&& GetpSwAttrSet())
1193 AttrSetHandleHelper::SetParent(mpAttrSet
, *this, pFormatColl
, pFormatColl
);
1195 static_cast<SwTextNode
*>(this)->SetCalcHiddenCharFlags();
1196 CallSwClientNotify(rHint
);
1198 else if (auto pModifyChangedHint
= dynamic_cast<const sw::ModifyChangedHint
*>(&rHint
))
1200 m_pCondColl
= const_cast<SwFormatColl
*>(static_cast<const SwFormatColl
*>(pModifyChangedHint
->m_pNew
));
1202 else if(auto pCondCollCondChgHint
= dynamic_cast<const sw::CondCollCondChg
*>(&rHint
))
1204 ChkCondColl(&pCondCollCondChgHint
->m_rColl
);
1208 bool SwContentNode::InvalidateNumRule()
1210 SwNumRule
* pRule
= nullptr;
1211 const SfxPoolItem
* pItem
;
1212 if( GetNodes().IsDocNodes() &&
1213 nullptr != ( pItem
= GetNoCondAttr( RES_PARATR_NUMRULE
, true )) &&
1214 !static_cast<const SwNumRuleItem
*>(pItem
)->GetValue().isEmpty() &&
1215 nullptr != (pRule
= GetDoc().FindNumRulePtr(
1216 static_cast<const SwNumRuleItem
*>(pItem
)->GetValue() ) ) )
1218 pRule
->SetInvalidRule( true );
1220 return nullptr != pRule
;
1223 SwContentFrame
*SwContentNode::getLayoutFrame( const SwRootFrame
* _pRoot
,
1224 const SwPosition
*const pPos
,
1225 std::pair
<Point
, bool> const*const pViewPosAndCalcFrame
) const
1227 return static_cast<SwContentFrame
*>( ::GetFrameOfModify( _pRoot
, *this, FRM_CNTNT
,
1228 pPos
, pViewPosAndCalcFrame
));
1231 SwRect
SwContentNode::FindLayoutRect( const bool bPrtArea
, const Point
* pPoint
) const
1234 std::pair
<Point
, bool> tmp
;
1237 tmp
.first
= *pPoint
;
1240 SwContentFrame
* pFrame
= static_cast<SwContentFrame
*>( ::GetFrameOfModify( nullptr, *this,
1241 FRM_CNTNT
, nullptr, pPoint
? &tmp
: nullptr) );
1243 aRet
= bPrtArea
? pFrame
->getFramePrintArea() : pFrame
->getFrameArea();
1247 SwRect
SwContentNode::FindPageFrameRect() const
1250 SwFrame
* pFrame
= ::GetFrameOfModify( nullptr, *this, FRM_CNTNT
);
1251 if( pFrame
&& nullptr != ( pFrame
= pFrame
->FindPageFrame() ))
1252 aRet
= pFrame
->getFrameArea();
1256 sal_Int32
SwContentNode::Len() const { return 0; }
1258 SwFormatColl
*SwContentNode::ChgFormatColl( SwFormatColl
*pNewColl
)
1260 OSL_ENSURE( pNewColl
, "Collectionpointer is 0." );
1261 SwFormatColl
*pOldColl
= GetFormatColl();
1263 if( pNewColl
!= pOldColl
)
1265 pNewColl
->Add( this );
1267 // Set the Parent of out AutoAttributes to the new Collection
1268 if( GetpSwAttrSet() )
1269 AttrSetHandleHelper::SetParent( mpAttrSet
, *this, pNewColl
, pNewColl
);
1271 SetCondFormatColl( nullptr );
1273 if( !IsModifyLocked() )
1275 assert(dynamic_cast<SwTextFormatColl
*>(pNewColl
));
1276 ChkCondColl(static_cast<SwTextFormatColl
*>(pNewColl
));
1277 SwFormatChg
aTmp1( pOldColl
);
1278 SwFormatChg
aTmp2( pNewColl
);
1279 CallSwClientNotify( sw::LegacyModifyHint(&aTmp1
, &aTmp2
) );
1282 InvalidateInSwCache(RES_ATTRSET_CHG
);
1286 bool SwContentNode::GoNext(SwPosition
* pPos
, SwCursorSkipMode nMode
) const
1288 if (!GoNext(&pPos
->nContent
, nMode
))
1290 if (pPos
->nContent
.GetContentNode() != &pPos
->GetNode())
1291 pPos
->nNode
.Assign(*pPos
->nContent
.GetContentNode());
1295 bool SwContentNode::GoNext(SwContentIndex
* pIdx
, SwCursorSkipMode nMode
) const
1298 if( pIdx
->GetIndex() < Len() )
1304 const SwTextNode
& rTNd
= *GetTextNode();
1305 sal_Int32 nPos
= pIdx
->GetIndex();
1306 assert(g_pBreakIt
&& g_pBreakIt
->GetBreakIter().is());
1307 sal_Int32 nDone
= 0;
1308 sal_uInt16 nItrMode
= ( SwCursorSkipMode::Cells
& nMode
) ?
1309 CharacterIteratorMode::SKIPCELL
:
1310 CharacterIteratorMode::SKIPCONTROLCHARACTER
;
1311 nPos
= g_pBreakIt
->GetBreakIter()->nextCharacters( rTNd
.GetText(), nPos
,
1312 g_pBreakIt
->GetLocale( rTNd
.GetLang( nPos
) ),
1313 nItrMode
, 1, nDone
);
1315 // Check if nPos is inside hidden text range:
1316 if ( SwCursorSkipMode::Hidden
& nMode
)
1318 sal_Int32 nHiddenStart
;
1319 sal_Int32 nHiddenEnd
;
1320 SwScriptInfo::GetBoundsOfHiddenRange( rTNd
, nPos
, nHiddenStart
, nHiddenEnd
);
1321 if ( nHiddenStart
!= COMPLETE_STRING
&& nHiddenStart
!= nPos
)
1336 bool SwContentNode::GoPrevious(SwContentIndex
* pIdx
, SwCursorSkipMode nMode
) const
1339 if( pIdx
->GetIndex() > 0 )
1345 const SwTextNode
& rTNd
= *GetTextNode();
1346 sal_Int32 nPos
= pIdx
->GetIndex();
1347 assert(g_pBreakIt
&& g_pBreakIt
->GetBreakIter().is());
1348 sal_Int32 nDone
= 0;
1349 sal_uInt16 nItrMode
= ( SwCursorSkipMode::Cells
& nMode
) ?
1350 CharacterIteratorMode::SKIPCELL
:
1351 CharacterIteratorMode::SKIPCONTROLCHARACTER
;
1352 nPos
= g_pBreakIt
->GetBreakIter()->previousCharacters( rTNd
.GetText(), nPos
,
1353 g_pBreakIt
->GetLocale( rTNd
.GetLang( nPos
) ),
1354 nItrMode
, 1, nDone
);
1356 // Check if nPos is inside hidden text range:
1357 if ( SwCursorSkipMode::Hidden
& nMode
)
1359 sal_Int32 nHiddenStart
;
1360 sal_Int32 nHiddenEnd
;
1361 SwScriptInfo::GetBoundsOfHiddenRange( rTNd
, nPos
, nHiddenStart
, nHiddenEnd
);
1362 if ( nHiddenStart
!= COMPLETE_STRING
)
1363 nPos
= nHiddenStart
;
1378 * Creates all Views for the Doc for this Node.
1379 * The created ContentFrames are attached to the corresponding Layout.
1381 void SwContentNode::MakeFramesForAdjacentContentNode(SwContentNode
& rNode
)
1383 OSL_ENSURE( &rNode
!= this,
1384 "No ContentNode or CopyNode and new Node identical." );
1386 if( !HasWriterListeners() || &rNode
== this ) // Do we actually have Frames?
1390 SwLayoutFrame
*pUpper
;
1391 // Create Frames for Nodes which come after the Table?
1392 OSL_ENSURE( FindTableNode() == rNode
.FindTableNode(), "Table confusion" );
1394 SwNode2Layout
aNode2Layout( *this, rNode
.GetIndex() );
1396 while( nullptr != (pUpper
= aNode2Layout
.UpperFrame( pFrame
, rNode
)) )
1398 if (pUpper
->getRootFrame()->HasMergedParas()
1399 && !rNode
.IsCreateFrameWhenHidingRedlines())
1403 SwFrame
*pNew
= rNode
.MakeFrame( pUpper
);
1404 pNew
->Paste( pUpper
, pFrame
);
1406 // notify accessibility paragraphs objects about changed
1407 // CONTENT_FLOWS_FROM/_TO relation.
1408 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1409 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1410 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1411 if ( pNew
->IsTextFrame() )
1413 SwViewShell
* pViewShell( pNew
->getRootFrame()->GetCurrShell() );
1414 if ( pViewShell
&& pViewShell
->GetLayout() &&
1415 pViewShell
->GetLayout()->IsAnyShellAccessible() )
1417 auto pNext
= pNew
->FindNextCnt( true );
1418 auto pPrev
= pNew
->FindPrevCnt();
1419 pViewShell
->InvalidateAccessibleParaFlowRelation(
1420 pNext
? pNext
->DynCastTextFrame() : nullptr,
1421 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1429 * Deletes all Views from the Doc for this Node.
1430 * The ContentFrames are removed from the corresponding Layout.
1432 void SwContentNode::DelFrames(SwRootFrame
const*const pLayout
)
1434 if( !HasWriterListeners() )
1437 SwIterator
<SwContentFrame
, SwContentNode
, sw::IteratorMode::UnwrapMulti
> aIter(*this);
1438 for( SwContentFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next() )
1440 if (pLayout
&& pLayout
!= pFrame
->getRootFrame())
1442 continue; // skip it
1444 if (pFrame
->IsTextFrame())
1446 if (sw::MergedPara
* pMerged
=
1447 static_cast<SwTextFrame
*>(pFrame
)->GetMergedPara())
1449 if (this != pMerged
->pFirstNode
)
1451 // SwNodes::RemoveNode iterates *backwards* - so
1452 // ensure there are no more extents pointing to this
1453 // node as SwFrame::InvalidatePage() will access them.
1454 // Note: cannot send via SwClientNotify from dtor
1455 // because that would access deleted wrong-lists
1456 sw::UpdateMergedParaForDelete(*pMerged
, true,
1457 *static_cast<SwTextNode
*>(this), 0, Len());
1458 if (this == pMerged
->pParaPropsNode
)
1460 // otherwise pointer should have been updated to a different node
1461 assert(this == pMerged
->pLastNode
);
1462 assert(pMerged
->extents
.empty());
1463 for (SwNodeOffset i
= pMerged
->pLastNode
->GetIndex() - 1;;
1466 assert(pMerged
->pFirstNode
->GetIndex() <= i
);
1467 SwNode
*const pNode(GetNodes()[i
]);
1468 if (pNode
->IsTextNode()
1469 && pNode
->GetRedlineMergeFlag() != Merge::Hidden
)
1471 pMerged
->pParaPropsNode
= pNode
->GetTextNode();
1474 else if (pMerged
->pFirstNode
->GetIndex() == i
)
1475 { // this can only happen when called from CheckParaRedlineMerge()
1476 // and the pMerged will be deleted anyway
1477 pMerged
->pParaPropsNode
= pMerged
->pFirstNode
;
1481 assert(pMerged
->listener
.IsListeningTo(pMerged
->pParaPropsNode
));
1483 assert(GetIndex() <= pMerged
->pLastNode
->GetIndex());
1484 if (this == pMerged
->pLastNode
)
1486 // tdf#130680 find the previous node that is a
1487 // listener of pMerged; see CheckParaRedlineMerge()
1488 for (SwNodeOffset i
= GetIndex() - 1;
1489 this == pMerged
->pLastNode
; --i
)
1491 SwNode
*const pNode
= GetNodes()[i
];
1492 if (pNode
->IsTextNode())
1494 pMerged
->pLastNode
= pNode
->GetTextNode();
1496 else if (SwEndNode
const*const pEnd
= pNode
->GetEndNode())
1498 SwStartNode
const*const pStart(pEnd
->StartOfSectionNode());
1499 i
= pStart
->GetIndex(); // skip table or section
1502 assert(pMerged
->pFirstNode
->GetIndex() <= pMerged
->pLastNode
->GetIndex());
1503 assert(pMerged
->listener
.IsListeningTo(pMerged
->pLastNode
));
1505 // avoid re-parenting mess (ModifyChangedHint)
1506 pMerged
->listener
.EndListening(this);
1507 continue; // don't delete
1511 // notify accessibility paragraphs objects about changed
1512 // CONTENT_FLOWS_FROM/_TO relation.
1513 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
1514 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
1515 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1516 SwViewShell
* pViewShell( pFrame
->getRootFrame()->GetCurrShell() );
1517 if ( pViewShell
&& pViewShell
->GetLayout() &&
1518 pViewShell
->GetLayout()->IsAnyShellAccessible() )
1520 auto pNext
= pFrame
->FindNextCnt( true );
1521 auto pPrev
= pFrame
->FindPrevCnt();
1522 pViewShell
->InvalidateAccessibleParaFlowRelation(
1523 pNext
? pNext
->DynCastTextFrame() : nullptr,
1524 pPrev
? pPrev
->DynCastTextFrame() : nullptr );
1529 if( pFrame
->IsFollow() )
1531 SwContentFrame
* pMaster
= pFrame
->FindMaster();
1532 pMaster
->SetFollow( pFrame
->GetFollow() );
1534 pFrame
->SetFollow( nullptr );//So it doesn't get funny ideas.
1535 //Otherwise it could be possible that a follow
1536 //gets destroyed before its master. Following
1537 //the now invalid pointer will then lead to an
1538 //illegal memory access. The chain can be
1539 //crushed here because we'll destroy all of it
1542 if( pFrame
->GetUpper() && pFrame
->IsInFootnote() && !pFrame
->GetIndNext() &&
1543 !pFrame
->GetIndPrev() )
1545 SwFootnoteFrame
*pFootnote
= pFrame
->FindFootnoteFrame();
1546 OSL_ENSURE( pFootnote
, "You promised a FootnoteFrame?" );
1547 SwContentFrame
* pCFrame
;
1548 if( !pFootnote
->GetFollow() && !pFootnote
->GetMaster() &&
1549 nullptr != ( pCFrame
= pFootnote
->GetRefFromAttr()) && pCFrame
->IsFollow() )
1551 OSL_ENSURE( pCFrame
->IsTextFrame(), "NoTextFrame has Footnote?" );
1552 pCFrame
->FindMaster()->Prepare( PrepareHint::FootnoteInvalidationGone
);
1556 SwFrame::DestroyFrame(pFrame
);
1560 SwContentNode
*SwContentNode::JoinNext()
1566 /// Get info from Modify
1567 bool SwContentNode::GetInfo( SfxPoolItem
& rInfo
) const
1569 switch( rInfo
.Which() )
1571 case RES_FINDNEARESTNODE
:
1572 if( GetAttr( RES_PAGEDESC
).GetPageDesc() )
1573 static_cast<SwFindNearestNode
&>(rInfo
).CheckNode( *this );
1575 case RES_AUTOFMT_DOCNODE
:
1576 if( &GetNodes() == static_cast<SwAutoFormatGetDocNode
&>(rInfo
).pNodes
)
1582 return sw::BroadcastingModify::GetInfo( rInfo
);
1585 /// @param rAttr the attribute to set
1586 bool SwContentNode::SetAttr(const SfxPoolItem
& rAttr
)
1588 if( !GetpSwAttrSet() ) // Have the Nodes created by the corresponding AttrSets
1589 NewAttrSet( GetDoc().GetAttrPool() );
1591 OSL_ENSURE( GetpSwAttrSet(), "Why did't we create an AttrSet?");
1593 InvalidateInSwCache(RES_ATTRSET_CHG
);
1596 // If Modify is locked, we do not send any Modifys
1597 if( IsModifyLocked() ||
1598 ( !HasWriterListeners() && RES_PARATR_NUMRULE
!= rAttr
.Which() ))
1600 bRet
= nullptr != AttrSetHandleHelper::Put( mpAttrSet
, *this, rAttr
);
1604 SwAttrSet
aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1605 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1606 bRet
= AttrSetHandleHelper::Put_BC( mpAttrSet
, *this, rAttr
, &aOld
, &aNew
);
1608 sw::ClientNotifyAttrChg(*this, *GetpSwAttrSet(), aOld
, aNew
);
1613 bool SwContentNode::SetAttr( const SfxItemSet
& rSet
)
1615 InvalidateInSwCache(RES_ATTRSET_CHG
);
1617 if( const SwFormatAutoFormat
* pFnd
= rSet
.GetItemIfSet( RES_AUTO_STYLE
, false ) )
1619 OSL_ENSURE( rSet
.Count() == 1, "SetAutoStyle mixed with other attributes?!" );
1621 // If there already is an attribute set (usually containing a numbering
1622 // item), we have to merge the attribute of the new set into the old set:
1623 bool bSetParent
= true;
1624 if ( GetpSwAttrSet() )
1627 AttrSetHandleHelper::Put( mpAttrSet
, *this, *pFnd
->GetStyleHandle() );
1631 mpAttrSet
= pFnd
->GetStyleHandle();
1636 // If the content node has a conditional style, we have to set the
1637 // string item containing the correct conditional style name (the
1638 // style name property has already been set during the import!)
1639 // In case we do not have a conditional style, we make use of the
1640 // fact that nobody else uses the attribute set behind the handle.
1641 // FME 2007-07-10 #i78124# If autostyle does not have a parent,
1642 // the string is empty.
1643 const SfxStringItem
* pNameItem
= nullptr;
1644 if ( nullptr != GetCondFormatColl() ||
1645 !(pNameItem
= mpAttrSet
->GetItemIfSet( RES_FRMATR_STYLE_NAME
, false )) ||
1646 pNameItem
->GetValue().isEmpty() )
1647 AttrSetHandleHelper::SetParent( mpAttrSet
, *this, &GetAnyFormatColl(), GetFormatColl() );
1649 const_cast<SfxItemSet
*>(mpAttrSet
.get())->SetParent( &GetFormatColl()->GetAttrSet() );
1655 if( !GetpSwAttrSet() ) // Have the AttrsSets created by the corresponding Nodes
1656 NewAttrSet( GetDoc().GetAttrPool() );
1659 // If Modify is locked, do not send any Modifys
1660 if ( IsModifyLocked() ||
1661 ( !HasWriterListeners() &&
1662 SfxItemState::SET
!= rSet
.GetItemState( RES_PARATR_NUMRULE
, false ) ) )
1664 // Some special treatment for Attributes
1665 bRet
= AttrSetHandleHelper::Put( mpAttrSet
, *this, rSet
);
1669 SwAttrSet
aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1670 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1671 bRet
= AttrSetHandleHelper::Put_BC( mpAttrSet
, *this, rSet
, &aOld
, &aNew
);
1673 sw::ClientNotifyAttrChg(*this, *GetpSwAttrSet(), aOld
, aNew
);
1678 // With nWhich it takes the Hint from the Delta array
1679 bool SwContentNode::ResetAttr( sal_uInt16 nWhich1
, sal_uInt16 nWhich2
)
1681 if( !GetpSwAttrSet() )
1684 InvalidateInSwCache(RES_ATTRSET_CHG
);
1686 // If Modify is locked, do not send out any Modifys
1687 if( IsModifyLocked() )
1689 sal_uInt16 nDel
= 0;
1690 if ( !nWhich2
|| nWhich2
< nWhich1
)
1692 nDel
= ClearItemsFromAttrSet( { nWhich1
} );
1695 nDel
= AttrSetHandleHelper::ClearItem_BC( mpAttrSet
, *this, nWhich1
, nWhich2
, nullptr, nullptr );
1697 if( !GetpSwAttrSet()->Count() ) // Empty? Delete
1702 // No valid area defined?
1703 if( !nWhich2
|| nWhich2
< nWhich1
)
1704 nWhich2
= nWhich1
; // Then set only this Item to 1st Id
1706 SwAttrSet
aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1707 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1708 bool bRet
= 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet
, *this, nWhich1
, nWhich2
, &aOld
, &aNew
);
1712 sw::ClientNotifyAttrChg(*this, *GetpSwAttrSet(), aOld
, aNew
);
1714 if( !GetpSwAttrSet()->Count() ) // Empty?, delete it
1720 bool SwContentNode::ResetAttr( const std::vector
<sal_uInt16
>& rWhichArr
)
1722 if( !GetpSwAttrSet() )
1725 InvalidateInSwCache(RES_ATTRSET_CHG
);
1726 // If Modify is locked, do not send out any Modifys
1727 sal_uInt16 nDel
= 0;
1728 if( IsModifyLocked() )
1730 nDel
= ClearItemsFromAttrSet( rWhichArr
);
1734 SwAttrSet
aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1735 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1737 for ( const auto& rWhich
: rWhichArr
)
1738 if( AttrSetHandleHelper::ClearItem_BC( mpAttrSet
, *this, rWhich
, &aOld
, &aNew
))
1742 sw::ClientNotifyAttrChg(*this, *GetpSwAttrSet(), aOld
, aNew
);
1744 if( !GetpSwAttrSet()->Count() ) // Empty?, delete it
1749 sal_uInt16
SwContentNode::ResetAllAttr()
1751 if( !GetpSwAttrSet() )
1753 InvalidateInSwCache(RES_ATTRSET_CHG
);
1755 // If Modify is locked, do not send out any Modifys
1756 if( IsModifyLocked() )
1758 sal_uInt16 nDel
= ClearItemsFromAttrSet( { 0 } );
1759 if( !GetpSwAttrSet()->Count() ) // Empty? Delete
1764 SwAttrSet
aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1765 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1766 bool bRet
= 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet
, *this, 0, &aOld
, &aNew
);
1770 sw::ClientNotifyAttrChg(*this, *GetpSwAttrSet(), aOld
, aNew
);
1771 if( !GetpSwAttrSet()->Count() ) // Empty? Delete
1774 return aNew
.Count();
1777 bool SwContentNode::GetAttr( SfxItemSet
& rSet
) const
1782 const SwAttrSet
& rAttrSet
= GetSwAttrSet();
1783 return rSet
.Set( rAttrSet
);
1786 sal_uInt16
SwContentNode::ClearItemsFromAttrSet( const std::vector
<sal_uInt16
>& rWhichIds
)
1788 sal_uInt16 nRet
= 0;
1789 if ( rWhichIds
.empty() )
1792 OSL_ENSURE( GetpSwAttrSet(), "no item set" );
1793 SwAttrSet
aNewAttrSet( *GetpSwAttrSet() );
1794 for ( const auto& rWhichId
: rWhichIds
)
1796 nRet
= nRet
+ aNewAttrSet
.ClearItem( rWhichId
);
1799 AttrSetHandleHelper::GetNewAutoStyle( mpAttrSet
, *this, aNewAttrSet
);
1804 const SfxPoolItem
* SwContentNode::GetNoCondAttr( sal_uInt16 nWhich
,
1805 bool bInParents
) const
1807 const SfxPoolItem
* pFnd
= nullptr;
1808 if( m_pCondColl
&& m_pCondColl
->GetRegisteredIn() )
1810 if( !GetpSwAttrSet() || ( SfxItemState::SET
!= GetpSwAttrSet()->GetItemState(
1811 nWhich
, false, &pFnd
) && bInParents
))
1813 (void)static_cast<const SwFormat
*>(GetRegisteredIn())->GetItemState( nWhich
, bInParents
, &pFnd
);
1816 // undo change of issue #i51029#
1817 // Note: <GetSwAttrSet()> returns <mpAttrSet>, if set, otherwise it returns
1818 // the attribute set of the paragraph style, which is valid for the
1819 // content node - see file <node.hxx>
1822 GetSwAttrSet().GetItemState( nWhich
, bInParents
, &pFnd
);
1827 static bool lcl_CheckMaxLength(SwNode
const& rPrev
, SwNode
const& rNext
)
1829 if (rPrev
.GetNodeType() != rNext
.GetNodeType())
1833 if (!rPrev
.IsTextNode())
1838 // Check if a node can contain the other (order is not significant)
1839 return rPrev
.GetTextNode()->GetSpaceLeft() > rNext
.GetTextNode()->Len();
1842 /// Can we join two Nodes?
1843 /// We can return the 2nd position in pIdx.
1844 bool SwContentNode::CanJoinNext( SwNodeIndex
* pIdx
) const
1846 const SwNodes
& rNds
= GetNodes();
1847 SwNodeIndex
aIdx( *this, 1 );
1849 const SwNode
* pNd
= this;
1850 while( aIdx
< rNds
.Count()-1 &&
1851 (( pNd
= &aIdx
.GetNode())->IsSectionNode() ||
1852 ( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsSectionNode() )))
1855 if (rNds
.Count()-1 == aIdx
.GetIndex())
1857 if (!lcl_CheckMaxLength(*this, *pNd
))
1866 /// Can we join two Nodes?
1867 /// We can return the 2nd position in pIdx.
1868 bool SwContentNode::CanJoinNext( SwPosition
* pIdx
) const
1870 const SwNodes
& rNds
= GetNodes();
1871 SwNodeIndex
aIdx( *this, 1 );
1873 const SwNode
* pNd
= this;
1874 while( aIdx
< rNds
.Count()-1 &&
1875 (( pNd
= &aIdx
.GetNode())->IsSectionNode() ||
1876 ( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsSectionNode() )))
1879 if (rNds
.Count()-1 == aIdx
.GetIndex())
1881 if (!lcl_CheckMaxLength(*this, *pNd
))
1890 /// Can we join two Nodes?
1891 /// We can return the 2nd position in pIdx.
1892 bool SwContentNode::CanJoinPrev( SwNodeIndex
* pIdx
) const
1894 SwNodeIndex
aIdx( *this, -1 );
1896 const SwNode
* pNd
= this;
1897 while( aIdx
.GetIndex() &&
1898 (( pNd
= &aIdx
.GetNode())->IsSectionNode() ||
1899 ( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsSectionNode() )))
1902 if (SwNodeOffset(0) == aIdx
.GetIndex())
1904 if (!lcl_CheckMaxLength(*pNd
, *this))
1913 void SwContentNode::SetCondFormatColl(SwFormatColl
* pColl
)
1915 if( !((!pColl
&& m_pCondColl
) || ( pColl
&& !m_pCondColl
) ||
1916 ( pColl
&& pColl
!= m_pCondColl
->GetRegisteredIn() )) )
1919 SwFormatColl
* pOldColl
= GetCondFormatColl();
1920 m_aCondCollListener
.EndListeningAll();
1922 m_aCondCollListener
.StartListening(pColl
);
1923 m_pCondColl
= pColl
;
1925 AttrSetHandleHelper::SetParent(mpAttrSet
, *this, &GetAnyFormatColl(), GetFormatColl());
1927 if(!IsModifyLocked())
1929 SwFormatChg
aTmp1(pOldColl
? pOldColl
: GetFormatColl());
1930 SwFormatChg
aTmp2(pColl
? pColl
: GetFormatColl());
1931 CallSwClientNotify(sw::LegacyModifyHint(&aTmp1
, &aTmp2
));
1933 InvalidateInSwCache(RES_ATTRSET_CHG
);
1936 bool SwContentNode::IsAnyCondition( SwCollCondition
& rTmp
) const
1938 const SwNodes
& rNds
= GetNodes();
1940 Master_CollCondition nCond
= Master_CollCondition::NONE
;
1941 const SwStartNode
* pSttNd
= StartOfSectionNode();
1944 switch( pSttNd
->GetNodeType() )
1946 case SwNodeType::Table
: nCond
= Master_CollCondition::PARA_IN_TABLEBODY
; break;
1947 case SwNodeType::Section
: nCond
= Master_CollCondition::PARA_IN_SECTION
; break;
1950 switch( pSttNd
->GetStartNodeType() )
1952 case SwTableBoxStartNode
:
1954 nCond
= Master_CollCondition::PARA_IN_TABLEBODY
;
1955 const SwTableNode
* pTableNd
= pSttNd
->FindTableNode();
1956 const SwTableBox
* pBox
;
1957 if( pTableNd
&& nullptr != ( pBox
= pTableNd
->GetTable().
1958 GetTableBox(pSttNd
->GetIndex()) ) &&
1959 pBox
->IsInHeadline( &pTableNd
->GetTable() ) )
1960 nCond
= Master_CollCondition::PARA_IN_TABLEHEAD
;
1963 case SwFlyStartNode
: nCond
= Master_CollCondition::PARA_IN_FRAME
; break;
1964 case SwFootnoteStartNode
:
1966 nCond
= Master_CollCondition::PARA_IN_FOOTNOTE
;
1967 const SwFootnoteIdxs
& rFootnoteArr
= rNds
.GetDoc().GetFootnoteIdxs();
1968 const SwTextFootnote
* pTextFootnote
;
1969 const SwNode
* pSrchNd
= pSttNd
;
1971 for( size_t n
= 0; n
< rFootnoteArr
.size(); ++n
)
1972 if( nullptr != ( pTextFootnote
= rFootnoteArr
[ n
])->GetStartNode() &&
1973 pSrchNd
== &pTextFootnote
->GetStartNode()->GetNode() )
1975 if( pTextFootnote
->GetFootnote().IsEndNote() )
1976 nCond
= Master_CollCondition::PARA_IN_ENDNOTE
;
1981 case SwHeaderStartNode
: nCond
= Master_CollCondition::PARA_IN_HEADER
; break;
1982 case SwFooterStartNode
: nCond
= Master_CollCondition::PARA_IN_FOOTER
; break;
1983 case SwNormalStartNode
: break;
1987 if( nCond
!= Master_CollCondition::NONE
)
1989 rTmp
.SetCondition( nCond
, 0 );
1992 pSttNd
= pSttNd
->GetIndex()
1993 ? pSttNd
->StartOfSectionNode()
1999 SwOutlineNodes::size_type nPos
;
2000 const SwOutlineNodes
& rOutlNds
= rNds
.GetOutLineNds();
2001 if( !rOutlNds
.empty() )
2003 if( !rOutlNds
.Seek_Entry( const_cast<SwContentNode
*>(this), &nPos
) && nPos
)
2005 if( nPos
< rOutlNds
.size() &&
2006 rOutlNds
[ nPos
]->GetIndex() < GetIndex() )
2008 SwTextNode
* pOutlNd
= rOutlNds
[ nPos
]->GetTextNode();
2010 if( pOutlNd
->IsOutline())
2012 rTmp
.SetCondition( Master_CollCondition::PARA_IN_OUTLINE
, pOutlNd
->GetAttrOutlineLevel() - 1 );
2022 void SwContentNode::ChkCondColl(const SwTextFormatColl
* pColl
)
2024 if(pColl
!= GetRegisteredIn())
2026 SAL_INFO("sw.core", "Not our cond collection, skipping check of Cond Colls.");
2029 if(&GetNodes() != &GetDoc().GetNodes())
2031 SAL_WARN("sw.core", "Nodes amiss, skipping check of Cond Colls.");
2034 // Check, just to be sure
2035 if( RES_CONDTXTFMTCOLL
!= GetFormatColl()->Which() )
2038 SwCollCondition
aTmp( nullptr, Master_CollCondition::NONE
, 0 );
2039 const SwCollCondition
* pCColl
;
2043 if( IsAnyCondition( aTmp
))
2045 pCColl
= static_cast<SwConditionTextFormatColl
*>(GetFormatColl())
2046 ->HasCondition( aTmp
);
2050 SetCondFormatColl( pCColl
->GetTextFormatColl() );
2058 if( IsTextNode() && static_cast<SwTextNode
*>(this)->GetNumRule())
2060 // Is at which Level in a list?
2061 aTmp
.SetCondition( Master_CollCondition::PARA_IN_LIST
,
2062 static_cast<SwTextNode
*>(this)->GetActualListLevel() );
2063 pCColl
= static_cast<SwConditionTextFormatColl
*>(GetFormatColl())->
2064 HasCondition( aTmp
);
2070 SetCondFormatColl( pCColl
->GetTextFormatColl() );
2071 else if( m_pCondColl
)
2072 SetCondFormatColl( nullptr );
2076 SvxFrameDirection
SwContentNode::GetTextDirection( const SwPosition
& rPos
,
2077 const Point
* pPt
) const
2079 SvxFrameDirection nRet
= SvxFrameDirection::Unknown
;
2085 // #i72024# - No format of the frame, because this can cause recursive layout actions
2086 std::pair
<Point
, bool> const tmp(aPt
, false);
2087 SwFrame
* pFrame
= getLayoutFrame(GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), &rPos
, &tmp
);
2091 if ( pFrame
->IsVertical() )
2093 if (pFrame
->IsVertLRBT())
2094 nRet
= SvxFrameDirection::Vertical_LR_BT
;
2095 else if (pFrame
->IsRightToLeft())
2096 nRet
= SvxFrameDirection::Vertical_LR_TB
;
2098 nRet
= SvxFrameDirection::Vertical_RL_TB
;
2102 if ( pFrame
->IsRightToLeft() )
2103 nRet
= SvxFrameDirection::Horizontal_RL_TB
;
2105 nRet
= SvxFrameDirection::Horizontal_LR_TB
;
2112 std::unique_ptr
<SwOLENodes
> SwContentNode::CreateOLENodesArray( const SwFormatColl
& rColl
, bool bOnlyWithInvalidSize
)
2114 std::unique_ptr
<SwOLENodes
> pNodes
;
2115 SwIterator
<SwContentNode
,SwFormatColl
> aIter( rColl
);
2116 for( SwContentNode
* pNd
= aIter
.First(); pNd
; pNd
= aIter
.Next() )
2118 SwOLENode
*pONd
= pNd
->GetOLENode();
2119 if ( pONd
&& (!bOnlyWithInvalidSize
|| pONd
->IsOLESizeInvalid()) )
2122 pNodes
.reset(new SwOLENodes
);
2123 pNodes
->push_back( pONd
);
2130 drawinglayer::attribute::SdrAllFillAttributesHelperPtr
SwContentNode::getSdrAllFillAttributesHelper() const
2132 return drawinglayer::attribute::SdrAllFillAttributesHelperPtr();
2136 * Document Interface Access
2138 const IDocumentSettingAccess
* SwNode::getIDocumentSettingAccess() const { return &GetDoc().GetDocumentSettingManager(); }
2139 const IDocumentDeviceAccess
& SwNode::getIDocumentDeviceAccess() const { return GetDoc().getIDocumentDeviceAccess(); }
2140 const IDocumentRedlineAccess
& SwNode::getIDocumentRedlineAccess() const { return GetDoc().getIDocumentRedlineAccess(); }
2141 const IDocumentStylePoolAccess
& SwNode::getIDocumentStylePoolAccess() const { return GetDoc().getIDocumentStylePoolAccess(); }
2142 const IDocumentDrawModelAccess
& SwNode::getIDocumentDrawModelAccess() const { return GetDoc().getIDocumentDrawModelAccess(); }
2143 const IDocumentLayoutAccess
& SwNode::getIDocumentLayoutAccess() const { return GetDoc().getIDocumentLayoutAccess(); }
2144 IDocumentLayoutAccess
& SwNode::getIDocumentLayoutAccess() { return GetDoc().getIDocumentLayoutAccess(); }
2145 const IDocumentLinksAdministration
& SwNode::getIDocumentLinksAdministration() const { return GetDoc().getIDocumentLinksAdministration(); }
2146 IDocumentLinksAdministration
& SwNode::getIDocumentLinksAdministration() { return GetDoc().getIDocumentLinksAdministration(); }
2147 const IDocumentFieldsAccess
& SwNode::getIDocumentFieldsAccess() const { return GetDoc().getIDocumentFieldsAccess(); }
2148 IDocumentFieldsAccess
& SwNode::getIDocumentFieldsAccess() { return GetDoc().getIDocumentFieldsAccess(); }
2149 IDocumentContentOperations
& SwNode::getIDocumentContentOperations() { return GetDoc().getIDocumentContentOperations(); }
2150 IDocumentListItems
& SwNode::getIDocumentListItems() { return GetDoc().getIDocumentListItems(); } // #i83479#
2152 const IDocumentMarkAccess
* SwNode::getIDocumentMarkAccess() const { return GetDoc().getIDocumentMarkAccess(); }
2153 IStyleAccess
& SwNode::getIDocumentStyleAccess() { return GetDoc().GetIStyleAccess(); }
2155 bool SwNode::IsInRedlines() const
2157 const SwDoc
& rDoc
= GetDoc();
2159 return rDoc
.getIDocumentRedlineAccess().IsInRedlines(*this);
2162 void SwNode::AddAnchoredFly(SwFrameFormat
*const pFlyFormat
)
2165 assert(pFlyFormat
->GetAnchor(false).GetAnchorNode() == this);
2166 // check node type, cf. SwFormatAnchor::SetAnchor()
2167 assert(IsTextNode() || IsStartNode() || IsTableNode());
2168 m_aAnchoredFlys
.push_back(pFlyFormat
);
2171 void SwNode::RemoveAnchoredFly(SwFrameFormat
*const pFlyFormat
)
2174 // cannot assert this in Remove because it is called when new anchor is already set
2175 // assert(&pFlyFormat->GetAnchor(false).GetContentAnchor()->GetNode() == this);
2176 assert(IsTextNode() || IsStartNode() || IsTableNode());
2177 auto it(std::find(m_aAnchoredFlys
.begin(), m_aAnchoredFlys
.end(), pFlyFormat
));
2178 assert(it
!= m_aAnchoredFlys
.end());
2179 m_aAnchoredFlys
.erase(it
);
2182 void SwNode::resetAndQueueAccessibilityCheck(bool bIssueObjectNameChanged
)
2184 GetDoc().getOnlineAccessibilityCheck()->resetAndQueue(this, bIssueObjectNameChanged
);
2188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */