Bug Summary

File:home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx
Warning:line 810, column 58
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name node.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <hintids.hxx>
21#include <editeng/protitem.hxx>
22#include <tools/gen.hxx>
23#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
24#include <com/sun/star/i18n/XBreakIterator.hpp>
25#include <fmtcntnt.hxx>
26#include <fmtanchr.hxx>
27#include <frmfmt.hxx>
28#include <txtftn.hxx>
29#include <ftnfrm.hxx>
30#include <doc.hxx>
31#include <docary.hxx>
32#include <node.hxx>
33#include <ndindex.hxx>
34#include <numrule.hxx>
35#include <swtable.hxx>
36#include <ndtxt.hxx>
37#include <pam.hxx>
38#include <swcache.hxx>
39#include <section.hxx>
40#include <cntfrm.hxx>
41#include <flyfrm.hxx>
42#include <txtfrm.hxx>
43#include <tabfrm.hxx>
44#include <viewsh.hxx>
45#include <paratr.hxx>
46#include <ftnidx.hxx>
47#include <fmtftn.hxx>
48#include <fmthdft.hxx>
49#include <frmatr.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>
66#include <calbck.hxx>
67#include <ndole.hxx>
68#include <memory>
69#include <swcrsr.hxx>
70#include <hints.hxx>
71#include <frameformats.hxx>
72
73using namespace ::com::sun::star::i18n;
74
75
76/*
77 * Some local helper functions for the attribute set handle of a content node.
78 * Since the attribute set of a content node may not be modified directly,
79 * we always have to create a new SwAttrSet, do the modifications, and get
80 * a new handle from the style access
81 */
82
83namespace AttrSetHandleHelper
84{
85
86static void GetNewAutoStyle( std::shared_ptr<const SfxItemSet>& rpAttrSet,
87 const SwContentNode& rNode,
88 SwAttrSet const & rNewAttrSet )
89{
90 const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(rpAttrSet.get());
91 if( rNode.GetModifyAtAttr() )
92 const_cast<SwAttrSet*>(pAttrSet)->SetModifyAtAttr( nullptr );
93 IStyleAccess& rSA = pAttrSet->GetPool()->GetDoc()->GetIStyleAccess();
94 rpAttrSet = rSA.getAutomaticStyle( rNewAttrSet, rNode.IsTextNode() ?
95 IStyleAccess::AUTO_STYLE_PARA :
96 IStyleAccess::AUTO_STYLE_NOTXT );
97 const bool bSetModifyAtAttr = const_cast<SwAttrSet*>(static_cast<const SwAttrSet*>(rpAttrSet.get()))->SetModifyAtAttr( &rNode );
98 rNode.SetModifyAtAttr( bSetModifyAtAttr );
99}
100
101static void SetParent( std::shared_ptr<const SfxItemSet>& rpAttrSet,
102 const SwContentNode& rNode,
103 const SwFormat* pParentFormat,
104 const SwFormat* pConditionalFormat )
105{
106 const SwAttrSet* pAttrSet = static_cast<const SwAttrSet*>(rpAttrSet.get());
107 OSL_ENSURE( pAttrSet, "no SwAttrSet" )do { if (true && (!(pAttrSet))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "107" ": "), "%s", "no SwAttrSet"); } } while (false)
;
108 OSL_ENSURE( pParentFormat || !pConditionalFormat, "ConditionalFormat without ParentFormat?" )do { if (true && (!(pParentFormat || !pConditionalFormat
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "108" ": "), "%s", "ConditionalFormat without ParentFormat?"
); } } while (false)
;
109
110 const SwAttrSet* pParentSet = pParentFormat ? &pParentFormat->GetAttrSet() : nullptr;
111
112 if ( pParentSet == pAttrSet->GetParent() )
113 return;
114
115 SwAttrSet aNewSet( *pAttrSet );
116 aNewSet.SetParent( pParentSet );
117 aNewSet.ClearItem( RES_FRMATR_STYLE_NAME );
118 aNewSet.ClearItem( RES_FRMATR_CONDITIONAL_STYLE_NAME );
119
120 if ( pParentFormat )
121 {
122 OUString sVal;
123 SwStyleNameMapper::FillProgName( pParentFormat->GetName(), sVal, SwGetPoolIdFromName::TxtColl );
124 const SfxStringItem aAnyFormatColl( RES_FRMATR_STYLE_NAME, sVal );
125 aNewSet.Put( aAnyFormatColl );
126
127 if ( pConditionalFormat != pParentFormat )
128 SwStyleNameMapper::FillProgName( pConditionalFormat->GetName(), sVal, SwGetPoolIdFromName::TxtColl );
129
130 const SfxStringItem aFormatColl( RES_FRMATR_CONDITIONAL_STYLE_NAME, sVal );
131 aNewSet.Put( aFormatColl );
132 }
133
134 GetNewAutoStyle( rpAttrSet, rNode, aNewSet );
135}
136
137static const SfxPoolItem* Put( std::shared_ptr<const SfxItemSet>& rpAttrSet,
138 const SwContentNode& rNode,
139 const SfxPoolItem& rAttr )
140{
141 SwAttrSet aNewSet( static_cast<const SwAttrSet&>(*rpAttrSet) );
142 const SfxPoolItem* pRet = aNewSet.Put( rAttr );
143 if ( pRet )
144 GetNewAutoStyle( rpAttrSet, rNode, aNewSet );
145 return pRet;
146}
147
148static bool Put( std::shared_ptr<const SfxItemSet>& rpAttrSet, const SwContentNode& rNode,
149 const SfxItemSet& rSet )
150{
151 SwAttrSet aNewSet( static_cast<const SwAttrSet&>(*rpAttrSet) );
152
153 // #i76273# Robust
154 std::unique_ptr<SfxItemSet> pStyleNames;
155 if ( SfxItemState::SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, false ) )
156 {
157 pStyleNames.reset(new SfxItemSet( *aNewSet.GetPool(), svl::Items<RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME>{} ));
158 pStyleNames->Put( aNewSet );
159 }
160
161 const bool bRet = aNewSet.Put( rSet );
162
163 // #i76273# Robust
164 if ( pStyleNames )
165 {
166 aNewSet.Put( *pStyleNames );
167 }
168
169 if ( bRet )
170 GetNewAutoStyle( rpAttrSet, rNode, aNewSet );
171
172 return bRet;
173}
174
175static bool Put_BC( std::shared_ptr<const SfxItemSet>& rpAttrSet,
176 const SwContentNode& rNode, const SfxPoolItem& rAttr,
177 SwAttrSet* pOld, SwAttrSet* pNew )
178{
179 SwAttrSet aNewSet( static_cast<const SwAttrSet&>(*rpAttrSet) );
180
181 // for a correct broadcast, we need to do a SetModifyAtAttr with the items
182 // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
183 if( rNode.GetModifyAtAttr() )
184 aNewSet.SetModifyAtAttr( &rNode );
185
186 const bool bRet = aNewSet.Put_BC( rAttr, pOld, pNew );
187
188 if ( bRet )
189 GetNewAutoStyle( rpAttrSet, rNode, aNewSet );
190
191 return bRet;
192}
193
194static bool Put_BC( std::shared_ptr<const SfxItemSet>& rpAttrSet,
195 const SwContentNode& rNode, const SfxItemSet& rSet,
196 SwAttrSet* pOld, SwAttrSet* pNew )
197{
198 SwAttrSet aNewSet( static_cast<const SwAttrSet&>(*rpAttrSet) );
199
200 // #i76273# Robust
201 std::unique_ptr<SfxItemSet> pStyleNames;
202 if ( SfxItemState::SET == rSet.GetItemState( RES_FRMATR_STYLE_NAME, false ) )
203 {
204 pStyleNames.reset(new SfxItemSet( *aNewSet.GetPool(), svl::Items<RES_FRMATR_STYLE_NAME, RES_FRMATR_CONDITIONAL_STYLE_NAME>{} ));
205 pStyleNames->Put( aNewSet );
206 }
207
208 // for a correct broadcast, we need to do a SetModifyAtAttr with the items
209 // from aNewSet. The 'regular' SetModifyAtAttr is done in GetNewAutoStyle
210 if( rNode.GetModifyAtAttr() )
211 aNewSet.SetModifyAtAttr( &rNode );
212
213 const bool bRet = aNewSet.Put_BC( rSet, pOld, pNew );
214
215 // #i76273# Robust
216 if ( pStyleNames )
217 {
218 aNewSet.Put( *pStyleNames );
219 }
220
221 if ( bRet )
222 GetNewAutoStyle( rpAttrSet, rNode, aNewSet );
223
224 return bRet;
225}
226
227static sal_uInt16 ClearItem_BC( std::shared_ptr<const SfxItemSet>& rpAttrSet,
228 const SwContentNode& rNode, sal_uInt16 nWhich,
229 SwAttrSet* pOld, SwAttrSet* pNew )
230{
231 SwAttrSet aNewSet( static_cast<const SwAttrSet&>(*rpAttrSet) );
232 if( rNode.GetModifyAtAttr() )
233 aNewSet.SetModifyAtAttr( &rNode );
234 const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich, pOld, pNew );
235 if ( nRet )
236 GetNewAutoStyle( rpAttrSet, rNode, aNewSet );
237 return nRet;
238}
239
240static sal_uInt16 ClearItem_BC( std::shared_ptr<const SfxItemSet>& rpAttrSet,
241 const SwContentNode& rNode,
242 sal_uInt16 nWhich1, sal_uInt16 nWhich2,
243 SwAttrSet* pOld, SwAttrSet* pNew )
244{
245 SwAttrSet aNewSet( static_cast<const SwAttrSet&>(*rpAttrSet) );
246 if( rNode.GetModifyAtAttr() )
247 aNewSet.SetModifyAtAttr( &rNode );
248 const sal_uInt16 nRet = aNewSet.ClearItem_BC( nWhich1, nWhich2, pOld, pNew );
249 if ( nRet )
250 GetNewAutoStyle( rpAttrSet, rNode, aNewSet );
251 return nRet;
252}
253
254}
255
256/** Returns the section level at the position given by aIndex.
257 *
258 * We use the following logic:
259 * S = Start, E = End, C = ContentNode
260 * Level 0 = E
261 * 1 = S E
262 * 2 = SC
263 *
264 * All EndNodes of the BaseSection have level 0
265 * All StartNodes of the BaseSection have level 1
266 */
267sal_uInt16 SwNode::GetSectionLevel() const
268{
269 // EndNode of a BaseSection? They are always 0!
270 if( IsEndNode() && 0 == m_pStartOfSection->StartOfSectionIndex() )
271 return 0;
272
273 sal_uInt16 nLevel;
274 const SwNode* pNode = IsStartNode() ? this : m_pStartOfSection;
275 for( nLevel = 1; 0 != pNode->StartOfSectionIndex(); ++nLevel )
276 pNode = pNode->m_pStartOfSection;
277 return IsEndNode() ? nLevel-1 : nLevel;
278}
279
280#ifdef DBG_UTIL
281long SwNode::s_nSerial = 0;
282#endif
283
284SwNode::SwNode( const SwNodeIndex &rWhere, const SwNodeType nNdType )
285 : m_nNodeType( nNdType )
286 , m_nAFormatNumLvl( 0 )
287 , m_bIgnoreDontExpand( false)
288 , m_eMerge(Merge::None)
289#ifdef DBG_UTIL
290 , m_nSerial( s_nSerial++)
291#endif
292 , m_pStartOfSection( nullptr )
293{
294 if( !rWhere.GetIndex() )
295 return;
296
297 SwNodes& rNodes = const_cast<SwNodes&> (rWhere.GetNodes());
298 SwNode* pNd = rNodes[ rWhere.GetIndex() -1 ];
299 rNodes.InsertNode( this, rWhere );
300 m_pStartOfSection = pNd->GetStartNode();
301 if( nullptr == m_pStartOfSection )
302 {
303 m_pStartOfSection = pNd->m_pStartOfSection;
304 if( pNd->GetEndNode() ) // Skip EndNode ? Section
305 {
306 pNd = m_pStartOfSection;
307 m_pStartOfSection = pNd->m_pStartOfSection;
308 }
309 }
310}
311
312/** Inserts a node into the rNodes array at the rWhere position
313 *
314 * @param rNodes the variable array in that the node will be inserted
315 * @param nPos position within the array where the node will be inserted
316 * @param nNdType the type of node to insert
317 */
318SwNode::SwNode( SwNodes& rNodes, sal_uLong nPos, const SwNodeType nNdType )
319 : m_nNodeType( nNdType )
320 , m_nAFormatNumLvl( 0 )
321 , m_bIgnoreDontExpand( false)
322 , m_eMerge(Merge::None)
323#ifdef DBG_UTIL
324 , m_nSerial( s_nSerial++)
325#endif
326 , m_pStartOfSection( nullptr )
327{
328 if( !nPos )
329 return;
330
331 SwNode* pNd = rNodes[ nPos - 1 ];
332 rNodes.InsertNode( this, nPos );
333 m_pStartOfSection = pNd->GetStartNode();
334 if( nullptr == m_pStartOfSection )
335 {
336 m_pStartOfSection = pNd->m_pStartOfSection;
337 if( pNd->GetEndNode() ) // Skip EndNode ? Section!
338 {
339 pNd = m_pStartOfSection;
340 m_pStartOfSection = pNd->m_pStartOfSection;
341 }
342 }
343}
344
345SwNode::~SwNode()
346{
347 assert(!m_pAnchoredFlys || GetDoc().IsInDtor())(static_cast <bool> (!m_pAnchoredFlys || GetDoc().IsInDtor
()) ? void (0) : __assert_fail ("!m_pAnchoredFlys || GetDoc().IsInDtor()"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 347, __extension__ __PRETTY_FUNCTION__))
; // must all be deleted
348}
349
350/// Find the TableNode in which it is located.
351/// If we're not in a table: return 0
352SwTableNode* SwNode::FindTableNode()
353{
354 if( IsTableNode() )
355 return GetTableNode();
356 SwStartNode* pTmp = m_pStartOfSection;
357 while( !pTmp->IsTableNode() && pTmp->GetIndex() )
358 pTmp = pTmp->m_pStartOfSection;
359 return pTmp->GetTableNode();
360}
361
362/// Is the node located in the visible area of the Shell?
363bool SwNode::IsInVisibleArea( SwViewShell const * pSh ) const
364{
365 bool bRet = false;
366 const SwContentNode* pNd;
367
368 if( SwNodeType::Start & m_nNodeType )
369 {
370 SwNodeIndex aIdx( *this );
371 pNd = GetNodes().GoNext( &aIdx );
372 }
373 else if( SwNodeType::End & m_nNodeType )
374 {
375 SwNodeIndex aIdx( *EndOfSectionNode() );
376 pNd = SwNodes::GoPrevious( &aIdx );
377 }
378 else
379 pNd = GetContentNode();
380
381 if( !pSh )
382 // Get the Shell from the Doc
383 pSh = GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell();
384
385 if( pSh )
386 {
387 const SwFrame* pFrame;
388 if (pNd && nullptr != (pFrame = pNd->getLayoutFrame(pSh->GetLayout(), nullptr, nullptr)))
389 {
390
391 if ( pFrame->IsInTab() )
392 pFrame = pFrame->FindTabFrame();
393
394 if( !pFrame->isFrameAreaDefinitionValid() )
395 {
396 do
397 {
398 pFrame = pFrame->FindPrev();
399 }
400 while ( pFrame && !pFrame->isFrameAreaDefinitionValid() );
401 }
402
403 if( !pFrame || pSh->VisArea().IsOver( pFrame->getFrameArea() ) )
404 bRet = true;
405 }
406 }
407
408 return bRet;
409}
410
411bool SwNode::IsInProtectSect() const
412{
413 const SwNode* pNd = SwNodeType::Section == m_nNodeType ? m_pStartOfSection : this;
414 const SwSectionNode* pSectNd = pNd->FindSectionNode();
415 return pSectNd && pSectNd->GetSection().IsProtectFlag();
416}
417
418/// Does the node contain anything protected?
419/// I.e.: Area/Frame/Table rows/... including the Anchor for
420/// Frames/Footnotes/...
421bool SwNode::IsProtect() const
422{
423 const SwNode* pNd = SwNodeType::Section == m_nNodeType ? m_pStartOfSection : this;
424 const SwStartNode* pSttNd = pNd->FindSectionNode();
425 if( pSttNd && static_cast<const SwSectionNode*>(pSttNd)->GetSection().IsProtectFlag() )
426 return true;
427
428 pSttNd = FindTableBoxStartNode();
429 if( nullptr != pSttNd )
430 {
431 SwContentFrame* pCFrame;
432 if( IsContentNode() && nullptr != (pCFrame = static_cast<const SwContentNode*>(this)->getLayoutFrame( GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) ))
433 return pCFrame->IsProtected();
434
435 const SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
436 GetTableBox( pSttNd->GetIndex() );
437 //Robust #149568
438 if( pBox && pBox->GetFrameFormat()->GetProtect().IsContentProtected() )
439 return true;
440 }
441
442 SwFrameFormat* pFlyFormat = GetFlyFormat();
443 if( pFlyFormat )
444 {
445 if (pFlyFormat->GetProtect().IsContentProtected())
446 return true;
447 const SwFormatAnchor& rAnchor = pFlyFormat->GetAnchor();
448 const SwPosition* pAnchorPos = rAnchor.GetContentAnchor();
449 if (!pAnchorPos)
450 return false;
451 const SwNode& rAnchorNd = pAnchorPos->nNode.GetNode();
452 return &rAnchorNd != this && rAnchorNd.IsProtect();
453 }
454
455 pSttNd = FindFootnoteStartNode();
456 if( nullptr != pSttNd )
457 {
458 const SwTextFootnote* pTFootnote = GetDoc().GetFootnoteIdxs().SeekEntry(
459 SwNodeIndex( *pSttNd ) );
460 if( pTFootnote )
461 return pTFootnote->GetTextNode().IsProtect();
462 }
463
464 return false;
465}
466
467/// Find the PageDesc that is used to format this node. If the Layout is available,
468/// we search through that. Else we can only do it the hard way by searching onwards through the nodes.
469const SwPageDesc* SwNode::FindPageDesc( size_t* pPgDescNdIdx ) const
470{
471 if ( !GetNodes().IsDocNodes() )
472 {
473 return nullptr;
474 }
475
476 const SwPageDesc* pPgDesc = nullptr;
477
478 const SwContentNode* pNode;
479 if( SwNodeType::Start & m_nNodeType )
480 {
481 SwNodeIndex aIdx( *this );
482 pNode = GetNodes().GoNext( &aIdx );
483 }
484 else if( SwNodeType::End & m_nNodeType )
485 {
486 SwNodeIndex aIdx( *EndOfSectionNode() );
487 pNode = SwNodes::GoPrevious( &aIdx );
488 }
489 else
490 {
491 pNode = GetContentNode();
492 if( pNode )
493 pPgDesc = static_cast<const SwFormatPageDesc&>(pNode->GetAttr( RES_PAGEDESC )).GetPageDesc();
494 }
495
496 // Are we going through the layout?
497 if( !pPgDesc )
498 {
499 const SwFrame* pFrame;
500 const SwPageFrame* pPage;
501 if (pNode && nullptr != (pFrame = pNode->getLayoutFrame(pNode->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, nullptr)) &&
502 nullptr != ( pPage = pFrame->FindPageFrame() ) )
503 {
504 pPgDesc = pPage->GetPageDesc();
505 if ( pPgDescNdIdx )
506 {
507 *pPgDescNdIdx = pNode->GetIndex();
508 }
509 }
510 }
511
512 if( !pPgDesc )
513 {
514 // Thus via the nodes array
515 const SwDoc& rDoc = GetDoc();
516 const SwNode* pNd = this;
517 const SwStartNode* pSttNd;
518 if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() &&
519 nullptr != ( pSttNd = pNd->FindFlyStartNode() ) )
520 {
521 // Find the right Anchor first
522 const SwFrameFormat* pFormat = nullptr;
523 const SwFrameFormats& rFormats = *rDoc.GetSpzFrameFormats();
524
525 for( size_t n = 0; n < rFormats.size(); ++n )
526 {
527 const SwFrameFormat* pFrameFormat = rFormats[ n ];
528 const SwFormatContent& rContent = pFrameFormat->GetContent();
529 if( rContent.GetContentIdx() &&
530 &rContent.GetContentIdx()->GetNode() == static_cast<SwNode const *>(pSttNd) )
531 {
532 pFormat = pFrameFormat;
533 break;
534 }
535 }
536
537 if( pFormat )
538 {
539 const SwFormatAnchor* pAnchor = &pFormat->GetAnchor();
540 if ((RndStdIds::FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
541 pAnchor->GetContentAnchor() )
542 {
543 pNd = &pAnchor->GetContentAnchor()->nNode.GetNode();
544 const SwNode* pFlyNd = pNd->FindFlyStartNode();
545 while( pFlyNd )
546 {
547 // Get up through the Anchor
548 size_t n;
549 for( n = 0; n < rFormats.size(); ++n )
550 {
551 const SwFrameFormat* pFrameFormat = rFormats[ n ];
552 const SwNodeIndex* pIdx = pFrameFormat->GetContent().
553 GetContentIdx();
554 if( pIdx && pFlyNd == &pIdx->GetNode() )
555 {
556 if( pFormat == pFrameFormat )
557 {
558 pNd = pFlyNd;
559 pFlyNd = nullptr;
560 break;
561 }
562 pAnchor = &pFrameFormat->GetAnchor();
563 if ((RndStdIds::FLY_AT_PAGE == pAnchor->GetAnchorId()) ||
564 !pAnchor->GetContentAnchor() )
565 {
566 pFlyNd = nullptr;
567 break;
568 }
569
570 pFlyNd = pAnchor->GetContentAnchor()->nNode.
571 GetNode().FindFlyStartNode();
572 break;
573 }
574 }
575 if( n >= rFormats.size() )
576 {
577 OSL_ENSURE( false, "FlySection, but no Format found" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "577" ": "), "%s", "FlySection, but no Format found"); }
} while (false)
;
578 return nullptr;
579 }
580 }
581 }
582 }
583 // pNd should now contain the correct Anchor or it's still this
584 }
585
586 if( pNd->GetIndex() < GetNodes().GetEndOfExtras().GetIndex() )
587 {
588 if( pNd->GetIndex() > GetNodes().GetEndOfAutotext().GetIndex() )
589 {
590 pPgDesc = &rDoc.GetPageDesc( 0 );
591 pNd = nullptr;
592 }
593 else
594 {
595 // Find the Body text node
596 if( nullptr != ( pSttNd = pNd->FindHeaderStartNode() ) ||
597 nullptr != ( pSttNd = pNd->FindFooterStartNode() ))
598 {
599 // Then find this StartNode in the PageDescs
600 sal_uInt16 nId;
601 UseOnPage eAskUse;
602 if( SwHeaderStartNode == pSttNd->GetStartNodeType())
603 {
604 nId = RES_HEADER;
605 eAskUse = UseOnPage::HeaderShare;
606 }
607 else
608 {
609 nId = RES_FOOTER;
610 eAskUse = UseOnPage::FooterShare;
611 }
612
613 for( size_t n = rDoc.GetPageDescCnt(); n && !pPgDesc; )
614 {
615 const SwPageDesc& rPgDsc = rDoc.GetPageDesc( --n );
616 const SwFrameFormat* pFormat = &rPgDsc.GetMaster();
617 int nStt = 0, nLast = 1;
618 if( !( eAskUse & rPgDsc.ReadUseOn() )) ++nLast;
619
620 for( ; nStt < nLast; ++nStt, pFormat = &rPgDsc.GetLeft() )
621 {
622 const SwFrameFormat * pHdFtFormat = nId == RES_HEADER
623 ? static_cast<SwFormatHeader const &>(
624 pFormat->GetFormatAttr(nId)).GetHeaderFormat()
625 : static_cast<SwFormatFooter const &>(
626 pFormat->GetFormatAttr(nId)).GetFooterFormat();
627 if( pHdFtFormat )
628 {
629 const SwFormatContent& rContent = pHdFtFormat->GetContent();
630 if( rContent.GetContentIdx() &&
631 &rContent.GetContentIdx()->GetNode() ==
632 static_cast<SwNode const *>(pSttNd) )
633 {
634 pPgDesc = &rPgDsc;
635 break;
636 }
637 }
638 }
639 }
640
641 if( !pPgDesc )
642 pPgDesc = &rDoc.GetPageDesc( 0 );
643 pNd = nullptr;
644 }
645 else if( nullptr != ( pSttNd = pNd->FindFootnoteStartNode() ))
646 {
647 // the Anchor can only be in the Body text
648 const SwTextFootnote* pTextFootnote;
649 const SwFootnoteIdxs& rFootnoteArr = rDoc.GetFootnoteIdxs();
650 for( size_t n = 0; n < rFootnoteArr.size(); ++n )
651 if( nullptr != ( pTextFootnote = rFootnoteArr[ n ])->GetStartNode() &&
652 static_cast<SwNode const *>(pSttNd) ==
653 &pTextFootnote->GetStartNode()->GetNode() )
654 {
655 pNd = &pTextFootnote->GetTextNode();
656 break;
657 }
658 }
659 else
660 {
661 // Can only be a page-bound Fly (or something newer).
662 // we can only return the standard here
663 OSL_ENSURE( pNd->FindFlyStartNode(),do { if (true && (!(pNd->FindFlyStartNode()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "664" ": "), "%s", "Where is this Node?"); } } while (false
)
664 "Where is this Node?" )do { if (true && (!(pNd->FindFlyStartNode()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "664" ": "), "%s", "Where is this Node?"); } } while (false
)
;
665
666 pPgDesc = &rDoc.GetPageDesc( 0 );
667 pNd = nullptr;
668 }
669 }
670 }
671
672 if( pNd )
673 {
674 SwFindNearestNode aInfo( *pNd );
675 // Over all Nodes of all PageDescs
676 for (const SfxPoolItem* pItem : rDoc.GetAttrPool().GetItemSurrogates(RES_PAGEDESC))
677 {
678 auto pPageDescItem = dynamic_cast<const SwFormatPageDesc*>(pItem);
679 if( pPageDescItem && pPageDescItem->GetDefinedIn() )
680 {
681 const SwModify* pMod = pPageDescItem->GetDefinedIn();
682 if( auto pContentNode = dynamic_cast<const SwContentNode*>( pMod) )
683 aInfo.CheckNode( *pContentNode );
684 else if( auto pFormat = dynamic_cast<const SwFormat*>( pMod) )
685 pFormat->GetInfo( aInfo );
686 }
687 }
688
689 pNd = aInfo.GetFoundNode();
690 if( nullptr != pNd )
691 {
692 if( pNd->IsContentNode() )
693 pPgDesc = static_cast<const SwFormatPageDesc&>(pNd->GetContentNode()->
694 GetAttr( RES_PAGEDESC )).GetPageDesc();
695 else if( pNd->IsTableNode() )
696 pPgDesc = pNd->GetTableNode()->GetTable().
697 GetFrameFormat()->GetPageDesc().GetPageDesc();
698 else if( pNd->IsSectionNode() )
699 pPgDesc = pNd->GetSectionNode()->GetSection().
700 GetFormat()->GetPageDesc().GetPageDesc();
701 if ( pPgDescNdIdx )
702 {
703 *pPgDescNdIdx = pNd->GetIndex();
704 }
705 }
706 if( !pPgDesc )
707 pPgDesc = &rDoc.GetPageDesc( 0 );
708 }
709 }
710 return pPgDesc;
711}
712
713/// If the node is located in a Fly, we return it formatted accordingly
714SwFrameFormat* SwNode::GetFlyFormat() const
715{
716 SwFrameFormat* pRet = nullptr;
717 const SwNode* pSttNd = FindFlyStartNode();
718 if( pSttNd )
719 {
720 if( IsContentNode() )
721 {
722 SwContentFrame* pFrame = SwIterator<SwContentFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*static_cast<const SwContentNode*>(this)).First();
723 if( pFrame )
724 pRet = pFrame->FindFlyFrame()->GetFormat();
725 }
726 if( !pRet )
727 {
728 // The hard way through the Doc is our last way out
729 const SwFrameFormats& rFrameFormatTable = *GetDoc().GetSpzFrameFormats();
730 for( size_t n = 0; n < rFrameFormatTable.size(); ++n )
731 {
732 SwFrameFormat* pFormat = rFrameFormatTable[n];
733 // Only Writer fly frames can contain Writer nodes.
734 if (pFormat->Which() != RES_FLYFRMFMT)
735 continue;
736 const SwFormatContent& rContent = pFormat->GetContent();
737 if( rContent.GetContentIdx() &&
738 &rContent.GetContentIdx()->GetNode() == pSttNd )
739 {
740 pRet = pFormat;
741 break;
742 }
743 }
744 }
745 }
746 return pRet;
747}
748
749SwTableBox* SwNode::GetTableBox() const
750{
751 SwTableBox* pBox = nullptr;
752 const SwNode* pSttNd = FindTableBoxStartNode();
753 if( pSttNd )
754 pBox = const_cast<SwTableBox*>(pSttNd->FindTableNode()->GetTable().GetTableBox(
755 pSttNd->GetIndex() ));
756 return pBox;
757}
758
759SwStartNode* SwNode::FindSttNodeByType( SwStartNodeType eTyp )
760{
761 SwStartNode* pTmp = IsStartNode() ? static_cast<SwStartNode*>(this) : m_pStartOfSection;
762
763 while( eTyp != pTmp->GetStartNodeType() && pTmp->GetIndex() )
764 pTmp = pTmp->m_pStartOfSection;
765 return eTyp == pTmp->GetStartNodeType() ? pTmp : nullptr;
766}
767
768const SwTextNode* SwNode::FindOutlineNodeOfLevel(sal_uInt8 const nLvl,
769 SwRootFrame const*const pLayout) const
770{
771 const SwTextNode* pRet = nullptr;
1
'pRet' initialized to a null pointer value
772 const SwOutlineNodes& rONds = GetNodes().GetOutLineNds();
773 if( MAXLEVEL > nLvl && !rONds.empty() )
2
Assuming 'MAXLEVEL' is > 'nLvl'
3
Assuming the condition is true
4
Taking true branch
774 {
775 SwOutlineNodes::size_type nPos;
776 SwNode* pNd = const_cast<SwNode*>(this);
777 bool bCheckFirst = false;
778 if( !rONds.Seek_Entry( pNd, &nPos ))
5
Assuming the condition is true
6
Taking true branch
779 {
780 if (nPos == 0)
7
Assuming 'nPos' is equal to 0
8
Taking true branch
781 bCheckFirst = true;
782 }
783 else
784 {
785 ++nPos;
786 }
787
788 if( bCheckFirst
8.1
'bCheckFirst' is true
)
9
Taking true branch
789 {
790 // The first OutlineNode comes after the one asking.
791 // Test if both are on the same page.
792 // If not it's invalid.
793 for (nPos = 0; nPos < rONds.size(); ++nPos)
10
Assuming the condition is false
11
Loop condition is false. Execution continues on line 801
794 {
795 pRet = rONds[nPos]->GetTextNode();
796 if (!pLayout || sw::IsParaPropsNode(*pLayout, *pRet))
797 {
798 break;
799 }
800 }
801 if (nPos == rONds.size())
12
Assuming the condition is false
13
Taking false branch
802 {
803 return nullptr;
804 }
805
806 const SwContentNode* pCNd = GetContentNode();
807
808 Point aPt( 0, 0 );
809 std::pair<Point, bool> const tmp(aPt, false);
810 const SwFrame* pFrame = pRet->getLayoutFrame(pRet->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp),
14
Called C++ object pointer is null
811 * pMyFrame = pCNd ? pCNd->getLayoutFrame(pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), nullptr, &tmp) : nullptr;
812 const SwPageFrame* pPgFrame = pFrame ? pFrame->FindPageFrame() : nullptr;
813 if( pPgFrame && pMyFrame &&
814 pPgFrame->getFrameArea().Top() > pMyFrame->getFrameArea().Top() )
815 {
816 // The one asking precedes the Page, thus its invalid
817 pRet = nullptr;
818 }
819 }
820 else
821 {
822 for ( ; 0 < nPos; --nPos)
823 {
824 SwTextNode const*const pNode = rONds[nPos - 1]->GetTextNode();
825 if ((nPos == 1 /*as before*/ || pNode->GetAttrOutlineLevel() - 1 <= nLvl)
826 && (!pLayout || sw::IsParaPropsNode(*pLayout, *pNode)))
827 {
828 pRet = pNode;
829 break;
830 }
831 }
832 }
833 }
834 return pRet;
835}
836
837static bool IsValidNextPrevNd( const SwNode& rNd )
838{
839 return SwNodeType::Table == rNd.GetNodeType() ||
840 ( SwNodeType::ContentMask & rNd.GetNodeType() ) ||
841 ( SwNodeType::End == rNd.GetNodeType() && rNd.StartOfSectionNode() &&
842 SwNodeType::Table == rNd.StartOfSectionNode()->GetNodeType() );
843}
844
845sal_uInt8 SwNode::HasPrevNextLayNode() const
846{
847 // assumption: <this> node is a node inside the document nodes array section.
848
849 sal_uInt8 nRet = 0;
850 if( IsValidNextPrevNd( *this ))
851 {
852 SwNodeIndex aIdx( *this, -1 );
853 // #i77805# - skip section start and end nodes
854 while ( aIdx.GetNode().IsSectionNode() ||
855 ( aIdx.GetNode().IsEndNode() &&
856 aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
857 {
858 --aIdx;
859 }
860 if( IsValidNextPrevNd( aIdx.GetNode() ))
861 nRet |= ND_HAS_PREV_LAYNODE;
862 // #i77805# - skip section start and end nodes
863 aIdx.Assign(*this, +1);
864 while ( aIdx.GetNode().IsSectionNode() ||
865 ( aIdx.GetNode().IsEndNode() &&
866 aIdx.GetNode().StartOfSectionNode()->IsSectionNode() ) )
867 {
868 ++aIdx;
869 }
870 if( IsValidNextPrevNd( aIdx.GetNode() ))
871 nRet |= ND_HAS_NEXT_LAYNODE;
872 }
873 return nRet;
874}
875
876void SwNode::dumpAsXml(xmlTextWriterPtr pWriter) const
877{
878 const char* pName = "???";
879 switch (GetNodeType())
880 {
881 case SwNodeType::End:
882 pName = "end";
883 break;
884 case SwNodeType::Start:
885 case SwNodeType::Text:
886 case SwNodeType::Ole:
887 abort(); // overridden
888 case SwNodeType::Table:
889 pName = "table";
890 break;
891 case SwNodeType::Grf:
892 pName = "grf";
893 break;
894 default: break;
895 }
896 xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)(pName));
897
898 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST(xmlChar *)("ptr"), "%p", this);
899 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("type"), BAD_CAST(xmlChar *)(OString::number(static_cast<sal_uInt8>(GetNodeType())).getStr()));
900 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("index"), BAD_CAST(xmlChar *)(OString::number(GetIndex()).getStr()));
901
902 switch (GetNodeType())
903 {
904 case SwNodeType::Grf:
905 {
906 auto pNoTextNode = static_cast<const SwNoTextNode*>(this);
907 const tools::PolyPolygon* pContour = pNoTextNode->HasContour();
908 if (pContour)
909 {
910 xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("pContour"));
911 for (sal_uInt16 i = 0; i < pContour->Count(); ++i)
912 {
913 xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("polygon"));
914 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("index"),
915 BAD_CAST(xmlChar *)(OString::number(i).getStr()));
916 const tools::Polygon& rPolygon = pContour->GetObject(i);
917 for (sal_uInt16 j = 0; j < rPolygon.GetSize(); ++j)
918 {
919 xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("point"));
920 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("index"),
921 BAD_CAST(xmlChar *)(OString::number(j).getStr()));
922 const Point& rPoint = rPolygon.GetPoint(j);
923 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("x"),
924 BAD_CAST(xmlChar *)(OString::number(rPoint.X()).getStr()));
925 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("y"),
926 BAD_CAST(xmlChar *)(OString::number(rPoint.Y()).getStr()));
927 xmlTextWriterEndElement(pWriter);
928 }
929 xmlTextWriterEndElement(pWriter);
930 }
931 xmlTextWriterEndElement(pWriter);
932 }
933 }
934 break;
935 default:
936 break;
937 }
938
939 xmlTextWriterEndElement(pWriter);
940 if (GetNodeType() == SwNodeType::End)
941 xmlTextWriterEndElement(pWriter); // end start node
942}
943
944SwStartNode::SwStartNode( const SwNodeIndex &rWhere, const SwNodeType nNdType,
945 SwStartNodeType eSttNd )
946 : SwNode( rWhere, nNdType ), m_eStartNodeType( eSttNd )
947{
948 if( !rWhere.GetIndex() )
949 {
950 SwNodes& rNodes = const_cast<SwNodes&> (rWhere.GetNodes());
951 rNodes.InsertNode( this, rWhere );
952 m_pStartOfSection = this;
953 }
954 // Just do this temporarily until the EndNode is inserted
955 m_pEndOfSection = reinterpret_cast<SwEndNode*>(this);
956}
957
958SwStartNode::SwStartNode( SwNodes& rNodes, sal_uLong nPos )
959 : SwNode( rNodes, nPos, SwNodeType::Start ), m_eStartNodeType( SwNormalStartNode )
960{
961 if( !nPos )
962 {
963 rNodes.InsertNode( this, nPos );
964 m_pStartOfSection = this;
965 }
966 // Just do this temporarily until the EndNode is inserted
967 m_pEndOfSection = reinterpret_cast<SwEndNode*>(this);
968}
969
970void SwStartNode::CheckSectionCondColl() const
971{
972//FEATURE::CONDCOLL
973 SwNodeIndex aIdx( *this );
974 sal_uLong nEndIdx = EndOfSectionIndex();
975 const SwNodes& rNds = GetNodes();
976 SwContentNode* pCNd;
977 while( nullptr != ( pCNd = rNds.GoNext( &aIdx )) && pCNd->GetIndex() < nEndIdx )
978 pCNd->ChkCondColl();
979//FEATURE::CONDCOLL
980}
981
982void SwStartNode::dumpAsXml(xmlTextWriterPtr pWriter) const
983{
984 const char* pName = "???";
985 switch (GetNodeType())
986 {
987 case SwNodeType::Table:
988 pName = "table";
989 break;
990 case SwNodeType::Section:
991 pName = "section";
992 break;
993 default:
994 switch(GetStartNodeType())
995 {
996 case SwNormalStartNode:
997 pName = "start";
998 break;
999 case SwTableBoxStartNode:
1000 pName = "tablebox";
1001 break;
1002 case SwFlyStartNode:
1003 pName = "fly";
1004 break;
1005 case SwFootnoteStartNode:
1006 pName = "footnote";
1007 break;
1008 case SwHeaderStartNode:
1009 pName = "header";
1010 break;
1011 case SwFooterStartNode:
1012 pName = "footer";
1013 break;
1014 }
1015 break;
1016 }
1017
1018 xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)(pName));
1019 xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST(xmlChar *)("ptr"), "%p", this);
1020 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("type"), BAD_CAST(xmlChar *)(OString::number(static_cast<sal_uInt8>(GetNodeType())).getStr()));
1021 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("index"), BAD_CAST(xmlChar *)(OString::number(GetIndex()).getStr()));
1022
1023 if (IsTableNode())
1024 {
1025 xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("attrset"));
1026 GetTableNode()->GetTable().GetFrameFormat()->GetAttrSet().dumpAsXml(pWriter);
1027 xmlTextWriterEndElement(pWriter);
1028 }
1029 else if (GetStartNodeType() == SwTableBoxStartNode)
1030 {
1031 if (SwTableBox* pBox = GetTableBox())
1032 xmlTextWriterWriteAttribute(pWriter, BAD_CAST(xmlChar *)("rowspan"), BAD_CAST(xmlChar *)(OString::number(pBox->getRowSpan()).getStr()));
1033 xmlTextWriterStartElement(pWriter, BAD_CAST(xmlChar *)("attrset"));
1034 if (SwTableBox* pBox = GetTableBox())
1035 pBox->GetFrameFormat()->GetAttrSet().dumpAsXml(pWriter);
1036 xmlTextWriterEndElement(pWriter);
1037 }
1038
1039 // xmlTextWriterEndElement(pWriter); - it is a start node, so don't end, will make xml better nested
1040}
1041
1042
1043/** Insert a node into the array
1044 *
1045 * The StartOfSection pointer is set to the given node.
1046 *
1047 * The EndOfSection pointer of the corresponding start node is set to this node.
1048 *
1049 * @param rWhere position where the node shoul be inserted
1050 * @param rSttNd the start note of the section
1051 */
1052
1053SwEndNode::SwEndNode( const SwNodeIndex &rWhere, SwStartNode& rSttNd )
1054 : SwNode( rWhere, SwNodeType::End )
1055{
1056 m_pStartOfSection = &rSttNd;
1057 m_pStartOfSection->m_pEndOfSection = this;
1058}
1059
1060SwEndNode::SwEndNode( SwNodes& rNds, sal_uLong nPos, SwStartNode& rSttNd )
1061 : SwNode( rNds, nPos, SwNodeType::End )
1062{
1063 m_pStartOfSection = &rSttNd;
1064 m_pStartOfSection->m_pEndOfSection = this;
1065}
1066
1067SwContentNode::SwContentNode( const SwNodeIndex &rWhere, const SwNodeType nNdType,
1068 SwFormatColl *pColl )
1069 : SwNode( rWhere, nNdType )
1070 , m_aCondCollListener( *this )
1071 , m_pCondColl( nullptr )
1072 , mbSetModifyAtAttr( false )
1073{
1074 if(pColl)
1075 pColl->Add(this);
1076}
1077
1078SwContentNode::~SwContentNode()
1079{
1080 // The base class SwClient of SwFrame excludes itself from the dependency list!
1081 // Thus, we need to delete all Frames in the dependency list.
1082 if (!IsTextNode()) // see ~SwTextNode
1083 {
1084 DelFrames(nullptr);
1085 }
1086
1087 m_aCondCollListener.EndListeningAll();
1088 m_pCondColl = nullptr;
1089
1090 if ( mpAttrSet && mbSetModifyAtAttr )
1091 const_cast<SwAttrSet*>(static_cast<const SwAttrSet*>(mpAttrSet.get()))->SetModifyAtAttr( nullptr );
1092}
1093
1094void SwContentNode::SwClientNotify( const SwModify&, const SfxHint& rHint)
1095{
1096 if (auto pLegacyHint = dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
1097 {
1098 const sal_uInt16 nWhich = pLegacyHint->m_pOld
1099 ? pLegacyHint->m_pOld->Which()
1100 : pLegacyHint->m_pNew
1101 ? pLegacyHint->m_pNew->Which()
1102 : 0 ;
1103
1104 bool bSetParent = false;
1105 bool bCalcHidden = false;
1106 SwFormatColl* pFormatColl = nullptr;
1107 switch(nWhich)
1108 {
1109 case RES_OBJECTDYING:
1110 {
1111 SwFormat* pFormat = pLegacyHint->m_pNew
1112 ? static_cast<SwFormat*>(static_cast<const SwPtrMsgPoolItem*>(pLegacyHint->m_pNew)->pObject)
1113 : nullptr;
1114 // Do not mangle pointers if it is the upper-most format!
1115 if(pFormat && GetRegisteredIn() == pFormat)
1116 {
1117 if(pFormat->GetRegisteredIn())
1118 {
1119 // If Parent, register anew in the new Parent
1120 pFormat->GetRegisteredIn()->Add(this);
1121 pFormatColl = GetFormatColl();
1122 }
1123 else
1124 EndListeningAll();
1125 bSetParent = true;
1126 }
1127 }
1128 break;
1129
1130 case RES_FMT_CHG:
1131 // If the Format parent was switched, register the Attrset at the new one
1132 // Skip own Modify!
1133 if(GetpSwAttrSet()
1134 && pLegacyHint->m_pNew
1135 && static_cast<const SwFormatChg*>(pLegacyHint->m_pNew)->pChangedFormat == GetRegisteredIn())
1136 {
1137 pFormatColl = GetFormatColl();
1138 bSetParent = true;
1139 }
1140 break;
1141
1142 case RES_CONDCOLL_CONDCHG:
1143 if(pLegacyHint->m_pNew
1144 && static_cast<const SwCondCollCondChg*>(pLegacyHint->m_pNew)->pChangedFormat == GetRegisteredIn()
1145 && &GetNodes() == &GetDoc().GetNodes() )
1146 ChkCondColl();
1147 return; // Do not pass through to the base class/Frames
1148
1149 case RES_ATTRSET_CHG:
1150 if (GetNodes().IsDocNodes()
1151 && IsTextNode()
1152 && pLegacyHint->m_pOld
1153 && SfxItemState::SET == static_cast<const SwAttrSetChg*>(pLegacyHint->m_pOld)->GetChgSet()->GetItemState(RES_CHRATR_HIDDEN, false))
1154 bCalcHidden = true;
1155 break;
1156
1157 case RES_UPDATE_ATTR:
1158 if (GetNodes().IsDocNodes()
1159 && IsTextNode()
1160 && pLegacyHint->m_pNew
1161 && RES_ATTRSET_CHG == static_cast<const SwUpdateAttr*>(pLegacyHint->m_pNew)->getWhichAttr())
1162 bCalcHidden = true;
1163 break;
1164 }
1165 if(bSetParent && GetpSwAttrSet())
1166 AttrSetHandleHelper::SetParent(mpAttrSet, *this, pFormatColl, pFormatColl);
1167 if(bCalcHidden)
1168 static_cast<SwTextNode*>(this)->SetCalcHiddenCharFlags();
1169 NotifyClients(pLegacyHint->m_pOld, pLegacyHint->m_pNew);
1170 }
1171 else if (auto pModifyChangedHint = dynamic_cast<const sw::ModifyChangedHint*>(&rHint))
1172 {
1173 m_pCondColl = const_cast<SwFormatColl*>(static_cast<const SwFormatColl*>(pModifyChangedHint->m_pNew));
1174 }
1175}
1176
1177bool SwContentNode::InvalidateNumRule()
1178{
1179 SwNumRule* pRule = nullptr;
1180 const SfxPoolItem* pItem;
1181 if( GetNodes().IsDocNodes() &&
1182 nullptr != ( pItem = GetNoCondAttr( RES_PARATR_NUMRULE, true )) &&
1183 !static_cast<const SwNumRuleItem*>(pItem)->GetValue().isEmpty() &&
1184 nullptr != (pRule = GetDoc().FindNumRulePtr(
1185 static_cast<const SwNumRuleItem*>(pItem)->GetValue() ) ) )
1186 {
1187 pRule->SetInvalidRule( true );
1188 }
1189 return nullptr != pRule;
1190}
1191
1192SwContentFrame *SwContentNode::getLayoutFrame( const SwRootFrame* _pRoot,
1193 const SwPosition *const pPos,
1194 std::pair<Point, bool> const*const pViewPosAndCalcFrame) const
1195{
1196 return static_cast<SwContentFrame*>( ::GetFrameOfModify( _pRoot, *this, FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt),
1197 pPos, pViewPosAndCalcFrame));
1198}
1199
1200SwRect SwContentNode::FindLayoutRect( const bool bPrtArea, const Point* pPoint ) const
1201{
1202 SwRect aRet;
1203 std::pair<Point, bool> tmp;
1204 if (pPoint)
1205 {
1206 tmp.first = *pPoint;
1207 tmp.second = false;
1208 }
1209 SwContentFrame* pFrame = static_cast<SwContentFrame*>( ::GetFrameOfModify( nullptr, *this,
1210 FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt), nullptr, pPoint ? &tmp : nullptr) );
1211 if( pFrame )
1212 aRet = bPrtArea ? pFrame->getFramePrintArea() : pFrame->getFrameArea();
1213 return aRet;
1214}
1215
1216SwRect SwContentNode::FindPageFrameRect() const
1217{
1218 SwRect aRet;
1219 SwFrame* pFrame = ::GetFrameOfModify( nullptr, *this, FRM_CNTNT(SwFrameType::Txt | SwFrameType::NoTxt) );
1220 if( pFrame && nullptr != ( pFrame = pFrame->FindPageFrame() ))
1221 aRet = pFrame->getFrameArea();
1222 return aRet;
1223}
1224
1225sal_Int32 SwContentNode::Len() const { return 0; }
1226
1227SwFormatColl *SwContentNode::ChgFormatColl( SwFormatColl *pNewColl )
1228{
1229 OSL_ENSURE( pNewColl, "Collectionpointer is 0." )do { if (true && (!(pNewColl))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1229" ": "), "%s", "Collectionpointer is 0."); } } while
(false)
;
1230 SwFormatColl *pOldColl = GetFormatColl();
1231
1232 if( pNewColl != pOldColl )
1233 {
1234 pNewColl->Add( this );
1235
1236 // Set the Parent of out AutoAttributes to the new Collection
1237 if( GetpSwAttrSet() )
1238 AttrSetHandleHelper::SetParent( mpAttrSet, *this, pNewColl, pNewColl );
1239
1240 SetCondFormatColl( nullptr );
1241
1242 if( !IsModifyLocked() )
1243 {
1244 SwFormatChg aTmp1( pOldColl );
1245 SwFormatChg aTmp2( pNewColl );
1246 SwClientNotify( *this, sw::LegacyModifyHint(&aTmp1, &aTmp2) );
1247 }
1248 }
1249 if ( IsInCache() )
1250 {
1251 SwFrame::GetCache().Delete( this );
1252 SetInCache( false );
1253 }
1254 return pOldColl;
1255}
1256
1257bool SwContentNode::GoNext(SwIndex * pIdx, sal_uInt16 nMode ) const
1258{
1259 bool bRet = true;
1260 if( pIdx->GetIndex() < Len() )
1261 {
1262 if( !IsTextNode() )
1263 ++(*pIdx);
1264 else
1265 {
1266 const SwTextNode& rTNd = *GetTextNode();
1267 sal_Int32 nPos = pIdx->GetIndex();
1268 assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is())(static_cast <bool> (g_pBreakIt && g_pBreakIt->
GetBreakIter().is()) ? void (0) : __assert_fail ("g_pBreakIt && g_pBreakIt->GetBreakIter().is()"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1268, __extension__ __PRETTY_FUNCTION__))
;
1269 sal_Int32 nDone = 0;
1270 sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
1271 CharacterIteratorMode::SKIPCELL :
1272 CharacterIteratorMode::SKIPCONTROLCHARACTER;
1273 nPos = g_pBreakIt->GetBreakIter()->nextCharacters( rTNd.GetText(), nPos,
1274 g_pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
1275 nItrMode, 1, nDone );
1276
1277 // Check if nPos is inside hidden text range:
1278 if ( CRSR_SKIP_HIDDEN & nMode )
1279 {
1280 sal_Int32 nHiddenStart;
1281 sal_Int32 nHiddenEnd;
1282 SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
1283 if ( nHiddenStart != COMPLETE_STRING && nHiddenStart != nPos )
1284 nPos = nHiddenEnd;
1285 }
1286
1287 if( 1 == nDone )
1288 *pIdx = nPos;
1289 else
1290 bRet = false;
1291 }
1292 }
1293 else
1294 bRet = false;
1295 return bRet;
1296}
1297
1298bool SwContentNode::GoPrevious(SwIndex * pIdx, sal_uInt16 nMode ) const
1299{
1300 bool bRet = true;
1301 if( pIdx->GetIndex() > 0 )
1302 {
1303 if( !IsTextNode() )
1304 --(*pIdx);
1305 else
1306 {
1307 const SwTextNode& rTNd = *GetTextNode();
1308 sal_Int32 nPos = pIdx->GetIndex();
1309 assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is())(static_cast <bool> (g_pBreakIt && g_pBreakIt->
GetBreakIter().is()) ? void (0) : __assert_fail ("g_pBreakIt && g_pBreakIt->GetBreakIter().is()"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1309, __extension__ __PRETTY_FUNCTION__))
;
1310 sal_Int32 nDone = 0;
1311 sal_uInt16 nItrMode = ( CRSR_SKIP_CELLS & nMode ) ?
1312 CharacterIteratorMode::SKIPCELL :
1313 CharacterIteratorMode::SKIPCONTROLCHARACTER;
1314 nPos = g_pBreakIt->GetBreakIter()->previousCharacters( rTNd.GetText(), nPos,
1315 g_pBreakIt->GetLocale( rTNd.GetLang( nPos ) ),
1316 nItrMode, 1, nDone );
1317
1318 // Check if nPos is inside hidden text range:
1319 if ( CRSR_SKIP_HIDDEN & nMode )
1320 {
1321 sal_Int32 nHiddenStart;
1322 sal_Int32 nHiddenEnd;
1323 SwScriptInfo::GetBoundsOfHiddenRange( rTNd, nPos, nHiddenStart, nHiddenEnd );
1324 if ( nHiddenStart != COMPLETE_STRING )
1325 nPos = nHiddenStart;
1326 }
1327
1328 if( 1 == nDone )
1329 *pIdx = nPos;
1330 else
1331 bRet = false;
1332 }
1333 }
1334 else
1335 bRet = false;
1336 return bRet;
1337}
1338
1339/**
1340 * Creates all Views for the Doc for this Node.
1341 * The created ContentFrames are attached to the corresponding Layout.
1342 */
1343void SwContentNode::MakeFramesForAdjacentContentNode(SwContentNode& rNode)
1344{
1345 OSL_ENSURE( &rNode != this,do { if (true && (!(&rNode != this))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1346" ": "), "%s", "No ContentNode or CopyNode and new Node identical."
); } } while (false)
1346 "No ContentNode or CopyNode and new Node identical." )do { if (true && (!(&rNode != this))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1346" ": "), "%s", "No ContentNode or CopyNode and new Node identical."
); } } while (false)
;
1347
1348 if( !HasWriterListeners() || &rNode == this ) // Do we actually have Frames?
1349 return;
1350
1351 SwFrame *pFrame;
1352 SwLayoutFrame *pUpper;
1353 // Create Frames for Nodes which come after the Table?
1354 OSL_ENSURE( FindTableNode() == rNode.FindTableNode(), "Table confusion" )do { if (true && (!(FindTableNode() == rNode.FindTableNode
()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1354" ": "), "%s", "Table confusion"); } } while (false
)
;
1355
1356 SwNode2Layout aNode2Layout( *this, rNode.GetIndex() );
1357
1358 while( nullptr != (pUpper = aNode2Layout.UpperFrame( pFrame, rNode )) )
1359 {
1360 if (pUpper->getRootFrame()->IsHideRedlines()
1361 && !rNode.IsCreateFrameWhenHidingRedlines())
1362 {
1363 continue;
1364 }
1365 SwFrame *pNew = rNode.MakeFrame( pUpper );
1366 pNew->Paste( pUpper, pFrame );
1367 // #i27138#
1368 // notify accessibility paragraphs objects about changed
1369 // CONTENT_FLOWS_FROM/_TO relation.
1370 // Relation CONTENT_FLOWS_FROM for next paragraph will change
1371 // and relation CONTENT_FLOWS_TO for previous paragraph will change.
1372 if ( pNew->IsTextFrame() )
1373 {
1374 SwViewShell* pViewShell( pNew->getRootFrame()->GetCurrShell() );
1375 if ( pViewShell && pViewShell->GetLayout() &&
1376 pViewShell->GetLayout()->IsAnyShellAccessible() )
1377 {
1378 pViewShell->InvalidateAccessibleParaFlowRelation(
1379 dynamic_cast<SwTextFrame*>(pNew->FindNextCnt( true )),
1380 dynamic_cast<SwTextFrame*>(pNew->FindPrevCnt()) );
1381 }
1382 }
1383 }
1384}
1385
1386/**
1387 * Deletes all Views from the Doc for this Node.
1388 * The ContentFrames are removed from the corresponding Layout.
1389 */
1390void SwContentNode::DelFrames(SwRootFrame const*const pLayout)
1391{
1392 if( !HasWriterListeners() )
1393 return;
1394
1395 SwIterator<SwContentFrame, SwContentNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
1396 for( SwContentFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
1397 {
1398 if (pLayout && pLayout != pFrame->getRootFrame())
1399 {
1400 continue; // skip it
1401 }
1402 if (pFrame->IsTextFrame())
1403 {
1404 if (sw::MergedPara * pMerged =
1405 static_cast<SwTextFrame *>(pFrame)->GetMergedPara())
1406 {
1407 if (this != pMerged->pFirstNode)
1408 {
1409 // SwNodes::RemoveNode iterates *backwards* - so
1410 // ensure there are no more extents pointing to this
1411 // node as SwFrame::InvalidatePage() will access them.
1412 // Note: cannot send via SwClientNotify from dtor
1413 // because that would access deleted wrong-lists
1414 sw::UpdateMergedParaForDelete(*pMerged, true,
1415 *static_cast<SwTextNode*>(this), 0, Len());
1416 if (this == pMerged->pParaPropsNode)
1417 {
1418 // otherwise pointer should have been updated to a different node
1419 assert(this == pMerged->pLastNode)(static_cast <bool> (this == pMerged->pLastNode) ? void
(0) : __assert_fail ("this == pMerged->pLastNode", "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1419, __extension__ __PRETTY_FUNCTION__))
;
1420 assert(pMerged->extents.empty())(static_cast <bool> (pMerged->extents.empty()) ? void
(0) : __assert_fail ("pMerged->extents.empty()", "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1420, __extension__ __PRETTY_FUNCTION__))
;
1421 for (sal_uLong i = pMerged->pLastNode->GetIndex() - 1;;
1422 --i)
1423 {
1424 assert(pMerged->pFirstNode->GetIndex() <= i)(static_cast <bool> (pMerged->pFirstNode->GetIndex
() <= i) ? void (0) : __assert_fail ("pMerged->pFirstNode->GetIndex() <= i"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1424, __extension__ __PRETTY_FUNCTION__))
;
1425 SwNode *const pNode(GetNodes()[i]);
1426 if (pNode->IsTextNode()
1427 && pNode->GetRedlineMergeFlag() != Merge::Hidden)
1428 {
1429 pMerged->pParaPropsNode = pNode->GetTextNode();
1430 break;
1431 }
1432 }
1433 assert(pMerged->listener.IsListeningTo(pMerged->pParaPropsNode))(static_cast <bool> (pMerged->listener.IsListeningTo
(pMerged->pParaPropsNode)) ? void (0) : __assert_fail ("pMerged->listener.IsListeningTo(pMerged->pParaPropsNode)"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1433, __extension__ __PRETTY_FUNCTION__))
;
1434 }
1435 assert(GetIndex() <= pMerged->pLastNode->GetIndex())(static_cast <bool> (GetIndex() <= pMerged->pLastNode
->GetIndex()) ? void (0) : __assert_fail ("GetIndex() <= pMerged->pLastNode->GetIndex()"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1435, __extension__ __PRETTY_FUNCTION__))
;
1436 if (this == pMerged->pLastNode)
1437 {
1438 // tdf#130680 find the previous node that is a
1439 // listener of pMerged; see CheckParaRedlineMerge()
1440 for (sal_uLong i = GetIndex() - 1;
1441 this == pMerged->pLastNode; --i)
1442 {
1443 SwNode *const pNode = GetNodes()[i];
1444 if (pNode->IsTextNode())
1445 {
1446 pMerged->pLastNode = pNode->GetTextNode();
1447 }
1448 else if (SwEndNode const*const pEnd = pNode->GetEndNode())
1449 {
1450 SwStartNode const*const pStart(pEnd->StartOfSectionNode());
1451 i = pStart->GetIndex(); // skip table or section
1452 }
1453 }
1454 assert(pMerged->pFirstNode->GetIndex() <= pMerged->pLastNode->GetIndex())(static_cast <bool> (pMerged->pFirstNode->GetIndex
() <= pMerged->pLastNode->GetIndex()) ? void (0) : __assert_fail
("pMerged->pFirstNode->GetIndex() <= pMerged->pLastNode->GetIndex()"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1454, __extension__ __PRETTY_FUNCTION__))
;
1455 assert(pMerged->listener.IsListeningTo(pMerged->pLastNode))(static_cast <bool> (pMerged->listener.IsListeningTo
(pMerged->pLastNode)) ? void (0) : __assert_fail ("pMerged->listener.IsListeningTo(pMerged->pLastNode)"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 1455, __extension__ __PRETTY_FUNCTION__))
;
1456 }
1457 // avoid re-parenting mess (ModifyChangedHint)
1458 pMerged->listener.EndListening(this);
1459 continue; // don't delete
1460 }
1461 }
1462 // #i27138#
1463 // notify accessibility paragraphs objects about changed
1464 // CONTENT_FLOWS_FROM/_TO relation.
1465 // Relation CONTENT_FLOWS_FROM for current next paragraph will change
1466 // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
1467 SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() );
1468 if ( pViewShell && pViewShell->GetLayout() &&
1469 pViewShell->GetLayout()->IsAnyShellAccessible() )
1470 {
1471 pViewShell->InvalidateAccessibleParaFlowRelation(
1472 dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )),
1473 dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) );
1474 }
1475 }
1476
1477 if( pFrame->IsFollow() )
1478 {
1479 SwContentFrame* pMaster = pFrame->FindMaster();
1480 pMaster->SetFollow( pFrame->GetFollow() );
1481 }
1482 pFrame->SetFollow( nullptr );//So it doesn't get funny ideas.
1483 //Otherwise it could be possible that a follow
1484 //gets destroyed before its master. Following
1485 //the now invalid pointer will then lead to an
1486 //illegal memory access. The chain can be
1487 //crushed here because we'll destroy all of it
1488 //anyway.
1489
1490 if( pFrame->GetUpper() && pFrame->IsInFootnote() && !pFrame->GetIndNext() &&
1491 !pFrame->GetIndPrev() )
1492 {
1493 SwFootnoteFrame *pFootnote = pFrame->FindFootnoteFrame();
1494 OSL_ENSURE( pFootnote, "You promised a FootnoteFrame?" )do { if (true && (!(pFootnote))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1494" ": "), "%s", "You promised a FootnoteFrame?"); } }
while (false)
;
1495 SwContentFrame* pCFrame;
1496 if( !pFootnote->GetFollow() && !pFootnote->GetMaster() &&
1497 nullptr != ( pCFrame = pFootnote->GetRefFromAttr()) && pCFrame->IsFollow() )
1498 {
1499 OSL_ENSURE( pCFrame->IsTextFrame(), "NoTextFrame has Footnote?" )do { if (true && (!(pCFrame->IsTextFrame()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1499" ": "), "%s", "NoTextFrame has Footnote?"); } } while
(false)
;
1500 pCFrame->FindMaster()->Prepare( PrepareHint::FootnoteInvalidationGone );
1501 }
1502 }
1503 pFrame->Cut();
1504 SwFrame::DestroyFrame(pFrame);
1505 }
1506}
1507
1508SwContentNode *SwContentNode::JoinNext()
1509{
1510 return this;
1511}
1512
1513/// Get info from Modify
1514bool SwContentNode::GetInfo( SfxPoolItem& rInfo ) const
1515{
1516 switch( rInfo.Which() )
1517 {
1518 case RES_AUTOFMT_DOCNODE:
1519 if( &GetNodes() == static_cast<SwAutoFormatGetDocNode&>(rInfo).pNodes )
1520 {
1521 return false;
1522 }
1523 break;
1524
1525 case RES_FINDNEARESTNODE:
1526 if( static_cast<const SwFormatPageDesc&>(GetAttr( RES_PAGEDESC )).GetPageDesc() )
1527 static_cast<SwFindNearestNode&>(rInfo).CheckNode( *this );
1528 return true;
1529
1530 case RES_CONTENT_VISIBLE:
1531 {
1532 static_cast<SwPtrMsgPoolItem&>(rInfo).pObject =
1533 SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*this).First();
1534 }
1535 return false;
1536 }
1537
1538 return SwModify::GetInfo( rInfo );
1539}
1540
1541/// @param rAttr the attribute to set
1542bool SwContentNode::SetAttr(const SfxPoolItem& rAttr )
1543{
1544 if( !GetpSwAttrSet() ) // Have the Nodes created by the corresponding AttrSets
1545 NewAttrSet( GetDoc().GetAttrPool() );
1546
1547 OSL_ENSURE( GetpSwAttrSet(), "Why did't we create an AttrSet?")do { if (true && (!(GetpSwAttrSet()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1547" ": "), "%s", "Why did't we create an AttrSet?"); }
} while (false)
;
1548
1549 if ( IsInCache() )
1550 {
1551 SwFrame::GetCache().Delete( this );
1552 SetInCache( false );
1553 }
1554
1555 bool bRet = false;
1556 // If Modify is locked, we do not send any Modifys
1557 if( IsModifyLocked() ||
1558 ( !HasWriterListeners() && RES_PARATR_NUMRULE != rAttr.Which() ))
1559 {
1560 bRet = nullptr != AttrSetHandleHelper::Put( mpAttrSet, *this, rAttr );
1561 }
1562 else
1563 {
1564 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1565 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1566 bRet = AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rAttr, &aOld, &aNew );
1567 if( bRet )
1568 {
1569 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1570 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1571 ModifyNotification( &aChgOld, &aChgNew ); // Send all changed ones
1572 }
1573 }
1574 return bRet;
1575}
1576
1577bool SwContentNode::SetAttr( const SfxItemSet& rSet )
1578{
1579 if ( IsInCache() )
1580 {
1581 SwFrame::GetCache().Delete( this );
1582 SetInCache( false );
1583 }
1584
1585 const SfxPoolItem* pFnd = nullptr;
1586 if( SfxItemState::SET == rSet.GetItemState( RES_AUTO_STYLE, false, &pFnd ) )
1587 {
1588 OSL_ENSURE( rSet.Count() == 1, "SetAutoStyle mixed with other attributes?!" )do { if (true && (!(rSet.Count() == 1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1588" ": "), "%s", "SetAutoStyle mixed with other attributes?!"
); } } while (false)
;
1589 const SwFormatAutoFormat* pTmp = static_cast<const SwFormatAutoFormat*>(pFnd);
1590
1591 // If there already is an attribute set (usually containing a numbering
1592 // item), we have to merge the attribute of the new set into the old set:
1593 bool bSetParent = true;
1594 if ( GetpSwAttrSet() )
1595 {
1596 bSetParent = false;
1597 AttrSetHandleHelper::Put( mpAttrSet, *this, *pTmp->GetStyleHandle() );
1598 }
1599 else
1600 {
1601 mpAttrSet = pTmp->GetStyleHandle();
1602 }
1603
1604 if ( bSetParent )
1605 {
1606 // If the content node has a conditional style, we have to set the
1607 // string item containing the correct conditional style name (the
1608 // style name property has already been set during the import!)
1609 // In case we do not have a conditional style, we make use of the
1610 // fact that nobody else uses the attribute set behind the handle.
1611 // FME 2007-07-10 #i78124# If autostyle does not have a parent,
1612 // the string is empty.
1613 const SfxPoolItem* pNameItem = nullptr;
1614 if ( nullptr != GetCondFormatColl() ||
1615 SfxItemState::SET != mpAttrSet->GetItemState( RES_FRMATR_STYLE_NAME, false, &pNameItem ) ||
1616 static_cast<const SfxStringItem*>(pNameItem)->GetValue().isEmpty() )
1617 AttrSetHandleHelper::SetParent( mpAttrSet, *this, &GetAnyFormatColl(), GetFormatColl() );
1618 else
1619 const_cast<SfxItemSet*>(mpAttrSet.get())->SetParent( &GetFormatColl()->GetAttrSet() );
1620 }
1621
1622 return true;
1623 }
1624
1625 if( !GetpSwAttrSet() ) // Have the AttrsSets created by the corresponding Nodes
1626 NewAttrSet( GetDoc().GetAttrPool() );
1627
1628 bool bRet = false;
1629 // If Modify is locked, do not send any Modifys
1630 if ( IsModifyLocked() ||
1631 ( !HasWriterListeners() &&
1632 SfxItemState::SET != rSet.GetItemState( RES_PARATR_NUMRULE, false ) ) )
1633 {
1634 // Some special treatment for Attributes
1635 bRet = AttrSetHandleHelper::Put( mpAttrSet, *this, rSet );
1636 }
1637 else
1638 {
1639 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1640 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1641 bRet = AttrSetHandleHelper::Put_BC( mpAttrSet, *this, rSet, &aOld, &aNew );
1642 if( bRet )
1643 {
1644 // Some special treatment for Attributes
1645 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1646 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1647 ModifyNotification( &aChgOld, &aChgNew ); // Send out all changed ones
1648 }
1649 }
1650 return bRet;
1651}
1652
1653// With nWhich it takes the Hint from the Delta array
1654bool SwContentNode::ResetAttr( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
1655{
1656 if( !GetpSwAttrSet() )
1657 return false;
1658
1659 if ( IsInCache() )
1660 {
1661 SwFrame::GetCache().Delete( this );
1662 SetInCache( false );
1663 }
1664
1665 // If Modify is locked, do not send out any Modifys
1666 if( IsModifyLocked() )
1667 {
1668 sal_uInt16 nDel = 0;
1669 if ( !nWhich2 || nWhich2 < nWhich1 )
1670 {
1671 std::vector<sal_uInt16> aClearWhichIds;
1672 aClearWhichIds.push_back( nWhich1 );
1673 nDel = ClearItemsFromAttrSet( aClearWhichIds );
1674 }
1675 else
1676 nDel = AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, nullptr, nullptr );
1677
1678 if( !GetpSwAttrSet()->Count() ) // Empty? Delete
1679 mpAttrSet.reset();
1680 return 0 != nDel;
1681 }
1682
1683 // No valid area defined?
1684 if( !nWhich2 || nWhich2 < nWhich1 )
1685 nWhich2 = nWhich1; // Then set only this Item to 1st Id
1686
1687 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1688 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1689 bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, nWhich1, nWhich2, &aOld, &aNew );
1690
1691 if( bRet )
1692 {
1693 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1694 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1695 ModifyNotification( &aChgOld, &aChgNew ); // All changed ones are sent
1696
1697 if( !GetpSwAttrSet()->Count() ) // Empty?, delete it
1698 mpAttrSet.reset();
1699 }
1700 return bRet;
1701}
1702
1703bool SwContentNode::ResetAttr( const std::vector<sal_uInt16>& rWhichArr )
1704{
1705 if( !GetpSwAttrSet() )
1706 return false;
1707
1708 if ( IsInCache() )
1709 {
1710 SwFrame::GetCache().Delete( this );
1711 SetInCache( false );
1712 }
1713
1714 // If Modify is locked, do not send out any Modifys
1715 sal_uInt16 nDel = 0;
1716 if( IsModifyLocked() )
1717 {
1718 nDel = ClearItemsFromAttrSet( rWhichArr );
1719 }
1720 else
1721 {
1722 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1723 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1724
1725 for ( const auto& rWhich : rWhichArr )
1726 if( AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, rWhich, &aOld, &aNew ))
1727 ++nDel;
1728
1729 if( nDel )
1730 {
1731 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1732 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1733 ModifyNotification( &aChgOld, &aChgNew ); // All changed ones are sent
1734 }
1735 }
1736 if( !GetpSwAttrSet()->Count() ) // Empty?, delete it
1737 mpAttrSet.reset();
1738 return 0 != nDel ;
1739}
1740
1741sal_uInt16 SwContentNode::ResetAllAttr()
1742{
1743 if( !GetpSwAttrSet() )
1744 return 0;
1745
1746 if ( IsInCache() )
1747 {
1748 SwFrame::GetCache().Delete( this );
1749 SetInCache( false );
1750 }
1751
1752 // If Modify is locked, do not send out any Modifys
1753 if( IsModifyLocked() )
1754 {
1755 std::vector<sal_uInt16> aClearWhichIds;
1756 aClearWhichIds.push_back(0);
1757 sal_uInt16 nDel = ClearItemsFromAttrSet( aClearWhichIds );
1758 if( !GetpSwAttrSet()->Count() ) // Empty? Delete
1759 mpAttrSet.reset();
1760 return nDel;
1761 }
1762
1763 SwAttrSet aOld( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() ),
1764 aNew( *GetpSwAttrSet()->GetPool(), GetpSwAttrSet()->GetRanges() );
1765 bool bRet = 0 != AttrSetHandleHelper::ClearItem_BC( mpAttrSet, *this, 0, &aOld, &aNew );
1766
1767 if( bRet )
1768 {
1769 SwAttrSetChg aChgOld( *GetpSwAttrSet(), aOld );
1770 SwAttrSetChg aChgNew( *GetpSwAttrSet(), aNew );
1771 ModifyNotification( &aChgOld, &aChgNew ); // All changed ones are sent
1772
1773 if( !GetpSwAttrSet()->Count() ) // Empty? Delete
1774 mpAttrSet.reset();
1775 }
1776 return aNew.Count();
1777}
1778
1779bool SwContentNode::GetAttr( SfxItemSet& rSet ) const
1780{
1781 if( rSet.Count() )
1782 rSet.ClearItem();
1783
1784 const SwAttrSet& rAttrSet = GetSwAttrSet();
1785 return rSet.Set( rAttrSet );
1786}
1787
1788sal_uInt16 SwContentNode::ClearItemsFromAttrSet( const std::vector<sal_uInt16>& rWhichIds )
1789{
1790 sal_uInt16 nRet = 0;
1791 if ( rWhichIds.empty() )
1792 return nRet;
1793
1794 OSL_ENSURE( GetpSwAttrSet(), "no item set" )do { if (true && (!(GetpSwAttrSet()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
":" "1794" ": "), "%s", "no item set"); } } while (false)
;
1795 SwAttrSet aNewAttrSet( *GetpSwAttrSet() );
1796 for ( const auto& rWhichId : rWhichIds )
1797 {
1798 nRet = nRet + aNewAttrSet.ClearItem( rWhichId );
1799 }
1800 if ( nRet )
1801 AttrSetHandleHelper::GetNewAutoStyle( mpAttrSet, *this, aNewAttrSet );
1802
1803 return nRet;
1804}
1805
1806const SfxPoolItem* SwContentNode::GetNoCondAttr( sal_uInt16 nWhich,
1807 bool bInParents ) const
1808{
1809 const SfxPoolItem* pFnd = nullptr;
1810 if( m_pCondColl && m_pCondColl->GetRegisteredIn() )
1811 {
1812 if( !GetpSwAttrSet() || ( SfxItemState::SET != GetpSwAttrSet()->GetItemState(
1813 nWhich, false, &pFnd ) && bInParents ))
1814 {
1815 (void)static_cast<const SwFormat*>(GetRegisteredIn())->GetItemState( nWhich, bInParents, &pFnd );
1816 }
1817 }
1818 // undo change of issue #i51029#
1819 // Note: <GetSwAttrSet()> returns <mpAttrSet>, if set, otherwise it returns
1820 // the attribute set of the paragraph style, which is valid for the
1821 // content node - see file <node.hxx>
1822 else
1823 {
1824 GetSwAttrSet().GetItemState( nWhich, bInParents, &pFnd );
1825 }
1826 return pFnd;
1827}
1828
1829static bool lcl_CheckMaxLength(SwNode const& rPrev, SwNode const& rNext)
1830{
1831 if (rPrev.GetNodeType() != rNext.GetNodeType())
1832 {
1833 return false;
1834 }
1835 if (!rPrev.IsTextNode())
1836 {
1837 return true;
1838 }
1839
1840 // Check if a node can contain the other (order is not significant)
1841 return rPrev.GetTextNode()->GetSpaceLeft() > rNext.GetTextNode()->Len();
1842}
1843
1844/// Can we join two Nodes?
1845/// We can return the 2nd position in pIdx.
1846bool SwContentNode::CanJoinNext( SwNodeIndex* pIdx ) const
1847{
1848 const SwNodes& rNds = GetNodes();
1849 SwNodeIndex aIdx( *this, 1 );
1850
1851 const SwNode* pNd = this;
1852 while( aIdx < rNds.Count()-1 &&
1853 (( pNd = &aIdx.GetNode())->IsSectionNode() ||
1854 ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
1855 ++aIdx;
1856
1857 if (rNds.Count()-1 == aIdx.GetIndex())
1858 return false;
1859 if (!lcl_CheckMaxLength(*this, *pNd))
1860 {
1861 return false;
1862 }
1863 if( pIdx )
1864 *pIdx = aIdx;
1865 return true;
1866}
1867
1868/// Can we join two Nodes?
1869/// We can return the 2nd position in pIdx.
1870bool SwContentNode::CanJoinPrev( SwNodeIndex* pIdx ) const
1871{
1872 SwNodeIndex aIdx( *this, -1 );
1873
1874 const SwNode* pNd = this;
1875 while( aIdx.GetIndex() &&
1876 (( pNd = &aIdx.GetNode())->IsSectionNode() ||
1877 ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
1878 --aIdx;
1879
1880 if (0 == aIdx.GetIndex())
1881 return false;
1882 if (!lcl_CheckMaxLength(*pNd, *this))
1883 {
1884 return false;
1885 }
1886 if( pIdx )
1887 *pIdx = aIdx;
1888 return true;
1889}
1890
1891void SwContentNode::SetCondFormatColl(SwFormatColl* pColl)
1892{
1893 if( !((!pColl && m_pCondColl) || ( pColl && !m_pCondColl ) ||
1894 ( pColl && pColl != m_pCondColl->GetRegisteredIn() )) )
1895 return;
1896
1897 SwFormatColl* pOldColl = GetCondFormatColl();
1898 m_aCondCollListener.EndListeningAll();
1899 if(pColl)
1900 m_aCondCollListener.StartListening(pColl);
1901 m_pCondColl = pColl;
1902 if(GetpSwAttrSet())
1903 AttrSetHandleHelper::SetParent(mpAttrSet, *this, &GetAnyFormatColl(), GetFormatColl());
1904
1905 if(!IsModifyLocked())
1906 {
1907 SwFormatChg aTmp1(pOldColl ? pOldColl : GetFormatColl());
1908 SwFormatChg aTmp2(pColl ? pColl : GetFormatColl());
1909 NotifyClients(&aTmp1, &aTmp2);
1910 }
1911 if(IsInCache())
1912 {
1913 SwFrame::GetCache().Delete(this);
1914 SetInCache(false);
1915 }
1916}
1917
1918bool SwContentNode::IsAnyCondition( SwCollCondition& rTmp ) const
1919{
1920 const SwNodes& rNds = GetNodes();
1921 {
1922 Master_CollCondition nCond = Master_CollCondition::NONE;
1923 const SwStartNode* pSttNd = StartOfSectionNode();
1924 while( pSttNd )
1925 {
1926 switch( pSttNd->GetNodeType() )
1927 {
1928 case SwNodeType::Table: nCond = Master_CollCondition::PARA_IN_TABLEBODY; break;
1929 case SwNodeType::Section: nCond = Master_CollCondition::PARA_IN_SECTION; break;
1930
1931 default:
1932 switch( pSttNd->GetStartNodeType() )
1933 {
1934 case SwTableBoxStartNode:
1935 {
1936 nCond = Master_CollCondition::PARA_IN_TABLEBODY;
1937 const SwTableNode* pTableNd = pSttNd->FindTableNode();
1938 const SwTableBox* pBox;
1939 if( pTableNd && nullptr != ( pBox = pTableNd->GetTable().
1940 GetTableBox(pSttNd->GetIndex()) ) &&
1941 pBox->IsInHeadline( &pTableNd->GetTable() ) )
1942 nCond = Master_CollCondition::PARA_IN_TABLEHEAD;
1943 }
1944 break;
1945 case SwFlyStartNode: nCond = Master_CollCondition::PARA_IN_FRAME; break;
1946 case SwFootnoteStartNode:
1947 {
1948 nCond = Master_CollCondition::PARA_IN_FOOTNOTE;
1949 const SwFootnoteIdxs& rFootnoteArr = rNds.GetDoc().GetFootnoteIdxs();
1950 const SwTextFootnote* pTextFootnote;
1951 const SwNode* pSrchNd = pSttNd;
1952
1953 for( size_t n = 0; n < rFootnoteArr.size(); ++n )
1954 if( nullptr != ( pTextFootnote = rFootnoteArr[ n ])->GetStartNode() &&
1955 pSrchNd == &pTextFootnote->GetStartNode()->GetNode() )
1956 {
1957 if( pTextFootnote->GetFootnote().IsEndNote() )
1958 nCond = Master_CollCondition::PARA_IN_ENDNOTE;
1959 break;
1960 }
1961 }
1962 break;
1963 case SwHeaderStartNode: nCond = Master_CollCondition::PARA_IN_HEADER; break;
1964 case SwFooterStartNode: nCond = Master_CollCondition::PARA_IN_FOOTER; break;
1965 case SwNormalStartNode: break;
1966 }
1967 }
1968
1969 if( nCond != Master_CollCondition::NONE )
1970 {
1971 rTmp.SetCondition( nCond, 0 );
1972 return true;
1973 }
1974 pSttNd = pSttNd->GetIndex()
1975 ? pSttNd->StartOfSectionNode()
1976 : nullptr;
1977 }
1978 }
1979
1980 {
1981 SwOutlineNodes::size_type nPos;
1982 const SwOutlineNodes& rOutlNds = rNds.GetOutLineNds();
1983 if( !rOutlNds.empty() )
1984 {
1985 if( !rOutlNds.Seek_Entry( const_cast<SwContentNode*>(this), &nPos ) && nPos )
1986 --nPos;
1987 if( nPos < rOutlNds.size() &&
1988 rOutlNds[ nPos ]->GetIndex() < GetIndex() )
1989 {
1990 SwTextNode* pOutlNd = rOutlNds[ nPos ]->GetTextNode();
1991
1992 if( pOutlNd->IsOutline())
1993 {
1994 rTmp.SetCondition( Master_CollCondition::PARA_IN_OUTLINE, pOutlNd->GetAttrOutlineLevel() - 1 );
1995 return true;
1996 }
1997 }
1998 }
1999 }
2000
2001 return false;
2002}
2003
2004void SwContentNode::ChkCondColl()
2005{
2006 // Check, just to be sure
2007 if( RES_CONDTXTFMTCOLL != GetFormatColl()->Which() )
2008 return;
2009
2010 SwCollCondition aTmp( nullptr, Master_CollCondition::NONE, 0 );
2011 const SwCollCondition* pCColl;
2012
2013 bool bDone = false;
2014
2015 if( IsAnyCondition( aTmp ))
2016 {
2017 pCColl = static_cast<SwConditionTextFormatColl*>(GetFormatColl())
2018 ->HasCondition( aTmp );
2019
2020 if (pCColl)
2021 {
2022 SetCondFormatColl( pCColl->GetTextFormatColl() );
2023 bDone = true;
2024 }
2025 }
2026
2027 if (bDone)
2028 return;
2029
2030 if( IsTextNode() && static_cast<SwTextNode*>(this)->GetNumRule())
2031 {
2032 // Is at which Level in a list?
2033 aTmp.SetCondition( Master_CollCondition::PARA_IN_LIST,
2034 static_cast<SwTextNode*>(this)->GetActualListLevel() );
2035 pCColl = static_cast<SwConditionTextFormatColl*>(GetFormatColl())->
2036 HasCondition( aTmp );
2037 }
2038 else
2039 pCColl = nullptr;
2040
2041 if( pCColl )
2042 SetCondFormatColl( pCColl->GetTextFormatColl() );
2043 else if( m_pCondColl )
2044 SetCondFormatColl( nullptr );
2045}
2046
2047// #i42921#
2048SvxFrameDirection SwContentNode::GetTextDirection( const SwPosition& rPos,
2049 const Point* pPt ) const
2050{
2051 SvxFrameDirection nRet = SvxFrameDirection::Unknown;
2052
2053 Point aPt;
2054 if( pPt )
2055 aPt = *pPt;
2056
2057 // #i72024# - No format of the frame, because this can cause recursive layout actions
2058 std::pair<Point, bool> const tmp(aPt, false);
2059 SwFrame* pFrame = getLayoutFrame(GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(), &rPos, &tmp);
2060
2061 if ( pFrame )
2062 {
2063 if ( pFrame->IsVertical() )
2064 {
2065 if (pFrame->IsVertLRBT())
2066 nRet = SvxFrameDirection::Vertical_LR_BT;
2067 else if (pFrame->IsRightToLeft())
2068 nRet = SvxFrameDirection::Vertical_LR_TB;
2069 else
2070 nRet = SvxFrameDirection::Vertical_RL_TB;
2071 }
2072 else
2073 {
2074 if ( pFrame->IsRightToLeft() )
2075 nRet = SvxFrameDirection::Horizontal_RL_TB;
2076 else
2077 nRet = SvxFrameDirection::Horizontal_LR_TB;
2078 }
2079 }
2080
2081 return nRet;
2082}
2083
2084std::unique_ptr<SwOLENodes> SwContentNode::CreateOLENodesArray( const SwFormatColl& rColl, bool bOnlyWithInvalidSize )
2085{
2086 std::unique_ptr<SwOLENodes> pNodes;
2087 SwIterator<SwContentNode,SwFormatColl> aIter( rColl );
2088 for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
2089 {
2090 SwOLENode *pONd = pNd->GetOLENode();
2091 if ( pONd && (!bOnlyWithInvalidSize || pONd->IsOLESizeInvalid()) )
2092 {
2093 if ( !pNodes )
2094 pNodes.reset(new SwOLENodes);
2095 pNodes->push_back( pONd );
2096 }
2097 }
2098
2099 return pNodes;
2100}
2101
2102drawinglayer::attribute::SdrAllFillAttributesHelperPtr SwContentNode::getSdrAllFillAttributesHelper() const
2103{
2104 return drawinglayer::attribute::SdrAllFillAttributesHelperPtr();
2105}
2106
2107/*
2108 * Document Interface Access
2109 */
2110const IDocumentSettingAccess* SwNode::getIDocumentSettingAccess() const { return &GetDoc().GetDocumentSettingManager(); }
2111const IDocumentDeviceAccess& SwNode::getIDocumentDeviceAccess() const { return GetDoc().getIDocumentDeviceAccess(); }
2112const IDocumentRedlineAccess& SwNode::getIDocumentRedlineAccess() const { return GetDoc().getIDocumentRedlineAccess(); }
2113const IDocumentStylePoolAccess& SwNode::getIDocumentStylePoolAccess() const { return GetDoc().getIDocumentStylePoolAccess(); }
2114const IDocumentDrawModelAccess& SwNode::getIDocumentDrawModelAccess() const { return GetDoc().getIDocumentDrawModelAccess(); }
2115const IDocumentLayoutAccess& SwNode::getIDocumentLayoutAccess() const { return GetDoc().getIDocumentLayoutAccess(); }
2116IDocumentLayoutAccess& SwNode::getIDocumentLayoutAccess() { return GetDoc().getIDocumentLayoutAccess(); }
2117const IDocumentLinksAdministration& SwNode::getIDocumentLinksAdministration() const { return GetDoc().getIDocumentLinksAdministration(); }
2118IDocumentLinksAdministration& SwNode::getIDocumentLinksAdministration() { return GetDoc().getIDocumentLinksAdministration(); }
2119const IDocumentFieldsAccess& SwNode::getIDocumentFieldsAccess() const { return GetDoc().getIDocumentFieldsAccess(); }
2120IDocumentFieldsAccess& SwNode::getIDocumentFieldsAccess() { return GetDoc().getIDocumentFieldsAccess(); }
2121IDocumentContentOperations& SwNode::getIDocumentContentOperations() { return GetDoc().getIDocumentContentOperations(); }
2122IDocumentListItems& SwNode::getIDocumentListItems() { return GetDoc().getIDocumentListItems(); } // #i83479#
2123
2124const IDocumentMarkAccess* SwNode::getIDocumentMarkAccess() const { return GetDoc().getIDocumentMarkAccess(); }
2125IStyleAccess& SwNode::getIDocumentStyleAccess() { return GetDoc().GetIStyleAccess(); }
2126
2127bool SwNode::IsInRedlines() const
2128{
2129 const SwDoc& rDoc = GetDoc();
2130
2131 return rDoc.getIDocumentRedlineAccess().IsInRedlines(*this);
2132}
2133
2134void SwNode::AddAnchoredFly(SwFrameFormat *const pFlyFormat)
2135{
2136 assert(pFlyFormat)(static_cast <bool> (pFlyFormat) ? void (0) : __assert_fail
("pFlyFormat", "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 2136, __extension__ __PRETTY_FUNCTION__))
;
2137 assert(&pFlyFormat->GetAnchor(false).GetContentAnchor()->nNode.GetNode() == this)(static_cast <bool> (&pFlyFormat->GetAnchor(false
).GetContentAnchor()->nNode.GetNode() == this) ? void (0) :
__assert_fail ("&pFlyFormat->GetAnchor(false).GetContentAnchor()->nNode.GetNode() == this"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 2137, __extension__ __PRETTY_FUNCTION__))
;
2138 // check node type, cf. SwFormatAnchor::SetAnchor()
2139 assert(IsTextNode() || IsStartNode() || IsTableNode())(static_cast <bool> (IsTextNode() || IsStartNode() || IsTableNode
()) ? void (0) : __assert_fail ("IsTextNode() || IsStartNode() || IsTableNode()"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 2139, __extension__ __PRETTY_FUNCTION__))
;
2140 if (!m_pAnchoredFlys)
2141 {
2142 m_pAnchoredFlys.reset(new std::vector<SwFrameFormat*>);
2143 }
2144 m_pAnchoredFlys->push_back(pFlyFormat);
2145}
2146
2147void SwNode::RemoveAnchoredFly(SwFrameFormat *const pFlyFormat)
2148{
2149 assert(pFlyFormat)(static_cast <bool> (pFlyFormat) ? void (0) : __assert_fail
("pFlyFormat", "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 2149, __extension__ __PRETTY_FUNCTION__))
;
2150 // cannot assert this in Remove because it is called when new anchor is already set
2151// assert(&pFlyFormat->GetAnchor(false).GetContentAnchor()->nNode.GetNode() == this);
2152 assert(IsTextNode() || IsStartNode() || IsTableNode())(static_cast <bool> (IsTextNode() || IsStartNode() || IsTableNode
()) ? void (0) : __assert_fail ("IsTextNode() || IsStartNode() || IsTableNode()"
, "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 2152, __extension__ __PRETTY_FUNCTION__))
;
2153 assert(m_pAnchoredFlys)(static_cast <bool> (m_pAnchoredFlys) ? void (0) : __assert_fail
("m_pAnchoredFlys", "/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 2153, __extension__ __PRETTY_FUNCTION__))
;
2154 auto it(std::find(m_pAnchoredFlys->begin(), m_pAnchoredFlys->end(), pFlyFormat));
2155 assert(it != m_pAnchoredFlys->end())(static_cast <bool> (it != m_pAnchoredFlys->end()) ?
void (0) : __assert_fail ("it != m_pAnchoredFlys->end()",
"/home/maarten/src/libreoffice/core/sw/source/core/docnode/node.cxx"
, 2155, __extension__ __PRETTY_FUNCTION__))
;
2156 m_pAnchoredFlys->erase(it);
2157 if (m_pAnchoredFlys->empty())
2158 {
2159 m_pAnchoredFlys.reset();
2160 }
2161}
2162
2163/* vim:set shiftwidth=4 softtabstop=4 expandtab: */