LibreOffice Module sw (master) 1
nodes.cxx
Go to the documentation of this file.
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 <stdlib.h>
21
22#include <libxml/xmlwriter.h>
23#include <osl/diagnose.h>
24
25#include <node.hxx>
26#include <doc.hxx>
27#include <IDocumentUndoRedo.hxx>
30#include <pam.hxx>
31#include <txtfld.hxx>
32#include <fmtfld.hxx>
33#include <numrule.hxx>
34#include <ndtxt.hxx>
35#include <ndnotxt.hxx>
36#include <swtable.hxx>
37#include <section.hxx>
38#include <ddefld.hxx>
39#include <swddetbl.hxx>
40#include <txtatr.hxx>
41#include <tox.hxx>
42#include <fmtrfmrk.hxx>
43#include <fmtftn.hxx>
44
45#include <docsh.hxx>
46#include <rootfrm.hxx>
47#include <txtfrm.hxx>
48
49typedef std::vector<SwStartNode*> SwStartNodePointers;
50
51// function to determine the highest level in the given range
52static sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange );
53
61 : m_vIndices(nullptr), m_rMyDoc( rDocument )
62{
64
66 SwStartNode* pSttNd = new SwStartNode( *this, nPos++ );
67 m_pEndOfPostIts = new SwEndNode( *this, nPos++, *pSttNd );
68
69 SwStartNode* pTmp = new SwStartNode( *this, nPos++ );
70 m_pEndOfInserts = new SwEndNode( *this, nPos++, *pTmp );
71
72 pTmp = new SwStartNode( *this, nPos++ );
73 pTmp->m_pStartOfSection = pSttNd;
74 m_pEndOfAutotext = new SwEndNode( *this, nPos++, *pTmp );
75
76 pTmp = new SwStartNode( *this, nPos++ );
77 pTmp->m_pStartOfSection = pSttNd;
78 m_pEndOfRedlines = new SwEndNode( *this, nPos++, *pTmp );
79
80 pTmp = new SwStartNode( *this, nPos++ );
81 pTmp->m_pStartOfSection = pSttNd;
82 m_pEndOfContent.reset(new SwEndNode( *this, nPos++, *pTmp ));
83
85}
86
94{
95 m_pOutlineNodes.reset();
96
97 {
98 SwNodeIndex aNdIdx( *this );
99 while( true )
100 {
101 SwNode *pNode = &aNdIdx.GetNode();
102 if( pNode == m_pEndOfContent.get() )
103 break;
104
105 ++aNdIdx;
106 delete pNode;
107 }
108 }
109
110 // here, all SwNodeIndices must be unregistered
111 m_pEndOfContent.reset();
112}
113
114static bool IsInsertOutline(SwNodes const& rNodes, SwNodeOffset const nIndex)
115{
116 if (!rNodes.IsDocNodes())
117 {
118 return false;
119 }
121 || rNodes.GetEndOfRedlines().GetIndex() < nIndex;
122}
123
124void SwNodes::ChgNode( SwNodeIndex const & rDelPos, SwNodeOffset nSz,
125 SwNodeIndex& rInsPos, bool bNewFrames )
126{
127 // no need for frames in the UndoArea
128 SwNodes& rNds = rInsPos.GetNodes();
129 const SwNode* pPrevInsNd = rNds[ rInsPos.GetIndex() -SwNodeOffset(1) ];
130
131 // declare all fields as invalid, updating will happen
132 // in the idle-handler of the doc
133 if( GetDoc().getIDocumentFieldsAccess().SetFieldsDirty( true, &rDelPos.GetNode(), nSz ) &&
134 &rNds.GetDoc() != &GetDoc() )
135 rNds.GetDoc().getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, SwNodeOffset(0) );
136
137 // NEVER include nodes from the RedLineArea
138 SwNodeOffset nNd = rInsPos.GetIndex();
139 bool const bInsOutlineIdx = IsInsertOutline(rNds, nNd);
140
141 if( &rNds == this ) // if in the same node array -> move
142 {
143 // Move order: from front to back, so that new entries are added at
144 // first position, thus, deletion position stays the same
145 const SwNodeOffset nDiff(rDelPos.GetIndex() < rInsPos.GetIndex() ? 0 : 1);
146
147 for( SwNodeOffset n = rDelPos.GetIndex(); nSz; n += nDiff, --nSz )
148 {
149 SwNodeIndex aDelIdx( *this, n );
150 SwNode& rNd = aDelIdx.GetNode();
151
152 // #i57920# - correction of refactoring done by cws swnumtree:
153 // - <SwTextNode::SetLevel( NO_NUMBERING ) is deprecated and
154 // set <IsCounted> state of the text node to <false>, which
155 // isn't correct here.
156 if ( rNd.IsTextNode() )
157 {
158 SwTextNode* pTextNode = rNd.GetTextNode();
159
160 pTextNode->RemoveFromList();
161
162 if (pTextNode->IsOutline())
163 {
164 SwNode* pSrch = &rNd;
165 m_pOutlineNodes->erase( pSrch );
166 }
167 }
168
169 BigPtrArray::Move( sal_Int32(aDelIdx.GetIndex()), sal_Int32(rInsPos.GetIndex()) );
170
171 if( rNd.IsTextNode() )
172 {
173 SwTextNode& rTextNd = static_cast<SwTextNode&>(rNd);
174
175 rTextNd.AddToList();
176
177 if (bInsOutlineIdx && rTextNd.IsOutline())
178 {
179 SwNode* pSrch = &rNd;
180 m_pOutlineNodes->insert( pSrch );
181 }
182 rTextNd.InvalidateNumRule();
183
184//FEATURE::CONDCOLL
185 if( RES_CONDTXTFMTCOLL == rTextNd.GetTextColl()->Which() )
186 rTextNd.ChkCondColl();
187//FEATURE::CONDCOLL
188 }
189 else if( rNd.IsContentNode() )
190 static_cast<SwContentNode&>(rNd).InvalidateNumRule();
191 }
192 }
193 else
194 {
195 bool bSavePersData(GetDoc().GetIDocumentUndoRedo().IsUndoNodes(rNds));
196 bool bRestPersData(GetDoc().GetIDocumentUndoRedo().IsUndoNodes(*this));
197 SwDoc* pDestDoc = &rNds.GetDoc() != &GetDoc() ? &rNds.GetDoc() : nullptr;
198 OSL_ENSURE(!pDestDoc, "SwNodes::ChgNode(): "
199 "the code to handle text fields here looks broken\n"
200 "if the target is in a different document.");
201 if( !bRestPersData && !bSavePersData && pDestDoc )
202 bSavePersData = bRestPersData = true;
203
204 OUString sNumRule;
205 for( SwNodeOffset n(0); n < nSz; n++ )
206 {
207 SwNode* pNd = &rDelPos.GetNode();
208
209 // NoTextNode keep their persistent data
210 if( pNd->IsNoTextNode() )
211 {
212 if( bSavePersData )
213 static_cast<SwNoTextNode*>(pNd)->SavePersistentData();
214 }
215 else if( pNd->IsTextNode() )
216 {
217 SwTextNode* pTextNd = static_cast<SwTextNode*>(pNd);
218
219 // remove outline index from old nodes array
220 if (pTextNd->IsOutline())
221 {
222 m_pOutlineNodes->erase( pNd );
223 }
224
225 // copy rules if needed
226 if( pDestDoc )
227 {
228 const SwNumRule* pNumRule = pTextNd->GetNumRule();
229 if( pNumRule && sNumRule != pNumRule->GetName() )
230 {
231 sNumRule = pNumRule->GetName();
232 SwNumRule* pDestRule = pDestDoc->FindNumRulePtr( sNumRule );
233 if( pDestRule )
234 pDestRule->SetInvalidRule( true );
235 else
236 pDestDoc->MakeNumRule( sNumRule, pNumRule );
237 }
238 }
239 else
240 {
241 // if movement into the UndoNodes-array, update numbering
243 {
244 pTextNd->InvalidateNumRule();
245 }
246 }
247
248 pTextNd->RemoveFromList();
249 }
250
251 RemoveNode( rDelPos.GetIndex(), SwNodeOffset(1), false ); // move indices
252 SwContentNode * pCNd = pNd->GetContentNode();
253 rNds.InsertNode( pNd, rInsPos );
254
255 if( pCNd )
256 {
257 SwTextNode* pTextNd = pCNd->GetTextNode();
258 if( pTextNd )
259 {
260 SwpHints * const pHts = pTextNd->GetpSwpHints();
261 // OutlineNodes set the new nodes in the array
262 if (bInsOutlineIdx && pTextNd->IsOutline())
263 {
264 rNds.m_pOutlineNodes->insert( pTextNd );
265 }
266
267 pTextNd->AddToList();
268
269 // special treatment for fields
270 if( pHts && pHts->Count() )
271 {
272 bool const bToUndo = !pDestDoc &&
274 for( size_t i = pHts->Count(); i; )
275 {
276 SwTextAttr * const pAttr = pHts->Get( --i );
277 switch ( pAttr->Which() )
278 {
279 case RES_TXTATR_FIELD:
282 {
283 SwTextField* pTextField = static_txtattr_cast<SwTextField*>(pAttr);
284 rNds.GetDoc().getIDocumentFieldsAccess().InsDelFieldInFieldLst( !bToUndo, *pTextField );
285
286 const SwFieldType* pTyp = pTextField->GetFormatField().GetField()->GetTyp();
287 if ( SwFieldIds::Postit == pTyp->Which() )
288 {
289 rNds.GetDoc().GetDocShell()->Broadcast(
291 &pTextField->GetFormatField(),
292 ( pTextField->GetFormatField().IsFieldInDoc()
295 }
296 else if( SwFieldIds::Dde == pTyp->Which() )
297 {
298 if( bToUndo )
299 const_cast<SwDDEFieldType*>(static_cast<const SwDDEFieldType*>(pTyp))->DecRefCnt();
300 else
301 const_cast<SwDDEFieldType*>(static_cast<const SwDDEFieldType*>(pTyp))->IncRefCnt();
302 }
303 static_cast<SwFormatField&>(pAttr->GetAttr())
304 .InvalidateField();
305 }
306 break;
307
308 case RES_TXTATR_FTN:
309 static_cast<SwFormatFootnote&>(pAttr->GetAttr())
310 .InvalidateFootnote();
311 break;
312
314 static_cast<SwTOXMark&>(pAttr->GetAttr())
315 .InvalidateTOXMark();
316 break;
317
319 static_cast<SwFormatRefMark&>(pAttr->GetAttr())
320 .InvalidateRefMark();
321 break;
322
323 case RES_TXTATR_META:
325 {
326 SwTextMeta *const pTextMeta(
327 static_txtattr_cast<SwTextMeta*>(pAttr));
328 // force removal of UNO object
329 pTextMeta->ChgTextNode(nullptr);
330 pTextMeta->ChgTextNode(pTextNd);
331 }
332 break;
333
334 default:
335 break;
336 }
337 }
338 }
339 //FEATURE::CONDCOLL
340 if( RES_CONDTXTFMTCOLL == pTextNd->GetTextColl()->Which() )
341 pTextNd->ChkCondColl();
342 //FEATURE::CONDCOLL
343 }
344 else
345 {
346 // Moved into different Docs? Persist data again!
347 if( pCNd->IsNoTextNode() && bRestPersData )
348 static_cast<SwNoTextNode*>(pCNd)->RestorePersistentData();
349 }
350 }
351 }
352 }
353
354 // declare all fields as invalid, updating will happen
355 // in the idle-handler of the doc
357 if( &rNds.GetDoc() != &GetDoc() )
358 rNds.GetDoc().getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, SwNodeOffset(0) );
359
360 if( bNewFrames )
361 bNewFrames = &GetDoc().GetNodes() == &rNds &&
363
364 if( !bNewFrames )
365 return;
366
367 // get the frames:
368 SwNodeIndex aIdx( *pPrevInsNd, 1 );
369 SwNodeIndex aFrameNdIdx( aIdx );
370 SwNode* pFrameNd = rNds.FindPrvNxtFrameNode( aFrameNdIdx,
371 rNds[ rInsPos.GetIndex() - 1 ] );
372
373 if( !pFrameNd )
374 return;
375
376 while( aIdx != rInsPos )
377 {
378 SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
379 if( pCNd )
380 {
381 if( pFrameNd->IsTableNode() )
382 static_cast<SwTableNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(aIdx);
383 else if( pFrameNd->IsSectionNode() )
384 static_cast<SwSectionNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(aIdx);
385 else
386 static_cast<SwContentNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(*pCNd);
387 pFrameNd = pCNd;
388 }
389 ++aIdx;
390 }
391}
392
393// TODO: provide documentation
409bool SwNodes::MoveNodes( const SwNodeRange& aRange, SwNodes & rNodes,
410 const SwNodeIndex& aIndex, bool bNewFrames )
411{
412 SwNode * pCurrentNode;
413 if( aIndex == SwNodeOffset(0) ||
414 ( (pCurrentNode = &aIndex.GetNode())->GetStartNode() &&
415 !pCurrentNode->StartOfSectionIndex() ))
416 return false;
417
418 SwNodeRange aRg( aRange );
419
420 // skip "simple" start or end nodes
421 while( SwNodeType::Start == (pCurrentNode = &aRg.aStart.GetNode())->GetNodeType()
422 || ( pCurrentNode->IsEndNode() &&
423 !pCurrentNode->m_pStartOfSection->IsSectionNode() ) )
424 ++aRg.aStart;
425 --aRg.aStart;
426
427 // if aEnd-1 points to no ContentNode, search previous one
428 --aRg.aEnd;
429 while( ( (( pCurrentNode = &aRg.aEnd.GetNode())->GetStartNode() &&
430 !pCurrentNode->IsSectionNode() ) ||
431 ( pCurrentNode->IsEndNode() &&
432 SwNodeType::Start == pCurrentNode->m_pStartOfSection->GetNodeType()) ) &&
433 aRg.aEnd > aRg.aStart )
434 --aRg.aEnd;
435
436 // if in same array, check insertion position
437 if( aRg.aStart >= aRg.aEnd )
438 return false;
439
440 if( this == &rNodes )
441 {
442 if( ( aIndex.GetIndex()-SwNodeOffset(1) >= aRg.aStart.GetIndex() &&
443 aIndex.GetIndex()-SwNodeOffset(1) < aRg.aEnd.GetIndex()) ||
444 ( aIndex.GetIndex()-SwNodeOffset(1) == aRg.aEnd.GetIndex() ) )
445 return false;
446 }
447
448 SwNodeOffset nInsPos(0); // counter for tmp array
449
450 // array as a stack, storing all StartOfSelections
451 SwStartNodePointers aSttNdStack;
452 SwStartNodePointers::size_type nLevel = 0; // level counter
453
454 // set start index
455 SwNodeIndex aIdx( aIndex );
456
457 SwStartNode* pStartNode = aIdx.GetNode().m_pStartOfSection;
458 aSttNdStack.insert( aSttNdStack.begin(), pStartNode );
459
460 SwNodeRange aOrigInsPos( aIdx, SwNodeOffset(-1), aIdx ); // original insertion position
461
462 // call DelFrames/MakeFrames for the upmost SectionNode
463 int nSectNdCnt = 0;
464 bool bSaveNewFrames = bNewFrames;
465
466 // continue until everything has been moved
467 while( aRg.aStart < aRg.aEnd )
468 {
469 pCurrentNode = &aRg.aEnd.GetNode();
470 switch( pCurrentNode->GetNodeType() )
471 {
472 case SwNodeType::End:
473 {
474 if( nInsPos ) // move everything until here
475 {
476 // delete and copy. CAUTION: all indices after
477 // "aRg.aEnd+1" will be moved as well!
478 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
479 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
480 aIdx -= nInsPos;
481 nInsPos = SwNodeOffset(0);
482 }
483
484 SwStartNode* pSttNd = pCurrentNode->m_pStartOfSection;
485 if( pSttNd->IsTableNode() )
486 {
487 SwTableNode* pTableNd = static_cast<SwTableNode*>(pSttNd);
488
489 // move the whole table/range
490 nInsPos = (aRg.aEnd.GetIndex() -
491 pSttNd->GetIndex() )+1;
492 aRg.aEnd -= nInsPos;
493
494 // NEVER include nodes from the RedLineArea
495 SwNodeOffset nNd = aIdx.GetIndex();
496 bool const bInsOutlineIdx = IsInsertOutline(rNodes, nNd);
497
498 if( bNewFrames )
499 // delete all frames
500 pTableNd->DelFrames(nullptr);
501 if( &rNodes == this ) // move into self?
502 {
503 // move all Start/End/ContentNodes
504 // ContentNodes: delete also the frames!
506 for( SwNodeOffset n(0); n < nInsPos; ++n )
507 {
508 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
509 SwContentNode* pCNd = nullptr;
510 SwNode* pTmpNd = &aMvIdx.GetNode();
511 if( pTmpNd->IsContentNode() )
512 {
513 pCNd = static_cast<SwContentNode*>(pTmpNd);
514 if( pTmpNd->IsTextNode() )
515 static_cast<SwTextNode*>(pTmpNd)->RemoveFromList();
516
517 // remove outline index from old nodes array
518 if (pCNd->IsTextNode() && pCNd->GetTextNode()->IsOutline())
519 {
520 m_pOutlineNodes->erase( pCNd );
521 }
522 else
523 pCNd = nullptr;
524 }
525
526 BigPtrArray::Move( sal_Int32(aMvIdx.GetIndex()), sal_Int32(aIdx.GetIndex()) );
527
528 if( bInsOutlineIdx && pCNd )
529 m_pOutlineNodes->insert( pCNd );
530 if( pTmpNd->IsTextNode() )
531 static_cast<SwTextNode*>(pTmpNd)->AddToList();
532 }
533 }
534 else
535 {
536 // get StartNode
537 // Even aIdx points to a startnode, we need the startnode
538 // of the environment of aIdx (#i80941)
539 SwStartNode* pSttNode = aIdx.GetNode().m_pStartOfSection;
540
541 // get all boxes with content because their indices
542 // pointing to the StartNodes need to be reset
543 // (copying the array and deleting all found ones eases
544 // searching)
545 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
546 for( SwNodeOffset n(0); n < nInsPos; ++n )
547 {
548 SwNode* pNd = &aMvIdx.GetNode();
549
550 const bool bOutlNd = pNd->IsTextNode() && pNd->GetTextNode()->IsOutline();
551 // delete outline indices from old node array
552 if( bOutlNd )
553 m_pOutlineNodes->erase( pNd );
554
555 RemoveNode( aMvIdx.GetIndex(), SwNodeOffset(1), false );
556 pNd->m_pStartOfSection = pSttNode;
557 rNodes.InsertNode( pNd, aIdx );
558
559 // set correct indices in Start/EndNodes
560 if( bInsOutlineIdx && bOutlNd )
561 // and put them into the new node array
562 rNodes.m_pOutlineNodes->insert( pNd );
563 else if( pNd->IsStartNode() )
564 pSttNode = static_cast<SwStartNode*>(pNd);
565 else if( pNd->IsEndNode() )
566 {
567 pSttNode->m_pEndOfSection = static_cast<SwEndNode*>(pNd);
568 if( pSttNode->IsSectionNode() )
569 static_cast<SwSectionNode*>(pSttNode)->NodesArrChgd();
570 pSttNode = pSttNode->m_pStartOfSection;
571 }
572 }
573
574 if( auto pDDETable = dynamic_cast<SwDDETable*>(&pTableNd->GetTable()) )
575 {
576 SwDDEFieldType* pTyp = pDDETable->GetDDEFieldType();
577 if( pTyp )
578 {
579 if( rNodes.IsDocNodes() )
580 pTyp->IncRefCnt();
581 else
582 pTyp->DecRefCnt();
583 }
584 }
585
587 {
588 SwFrameFormat* pTableFormat = pTableNd->GetTable().GetFrameFormat();
589 pTableFormat->GetNotifier().Broadcast(SfxHint(SfxHintId::Dying));
590 }
591 }
592 if( bNewFrames )
593 {
594 SwNodeIndex aTmp( aIdx );
595 pTableNd->MakeOwnFrames(&aTmp);
596 }
597 aIdx -= nInsPos;
598 nInsPos = SwNodeOffset(0);
599 }
600 else if( pSttNd->GetIndex() < aRg.aStart.GetIndex() )
601 {
602 // SectionNode: not the whole section will be moved, thus,
603 // move only the ContentNodes
604 // StartNode: create a new section at the given position
605 do { // middle check loop
606 if( !pSttNd->IsSectionNode() )
607 {
608 // create StartNode and EndNode at InsertPos
609 SwStartNode* pTmp = new SwStartNode( aIdx,
611/*?? NodeType ??*/ SwNormalStartNode );
612
613 nLevel++; // put the index to StartNode on the stack
614 aSttNdStack.insert( aSttNdStack.begin() + nLevel, pTmp );
615
616 // create EndNode
617 new SwEndNode( aIdx, *pTmp );
618 }
619 else if (GetDoc().GetIDocumentUndoRedo().IsUndoNodes(
620 rNodes))
621 {
622 // use placeholder in UndoNodes array
623 new SwPlaceholderNode(aIdx);
624 }
625 else
626 {
627 // JP 18.5.2001 (Bug 70454) creating new section?
628 --aRg.aEnd;
629 break;
630
631 }
632
633 --aRg.aEnd;
634 --aIdx;
635 } while( false );
636 }
637 else
638 {
639 // move StartNode and EndNode in total
640
641 // if Start is exactly the Start of the area,
642 // then the Node needs to be re-visited
643 if( &aRg.aStart.GetNode() == pSttNd )
644 --aRg.aStart;
645
646 SwSectionNode* pSctNd = pSttNd->GetSectionNode();
647 if( bNewFrames && pSctNd )
648 { // tdf#135056 skip over code in DelFrames() that moves
649 // SwNodeIndex around because in case of nested
650 // sections, m_pStartOfSection will point between
651 // undo nodes-array and doc nodes-array
652 pSctNd->DelFrames(nullptr, true);
653 }
654
655 RemoveNode( aRg.aEnd.GetIndex(), SwNodeOffset(1), false ); // delete EndNode
656 SwNodeOffset nSttPos = pSttNd->GetIndex();
657
658 // this StartNode will be removed later
659 SwStartNode* pTmpSttNd = new SwStartNode( *this, nSttPos+1 );
660 pTmpSttNd->m_pStartOfSection = pSttNd->m_pStartOfSection;
661
662 RemoveNode( nSttPos, SwNodeOffset(1), false ); // delete SttNode
663
665 rNodes.InsertNode( pSttNd, aIdx );
666 rNodes.InsertNode( pCurrentNode, aIdx );
667 --aIdx;
668 pSttNd->m_pEndOfSection = static_cast<SwEndNode*>(pCurrentNode);
669
670 --aRg.aEnd;
671
672 nLevel++; // put the index pointing to the StartNode onto the stack
673 aSttNdStack.insert( aSttNdStack.begin() + nLevel, pSttNd );
674
675 // reset remaining indices if SectionNode
676 if( pSctNd )
677 {
678 pSctNd->NodesArrChgd();
679 ++nSectNdCnt;
680 // tdf#132326 do not let frames survive in undo nodes
681 if (!GetDoc().GetIDocumentUndoRedo().IsUndoNodes(rNodes))
682 {
683 bNewFrames = false;
684 }
685 }
686 }
687 }
688 break;
689
691 if( !nLevel &&
693 {
694 // here, a SectionDummyNode needs to be inserted at the current position
695 if( nInsPos ) // move everything until here
696 {
697 // delete and copy. CAUTION: all indices after
698 // "aRg.aEnd+1" will be moved as well!
699 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
700 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
701 aIdx -= nInsPos;
702 nInsPos = SwNodeOffset(0);
703 }
704 new SwPlaceholderNode(aIdx);
705 --aRg.aEnd;
706 --aIdx;
707 break;
708 }
709 [[fallthrough]];
712 {
713 // empty section -> nothing to do
714 // and only if it's a top level section
715 if( !nInsPos && !nLevel )
716 {
717 --aRg.aEnd;
718 break;
719 }
720
721 if( !nLevel ) // level is decreasing
722 {
723 // create decrease
724 SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 );
725 SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx,
727 static_cast<SwStartNode*>(pCurrentNode)->GetStartNodeType() );
728
729 --aTmpSIdx;
730
731 SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd );
732 new SwEndNode( aTmpEIdx, *pTmpStt );
733 --aTmpEIdx;
734 ++aTmpSIdx;
735
736 // set correct StartOfSection
737 ++aRg.aEnd;
738 {
739 SwNodeIndex aCntIdx( aRg.aEnd );
740 for( SwNodeOffset n(0); n < nInsPos; n++, ++aCntIdx)
741 aCntIdx.GetNode().m_pStartOfSection = pTmpStt;
742 }
743
744 // also set correct StartNode for all decreased nodes
745 while( aTmpSIdx < aTmpEIdx )
746 if( nullptr != (( pCurrentNode = &aTmpEIdx.GetNode())->GetEndNode()) )
747 aTmpEIdx = pCurrentNode->StartOfSectionIndex();
748 else
749 {
750 pCurrentNode->m_pStartOfSection = pTmpStt;
751 --aTmpEIdx;
752 }
753
754 --aIdx; // after the inserted StartNode
755 --aRg.aEnd; // before StartNode
756 // copy array. CAUTION: all indices after
757 // "aRg.aEnd+1" will be moved as well!
758 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
759 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
760 aIdx -= nInsPos+1;
761 nInsPos = SwNodeOffset(0);
762 }
763 else // all nodes between StartNode and EndNode were moved
764 {
765 OSL_ENSURE( pCurrentNode == aSttNdStack[nLevel] ||
766 ( pCurrentNode->IsStartNode() &&
767 aSttNdStack[nLevel]->IsSectionNode()),
768 "wrong StartNode" );
769
770 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
771 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
772 aIdx -= nInsPos+1; // before inserted StartNode
773 nInsPos = SwNodeOffset(0);
774
775 // remove pointer from node array
776 RemoveNode( aRg.aEnd.GetIndex(), SwNodeOffset(1), true );
777 --aRg.aEnd;
778
779 SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode();
780 if( pSectNd && !--nSectNdCnt )
781 {
782 SwNodeIndex aTmp( *pSectNd );
783 pSectNd->MakeOwnFrames(&aTmp);
784 bNewFrames = bSaveNewFrames;
785 }
786 aSttNdStack.erase( aSttNdStack.begin() + nLevel ); // remove from stack
787 nLevel--;
788 }
789
790 // delete all resulting empty start/end node pairs
791 SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode();
792 if( pTmpNode && SwNodeType::Start == (pCurrentNode = &aRg.aEnd.GetNode())
793 ->GetNodeType() && pCurrentNode->StartOfSectionIndex() &&
794 pTmpNode->StartOfSectionNode() == pCurrentNode )
795 {
796 DelNodes( aRg.aEnd, SwNodeOffset(2) );
797 --aRg.aEnd;
798 }
799 }
800 break;
801
802 case SwNodeType::Text:
803 //Add special function to text node.
804 {
805 if( bNewFrames && pCurrentNode->GetContentNode() )
806 static_cast<SwContentNode*>(pCurrentNode)->DelFrames(nullptr);
807 pCurrentNode->m_pStartOfSection = aSttNdStack[ nLevel ];
808 nInsPos++;
809 --aRg.aEnd;
810 }
811 break;
812 case SwNodeType::Grf:
813 case SwNodeType::Ole:
814 {
815 if( bNewFrames && pCurrentNode->GetContentNode() )
816 static_cast<SwContentNode*>(pCurrentNode)->DelFrames(nullptr);
817
818 pCurrentNode->m_pStartOfSection = aSttNdStack[ nLevel ];
819 nInsPos++;
820 --aRg.aEnd;
821 }
822 break;
823
826 {
827 if( &rNodes == this ) // inside UndoNodesArray
828 {
829 // move everything
830 pCurrentNode->m_pStartOfSection = aSttNdStack[ nLevel ];
831 nInsPos++;
832 }
833 else // move into "normal" node array
834 {
835 // than a SectionNode (start/end) is needed at the current
836 // InsPos; if so skip it, otherwise ignore current node
837 if( nInsPos ) // move everything until here
838 {
839 // delete and copy. CAUTION: all indices after
840 // "aRg.aEnd+1" will be moved as well!
841 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
842 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
843 aIdx -= nInsPos;
844 nInsPos = SwNodeOffset(0);
845 }
846 SwNode* pTmpNd = &aIdx.GetNode();
847 if( pTmpNd->IsSectionNode() ||
848 pTmpNd->StartOfSectionNode()->IsSectionNode() )
849 --aIdx; // skip
850 }
851 }
852 else {
853 assert(!"How can this node be in the node array?");
854 }
855 --aRg.aEnd;
856 break;
857
858 default:
859 assert(!"Unknown node type");
860 break;
861 }
862 }
863
864 if( nInsPos ) // copy remaining rest
865 {
866 // rest should be ok
867 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
868 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
869 }
870 ++aRg.aEnd; // again, exclusive end
871
872 // delete all resulting empty start/end node pairs
873 if( ( pCurrentNode = &aRg.aStart.GetNode())->GetStartNode() &&
874 pCurrentNode->StartOfSectionIndex() &&
875 aRg.aEnd.GetNode().GetEndNode() )
876 DelNodes( aRg.aStart, SwNodeOffset(2) );
877
878 // initialize numbering update
879 ++aOrigInsPos.aStart;
880 // Moved in same node array? Then call update top down!
881 if( this == &rNodes &&
882 aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() )
883 {
884 UpdateOutlineIdx( aOrigInsPos.aStart.GetNode() );
886 }
887 else
888 {
890 rNodes.UpdateOutlineIdx( aOrigInsPos.aStart.GetNode() );
891 }
892
893 return true;
894}
895
913{
914 if( pRange->aStart >= pRange->aEnd ||
915 pRange->aEnd >= Count() ||
916 !::CheckNodesRange(pRange->aStart, pRange->aEnd, false))
917 {
918 return;
919 }
920
921 // If the beginning of a range is before or at a start node position, so
922 // delete it, otherwise empty S/E or E/S nodes would be created.
923 // For other nodes, create a new start node.
924 SwNode * pCurrentNode = &pRange->aStart.GetNode();
925 SwNodeIndex aTmpIdx( *pCurrentNode->StartOfSectionNode() );
926
927 if( pCurrentNode->GetEndNode() )
928 DelNodes( pRange->aStart ); // prevent empty section
929 else
930 {
931 // insert a new StartNode
932 SwNode* pSttNd = new SwStartNode( pRange->aStart, SwNodeType::Start, eSttNdTyp );
933 pRange->aStart = *pSttNd;
934 aTmpIdx = pRange->aStart;
935 }
936
937 // If the end of a range is before or at a StartNode, so delete it,
938 // otherwise empty S/E or E/S nodes would be created.
939 // For other nodes, insert a new end node.
940 --pRange->aEnd;
941 if( pRange->aEnd.GetNode().GetStartNode() )
942 DelNodes( pRange->aEnd );
943 else
944 {
945 ++pRange->aEnd;
946 // insert a new EndNode
947 new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() );
948 }
949 --pRange->aEnd;
950
951 SectionUpDown( aTmpIdx, pRange->aEnd );
952}
953
967{
968 if( pRange->aStart >= pRange->aEnd ||
969 pRange->aEnd >= Count() ||
970 !::CheckNodesRange(pRange->aStart, pRange->aEnd, false) ||
971 ( HighestLevel( *this, *pRange ) <= 1 ))
972 {
973 return;
974 }
975
976 // If the beginning of a range is before or at a start node position, so
977 // delete it, otherwise empty S/E or E/S nodes would be created.
978 // For other nodes, create a new start node.
979 SwNode * pCurrentNode = &pRange->aStart.GetNode();
980 SwNodeIndex aIdx( *pCurrentNode->StartOfSectionNode() );
981 if( pCurrentNode->IsStartNode() ) // is StartNode itself
982 {
983 SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode();
984 if (pEndNd && pCurrentNode == pEndNd->m_pStartOfSection)
985 {
986 // there was a pairwise reset, adjust only those in the range
987 SwStartNode* pTmpSttNd = pCurrentNode->m_pStartOfSection;
988 RemoveNode( pRange->aStart.GetIndex(), SwNodeOffset(1), true );
989 RemoveNode( pRange->aEnd.GetIndex(), SwNodeOffset(1), true );
990
991 SwNodeIndex aTmpIdx( pRange->aStart );
992 while( aTmpIdx < pRange->aEnd )
993 {
994 pCurrentNode = &aTmpIdx.GetNode();
995 pCurrentNode->m_pStartOfSection = pTmpSttNd;
996 if( pCurrentNode->IsStartNode() )
997 aTmpIdx = pCurrentNode->EndOfSectionIndex() + 1;
998 else
999 ++aTmpIdx;
1000 }
1001 return ;
1002 }
1003 DelNodes( pRange->aStart );
1004 }
1005 else if( aIdx == pRange->aStart.GetIndex()-1 ) // before StartNode
1006 DelNodes( aIdx );
1007 else
1008 new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() );
1009
1010 // If the end of a range is before or at a StartNode, so delete it,
1011 // otherwise empty S/E or E/S nodes would be created.
1012 // For other nodes, insert a new end node.
1013 SwNodeIndex aTmpIdx( pRange->aEnd );
1014 if( pRange->aEnd.GetNode().IsEndNode() )
1015 DelNodes( pRange->aEnd );
1016 else
1017 {
1018 new SwStartNode( pRange->aEnd );
1019/*?? which NodeType ??*/
1020 aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode();
1021 --pRange->aEnd;
1022 }
1023
1024 SectionUpDown( aIdx, aTmpIdx );
1025}
1026
1037void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd )
1038{
1039 SwNodeIndex aTmpIdx( aStart, +1 );
1040 // array forms a stack, holding all StartOfSelections
1041 SwStartNodePointers aSttNdStack;
1042 SwStartNode* pTmp = aStart.GetNode().GetStartNode();
1043 aSttNdStack.push_back( pTmp );
1044
1045 // loop until the first start node that needs to be change was found
1046 // (the indices are updated from the end node backwards to the start)
1047 for( ;; ++aTmpIdx )
1048 {
1049 SwNode * pCurrentNode = &aTmpIdx.GetNode();
1050 pCurrentNode->m_pStartOfSection = aSttNdStack[ aSttNdStack.size()-1 ];
1051
1052 if( pCurrentNode->GetStartNode() )
1053 {
1054 pTmp = static_cast<SwStartNode*>(pCurrentNode);
1055 aSttNdStack.push_back( pTmp );
1056 }
1057 else if( pCurrentNode->GetEndNode() )
1058 {
1059 SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.size() - 1 ];
1060 pSttNd->m_pEndOfSection = static_cast<SwEndNode*>(pCurrentNode);
1061 aSttNdStack.pop_back();
1062 if( !aSttNdStack.empty() )
1063 continue; // still enough EndNodes on the stack
1064
1065 else if( aTmpIdx < aEnd ) // too many StartNodes
1066 // if the end is not reached, yet, get the start of the section above
1067 {
1068 aSttNdStack.insert( aSttNdStack.begin(), pSttNd->m_pStartOfSection );
1069 }
1070 else // finished, as soon as out of the range
1071 break;
1072 }
1073 }
1074}
1075
1085void SwNodes::Delete(const SwNodeIndex &rIndex, SwNodeOffset nNodes)
1086{
1087 int nLevel = 0; // level counter
1088 SwNode * pCurrentNode;
1089
1090 SwNodeOffset nCnt = Count() - rIndex.GetIndex() - 1;
1091 if( nCnt > nNodes ) nCnt = nNodes;
1092
1093 if( nCnt == SwNodeOffset(0) ) // no count -> return
1094 return;
1095
1096 SwNodeRange aRg( rIndex, SwNodeOffset(0), rIndex, nCnt-1 );
1097 // check if [rIndex..rIndex + nCnt] is larger than the range
1098 if( ( !aRg.aStart.GetNode().StartOfSectionIndex() &&
1099 !aRg.aStart.GetIndex() ) ||
1100 !::CheckNodesRange(aRg.aStart, aRg.aEnd, false))
1101 {
1102 return;
1103 }
1104
1105 // if aEnd is not on a ContentNode, search the previous one
1106 while( ( pCurrentNode = &aRg.aEnd.GetNode())->GetStartNode() ||
1107 ( pCurrentNode->GetEndNode() &&
1108 !pCurrentNode->m_pStartOfSection->IsTableNode() ))
1109 --aRg.aEnd;
1110
1111 nCnt = SwNodeOffset(0);
1112//TODO: check/improve comment
1113 // increase start so that we are able to use "<" (using "<=" might cause
1114 // problems if aEnd == aStart and aEnd is deleted, so aEnd <= aStart)
1115 --aRg.aStart;
1116
1117 bool bSaveInNodesDel = m_bInNodesDel;
1118 m_bInNodesDel = true;
1119 bool bUpdateOutline = false;
1120
1121 // loop until everything is deleted
1122 while( aRg.aStart < aRg.aEnd )
1123 {
1124 pCurrentNode = &aRg.aEnd.GetNode();
1125
1126 if( pCurrentNode->GetEndNode() )
1127 {
1128 // delete the whole section?
1129 if( pCurrentNode->StartOfSectionIndex() > aRg.aStart.GetIndex() )
1130 {
1131 SwTableNode* pTableNd = pCurrentNode->m_pStartOfSection->GetTableNode();
1132 if( pTableNd )
1133 pTableNd->DelFrames();
1134
1135 SwNode *pNd, *pChkNd = pCurrentNode->m_pStartOfSection;
1137 do {
1138 pNd = &aRg.aEnd.GetNode();
1139
1140 if( pNd->IsTextNode() )
1141 {
1142 SwTextNode *const pTextNode(pNd->GetTextNode());
1143 if (pTextNode->IsOutline() &&
1144 m_pOutlineNodes->Seek_Entry( pNd, &nIdxPos ))
1145 {
1146 // remove outline indices
1147 m_pOutlineNodes->erase_at(nIdxPos);
1148 bUpdateOutline = true;
1149 }
1150 pTextNode->InvalidateNumRule();
1151 }
1152 else if( pNd->IsEndNode() &&
1154 static_cast<SwTableNode*>(pNd->m_pStartOfSection)->DelFrames();
1155
1156 --aRg.aEnd;
1157 nCnt++;
1158
1159 } while( pNd != pChkNd );
1160 }
1161 else
1162 {
1163 RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, true ); // delete
1164 nCnt = SwNodeOffset(0);
1165 --aRg.aEnd; // before the EndNode
1166 nLevel++;
1167 }
1168 }
1169 else if( pCurrentNode->GetStartNode() ) // found StartNode
1170 {
1171 if( nLevel == 0 ) // decrease one level
1172 {
1173 if( nCnt )
1174 {
1175 // now delete array
1176 ++aRg.aEnd;
1177 RemoveNode( aRg.aEnd.GetIndex(), nCnt, true );
1178 nCnt = SwNodeOffset(0);
1179 }
1180 }
1181 else // remove all nodes between start and end node (incl. both)
1182 {
1183 RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, true ); // delete array
1184 nCnt = SwNodeOffset(0);
1185 nLevel--;
1186 }
1187
1188 // after deletion, aEnd might point to an EndNode...
1189 // delete all empty start/end node pairs
1190 SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1191 --aRg.aEnd;
1192 while( pTmpNode &&
1193 ( pCurrentNode = &aRg.aEnd.GetNode())->GetStartNode() &&
1194 pCurrentNode->StartOfSectionIndex() )
1195 {
1196 // remove end and start node
1197 DelNodes( aRg.aEnd, SwNodeOffset(2) );
1198 pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1199 --aRg.aEnd;
1200 }
1201 }
1202 else // "normal" node, so insert into TmpArray
1203 {
1204 SwTextNode* pTextNd = pCurrentNode->GetTextNode();
1205 if( pTextNd )
1206 {
1207 if( pTextNd->IsOutline())
1208 {
1209 // delete outline indices
1210 m_pOutlineNodes->erase( pTextNd );
1211 bUpdateOutline = true;
1212 }
1214 {
1215 pTextNd->InvalidateNumRule();
1216 }
1217 }
1218 else if( pCurrentNode->IsContentNode() )
1219 static_cast<SwContentNode*>(pCurrentNode)->InvalidateNumRule();
1220
1221 --aRg.aEnd;
1222 nCnt++;
1223 }
1224 }
1225
1226 ++aRg.aEnd;
1227 if( nCnt != SwNodeOffset(0) )
1228 RemoveNode( aRg.aEnd.GetIndex(), nCnt, true ); // delete the rest
1229
1230 // delete all empty start/end node pairs
1231 while( aRg.aEnd.GetNode().GetEndNode() &&
1232 ( pCurrentNode = &aRg.aStart.GetNode())->GetStartNode() &&
1233 pCurrentNode->StartOfSectionIndex() )
1234 // but none of the holy 5. (???)
1235 {
1236 DelNodes( aRg.aStart, SwNodeOffset(2) ); // delete start and end node
1237 --aRg.aStart;
1238 }
1239
1240 m_bInNodesDel = bSaveInNodesDel;
1241
1242 if( !m_bInNodesDel )
1243 {
1244 // update numbering
1245 if( bUpdateOutline || m_bInDelUpdOutline )
1246 {
1247 UpdateOutlineIdx( aRg.aEnd.GetNode() );
1248 m_bInDelUpdOutline = false;
1249 }
1250
1251 }
1252 else
1253 {
1254 if( bUpdateOutline )
1255 m_bInDelUpdOutline = true;
1256 }
1257}
1258
1269{
1270 // special treatment for 1st Node
1271 if(rIdx == SwNodeOffset(0)) return 1;
1272 // no recursion! This calls a SwNode::GetSectionLevel (missing "s")
1273 return rIdx.GetNode().GetSectionLevel();
1274}
1275
1277{
1278 // after the next start node
1279 SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 );
1280
1281 // If index points to no ContentNode, then go to one.
1282 // If there is no further available, do not change the index' position!
1283 while( !aTmp.GetNode().IsContentNode() )
1284 { // go from this StartNode (can only be one) to its end
1285 if( *pIdx <= aTmp )
1286 return; // ERROR: already after the section
1287 aTmp = aTmp.GetNode().EndOfSectionIndex()+1;
1288 if( *pIdx <= aTmp )
1289 return; // ERROR: already after the section
1290 }
1291 (*pIdx) = aTmp; // is on a ContentNode
1292}
1293
1295{
1296 if( !pIdx->GetNode().IsEndNode() )
1297 (*pIdx) = *pIdx->GetNode().EndOfSectionNode();
1298}
1299
1301{
1302 if( pIdx->GetIndex() >= Count() - 1 )
1303 return nullptr;
1304
1305 SwNodeIndex aTmp(*pIdx, +1);
1306 SwNode* pNd = nullptr;
1307 while( aTmp < Count()-1 && !( pNd = &aTmp.GetNode())->IsContentNode() )
1308 ++aTmp;
1309
1310 if( aTmp == Count()-1 )
1311 pNd = nullptr;
1312 else
1313 (*pIdx) = aTmp;
1314 return static_cast<SwContentNode*>(pNd);
1315}
1316
1318{
1319 if( !pIdx->GetIndex() )
1320 return nullptr;
1321
1322 SwNodeIndex aTmp( *pIdx, -1 );
1323 SwNode* pNd = nullptr;
1324 while( aTmp.GetIndex() && !( pNd = &aTmp.GetNode())->IsContentNode() )
1325 --aTmp;
1326
1327 if( !aTmp.GetIndex() )
1328 pNd = nullptr;
1329 else
1330 (*pIdx) = aTmp;
1331 return static_cast<SwContentNode*>(pNd);
1332}
1333
1339void SwNodes::DelNodes( const SwNodeIndex & rStart, SwNodeOffset nCnt )
1340{
1341 SwNodeOffset nSttIdx = rStart.GetIndex();
1342
1343 if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 )
1344 {
1345 // The whole nodes array will be destroyed, you're in the Doc's DTOR!
1346 // The initial start/end nodes should be only destroyed in the SwNodes' DTOR!
1347 SwNode* aEndNdArr[] = { m_pEndOfContent.get(),
1350 nullptr
1351 };
1352
1353 SwNode** ppEndNdArr = aEndNdArr;
1354 while( *ppEndNdArr )
1355 {
1356 nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1;
1357 SwNodeOffset nEndIdx = (*ppEndNdArr)->GetIndex();
1358
1359 if( nSttIdx != nEndIdx )
1360 RemoveNode( nSttIdx, nEndIdx - nSttIdx, true );
1361
1362 ++ppEndNdArr;
1363 }
1364 }
1365 else
1366 {
1367 int bUpdateNum = 0;
1368 for( SwNodeOffset n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n )
1369 {
1370 SwNode* pNd = (*this)[ n ];
1371
1372 if (pNd->IsTextNode() && pNd->GetTextNode()->IsOutline())
1373 {
1374 // remove the outline indices
1375 if (m_pOutlineNodes->erase(pNd))
1376 bUpdateNum = 1;
1377 }
1378 if( pNd->IsContentNode() )
1379 {
1380 static_cast<SwContentNode*>(pNd)->InvalidateNumRule();
1381 static_cast<SwContentNode*>(pNd)->DelFrames(nullptr);
1382 }
1383 }
1384 RemoveNode( nSttIdx, nCnt, true );
1385
1386 // update numbering
1387 if( bUpdateNum )
1388 UpdateOutlineIdx( rStart.GetNode() );
1389 }
1390}
1391
1392namespace {
1393
1394struct HighLevel
1395{
1396 sal_uInt16 nLevel, nTop;
1397 explicit HighLevel( sal_uInt16 nLv ) : nLevel( nLv ), nTop( nLv ) {}
1398};
1399
1400}
1401
1402static bool lcl_HighestLevel( SwNode* pNode, void * pPara )
1403{
1404 HighLevel * pHL = static_cast<HighLevel*>(pPara);
1405 if( pNode->GetStartNode() )
1406 pHL->nLevel++;
1407 else if( pNode->GetEndNode() )
1408 pHL->nLevel--;
1409 if( pHL->nTop > pHL->nLevel )
1410 pHL->nTop = pHL->nLevel;
1411 return true;
1412
1413}
1414
1421sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1422{
1423 HighLevel aPara( SwNodes::GetSectionLevel( rRange.aStart ));
1424 rNodes.ForEach( rRange.aStart, rRange.aEnd, lcl_HighestLevel, &aPara );
1425 return aPara.nTop;
1426
1427}
1428
1435void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
1436{
1437 SwPosition * const pStt = rPam.Start();
1438 SwPosition * const pEnd = rPam.End();
1439
1440 if( !rPam.HasMark() || *pStt >= *pEnd )
1441 return;
1442
1443 if( this == &rNodes && *pStt <= rPos && rPos < *pEnd )
1444 return;
1445
1446 SwNodeIndex aEndIdx( pEnd->nNode );
1447 SwNodeIndex aSttIdx( pStt->nNode );
1448 SwTextNode *const pSrcNd = aSttIdx.GetNode().GetTextNode();
1449 SwTextNode * pDestNd = rPos.nNode.GetNode().GetTextNode();
1450 bool bSplitDestNd = true;
1451 bool bCopyCollFormat = pDestNd && pDestNd->GetText().isEmpty();
1452
1453 if( pSrcNd )
1454 {
1455 // if the first node is a TextNode, then there must
1456 // be also a TextNode in the NodesArray to store the content
1457 if( !pDestNd )
1458 {
1459 pDestNd = rNodes.MakeTextNode( rPos.nNode, pSrcNd->GetTextColl() );
1460 --rPos.nNode;
1461 rPos.nContent.Assign( pDestNd, 0 );
1462 bCopyCollFormat = true;
1463 }
1464 bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() ||
1465 pEnd->nNode.GetNode().IsTextNode();
1466
1467 // move the content into the new node
1468 bool bOneNd = pStt->nNode == pEnd->nNode;
1469 const sal_Int32 nLen =
1470 ( bOneNd ? std::min(pEnd->nContent.GetIndex(), pSrcNd->Len()) : pSrcNd->Len() )
1471 - pStt->nContent.GetIndex();
1472
1473 if( !pEnd->nNode.GetNode().IsContentNode() )
1474 {
1475 bOneNd = true;
1476 SwNodeOffset nSttNdIdx = pStt->nNode.GetIndex() + 1;
1477 const SwNodeOffset nEndNdIdx = pEnd->nNode.GetIndex();
1478 for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx )
1479 {
1480 if( (*this)[ nSttNdIdx ]->IsContentNode() )
1481 {
1482 bOneNd = false;
1483 break;
1484 }
1485 }
1486 }
1487
1488 // templates must be copied/set after a split
1489 if( !bOneNd && bSplitDestNd )
1490 {
1491 if( !rPos.nContent.GetIndex() )
1492 {
1493 bCopyCollFormat = true;
1494 }
1495 if( rNodes.IsDocNodes() )
1496 {
1497 SwDoc& rInsDoc = pDestNd->GetDoc();
1498 ::sw::UndoGuard const ug(rInsDoc.GetIDocumentUndoRedo());
1499 rInsDoc.getIDocumentContentOperations().SplitNode( rPos, false );
1500 }
1501 else
1502 {
1503 pDestNd->SplitContentNode(rPos, nullptr);
1504 }
1505
1506 if( rPos.nNode == aEndIdx )
1507 {
1508 --aEndIdx;
1509 }
1510 bSplitDestNd = true;
1511
1512 pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTextNode();
1513 if( nLen )
1514 {
1515 pSrcNd->CutText( pDestNd, SwIndex( pDestNd, pDestNd->Len()),
1516 pStt->nContent, nLen );
1517 }
1518 }
1519 else if ( nLen )
1520 {
1521 pSrcNd->CutText( pDestNd, rPos.nContent, pStt->nContent, nLen );
1522 }
1523
1524 if( bCopyCollFormat )
1525 {
1526 SwDoc& rInsDoc = pDestNd->GetDoc();
1527 ::sw::UndoGuard const undoGuard(rInsDoc.GetIDocumentUndoRedo());
1528 pSrcNd->CopyCollFormat( *pDestNd );
1529 }
1530
1531 if( bOneNd )
1532 {
1533 // Correct the PaM, because it might have happened that the move
1534 // went over the node borders (so the data might be in different nodes).
1535 // Also, a selection is invalidated.
1536 pEnd->nContent = pStt->nContent;
1537 rPam.DeleteMark();
1538 GetDoc().GetDocShell()->Broadcast( SwFormatFieldHint( nullptr,
1540 return;
1541 }
1542
1543 ++aSttIdx;
1544 }
1545 else if( pDestNd )
1546 {
1547 if( rPos.nContent.GetIndex() )
1548 {
1549 if( rPos.nContent.GetIndex() == pDestNd->Len() )
1550 {
1551 ++rPos.nNode;
1552 }
1553 else if( rPos.nContent.GetIndex() )
1554 {
1555 // if the EndNode is split than correct the EndIdx
1556 const bool bCorrEnd = aEndIdx == rPos.nNode;
1557
1558 // if no text is attached to the TextNode, split it
1559 if( rNodes.IsDocNodes() )
1560 {
1561 SwDoc& rInsDoc = pDestNd->GetDoc();
1562 ::sw::UndoGuard const ug(rInsDoc.GetIDocumentUndoRedo());
1563 rInsDoc.getIDocumentContentOperations().SplitNode( rPos, false );
1564 }
1565 else
1566 {
1567 pDestNd->SplitContentNode(rPos, nullptr);
1568 }
1569
1570 if ( bCorrEnd )
1571 {
1572 --aEndIdx;
1573 }
1574 }
1575 }
1576 // at the end only an empty TextNode is left over
1577 bSplitDestNd = true;
1578 }
1579
1580 SwTextNode* const pEndSrcNd = aEndIdx.GetNode().GetTextNode();
1581 if ( pEndSrcNd )
1582 {
1583 // at the end of this range a new TextNode will be created
1584 if( !bSplitDestNd )
1585 {
1586 if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() )
1587 {
1588 ++rPos.nNode;
1589 }
1590
1591 pDestNd =
1592 rNodes.MakeTextNode( rPos.nNode, pEndSrcNd->GetTextColl() );
1593 --rPos.nNode;
1594 rPos.nContent.Assign( pDestNd, 0 );
1595 }
1596 else
1597 {
1598 pDestNd = rPos.nNode.GetNode().GetTextNode();
1599 }
1600
1601 if (pDestNd && pEnd->nContent.GetIndex())
1602 {
1603 // move the content into the new node
1604 SwIndex aIdx( pEndSrcNd, 0 );
1605 pEndSrcNd->CutText( pDestNd, rPos.nContent, aIdx,
1606 pEnd->nContent.GetIndex());
1607 }
1608
1609 if (pDestNd && bCopyCollFormat)
1610 {
1611 SwDoc& rInsDoc = pDestNd->GetDoc();
1612 ::sw::UndoGuard const ug(rInsDoc.GetIDocumentUndoRedo());
1613 pEndSrcNd->CopyCollFormat( *pDestNd );
1614 }
1615 }
1616 else
1617 {
1618 if ( pSrcNd && aEndIdx.GetNode().IsContentNode() )
1619 {
1620 ++aEndIdx;
1621 }
1622 if( !bSplitDestNd )
1623 {
1624 ++rPos.nNode;
1625 rPos.nContent.Assign( rPos.nNode.GetNode().GetContentNode(), 0 );
1626 }
1627 }
1628
1629 if( aEndIdx != aSttIdx )
1630 {
1631 // move the nodes into the NodesArray
1632 const SwNodeOffset nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex();
1633 SwNodeRange aRg( aSttIdx, aEndIdx );
1634 MoveNodes( aRg, rNodes, rPos.nNode );
1635
1636 // if in the same node array, all indices are now at new positions (so correct them)
1637 if( &rNodes == this )
1638 {
1639 pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff;
1640 }
1641 }
1642
1643 // if the StartNode was moved to whom the cursor pointed, so
1644 // the content must be registered in the current content!
1645 if ( &pStt->nNode.GetNode() == &GetEndOfContent() )
1646 {
1647 const bool bSuccess = GoPrevious( &pStt->nNode );
1648 OSL_ENSURE( bSuccess, "Move() - no ContentNode here" );
1649 }
1650 pStt->nContent.Assign( pStt->nNode.GetNode().GetContentNode(),
1651 pStt->nContent.GetIndex() );
1652 // Correct the PaM, because it might have happened that the move
1653 // went over the node borders (so the data might be in different nodes).
1654 // Also, a selection is invalidated.
1655 *pEnd = *pStt;
1656 rPam.DeleteMark();
1657 GetDoc().GetDocShell()->Broadcast( SwFormatFieldHint( nullptr,
1659}
1660
1663 const SwNodeIndex& rIndex, bool bNewFrames, bool bTableInsDummyNode ) const
1664{
1665 SwDoc& rDoc = rIndex.GetNode().GetDoc();
1666
1667 SwNode * pCurrentNode;
1668 if( rIndex == SwNodeOffset(0) ||
1669 ( (pCurrentNode = &rIndex.GetNode())->GetStartNode() &&
1670 !pCurrentNode->StartOfSectionIndex() ))
1671 return;
1672
1673 SwNodeRange aRg( rRange );
1674
1675 // skip "simple" StartNodes or EndNodes
1676 while( SwNodeType::Start == (pCurrentNode = & aRg.aStart.GetNode())->GetNodeType()
1677 || ( pCurrentNode->IsEndNode() &&
1678 !pCurrentNode->m_pStartOfSection->IsSectionNode() ) )
1679 ++aRg.aStart;
1680
1681 const SwNode *aEndNode = &aRg.aEnd.GetNode();
1682 SwNodeOffset nIsEndOfContent((aEndNode == &aEndNode->GetNodes().GetEndOfContent()) ? 1 : 0);
1683
1684 if (SwNodeOffset(0) == nIsEndOfContent)
1685 {
1686 // if aEnd-1 points to no ContentNode, search previous one
1687 --aRg.aEnd;
1688 // #i107142#: if aEnd is start node of a special section, do nothing.
1689 // Otherwise this could lead to crash: going through all previous
1690 // special section nodes and then one before the first.
1691 if (aRg.aEnd.GetNode().StartOfSectionIndex() != SwNodeOffset(0))
1692 {
1693 while( ((pCurrentNode = & aRg.aEnd.GetNode())->GetStartNode() &&
1694 !pCurrentNode->IsSectionNode() ) ||
1695 ( pCurrentNode->IsEndNode() &&
1696 SwNodeType::Start == pCurrentNode->m_pStartOfSection->GetNodeType()) )
1697 {
1698 --aRg.aEnd;
1699 }
1700 }
1701 ++aRg.aEnd;
1702 }
1703
1704 // is there anything left to copy?
1705 if( aRg.aStart >= aRg.aEnd )
1706 return;
1707
1708 // when inserting into the source range, nothing need to be done
1709 OSL_ENSURE( &aRg.aStart.GetNodes() == this,
1710 "aRg should use this node array" );
1711 OSL_ENSURE( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(),
1712 "Range across different nodes arrays? You deserve punishment!");
1713 if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() &&
1714 rIndex.GetIndex() >= aRg.aStart.GetIndex() &&
1715 rIndex.GetIndex() < aRg.aEnd.GetIndex() )
1716 return;
1717
1718 SwNodeIndex aInsPos( rIndex );
1719 SwNodeIndex aOrigInsPos( rIndex, -1 ); // original insertion position
1720 int nLevel = 0; // level counter
1721
1722 for( SwNodeOffset nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
1723 nNodeCnt > SwNodeOffset(0); --nNodeCnt )
1724 {
1725 pCurrentNode = &aRg.aStart.GetNode();
1726 switch( pCurrentNode->GetNodeType() )
1727 {
1728 case SwNodeType::Table:
1729 // Does it copy a table in(to) a footnote?
1730 if( aInsPos < rDoc.GetNodes().GetEndOfInserts().GetIndex() &&
1732 < aInsPos.GetIndex() )
1733 {
1734 const SwNodeOffset nDistance =
1735 pCurrentNode->EndOfSectionIndex() -
1736 aRg.aStart.GetIndex();
1737 if (nDistance < nNodeCnt)
1738 nNodeCnt -= nDistance;
1739 else
1740 nNodeCnt = SwNodeOffset(1);
1741
1742 // insert a DummyNode for a TableNode
1743 if( bTableInsDummyNode )
1744 new SwPlaceholderNode(aInsPos);
1745
1746 // copy all of the table's nodes into the current cell
1747 for( ++aRg.aStart; aRg.aStart.GetIndex() <
1748 pCurrentNode->EndOfSectionIndex();
1749 ++aRg.aStart )
1750 {
1751 // insert a DummyNode for the box-StartNode?
1752 if( bTableInsDummyNode )
1753 new SwPlaceholderNode(aInsPos);
1754
1755 SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode();
1756 CopyNodes( SwNodeRange( *pSttNd, SwNodeOffset(+ 1),
1757 *pSttNd->EndOfSectionNode() ),
1758 aInsPos, bNewFrames );
1759
1760 // insert a DummyNode for the box-EndNode?
1761 if( bTableInsDummyNode )
1762 new SwPlaceholderNode(aInsPos);
1763 aRg.aStart = *pSttNd->EndOfSectionNode();
1764 }
1765 // insert a DummyNode for the table-EndNode
1766 if( bTableInsDummyNode )
1767 new SwPlaceholderNode(aInsPos);
1768 aRg.aStart = *pCurrentNode->EndOfSectionNode();
1769 }
1770 else
1771 {
1772 SwNodeIndex nStt( aInsPos, -1 );
1773 SwTableNode* pTableNd = static_cast<SwTableNode*>(pCurrentNode)->
1774 MakeCopy( rDoc, aInsPos );
1775 const SwNodeOffset nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
1776 if (nDistance < nNodeCnt)
1777 nNodeCnt -= nDistance;
1778 else
1779 nNodeCnt = SwNodeOffset(1) - nIsEndOfContent;
1780
1781 aRg.aStart = pCurrentNode->EndOfSectionIndex();
1782
1783 if( bNewFrames && pTableNd )
1784 {
1785 nStt = aInsPos;
1786 pTableNd->MakeOwnFrames(&nStt);
1787 }
1788 }
1789 break;
1790
1792 // If the end of the section is outside the copy range,
1793 // the section node will skipped, not copied!
1794 // If someone want to change this behaviour, he has to adjust the function
1795 // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
1796 if( pCurrentNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
1797 {
1798 // copy of the whole section, so create a new SectionNode
1799 SwNodeIndex nStt( aInsPos, -1 );
1800 SwSectionNode* pSectNd = static_cast<SwSectionNode*>(pCurrentNode)->
1801 MakeCopy( rDoc, aInsPos );
1802
1803 const SwNodeOffset nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
1804 if (nDistance < nNodeCnt)
1805 nNodeCnt -= nDistance;
1806 else
1807 nNodeCnt = SwNodeOffset(1) - nIsEndOfContent;
1808 aRg.aStart = pCurrentNode->EndOfSectionIndex();
1809
1810 if( bNewFrames && pSectNd &&
1811 !pSectNd->GetSection().IsHidden() )
1812 pSectNd->MakeOwnFrames(&nStt);
1813 }
1814 break;
1815
1816 case SwNodeType::Start:
1817 {
1818 SwStartNode* pTmp = new SwStartNode( aInsPos, SwNodeType::Start,
1819 static_cast<SwStartNode*>(pCurrentNode)->GetStartNodeType() );
1820 new SwEndNode( aInsPos, *pTmp );
1821 --aInsPos;
1822 nLevel++;
1823 }
1824 break;
1825
1826 case SwNodeType::End:
1827 if( nLevel ) // complete section
1828 {
1829 --nLevel;
1830 ++aInsPos; // EndNode already exists
1831 }
1832 else if( SwNodeOffset(1) == nNodeCnt && SwNodeOffset(1) == nIsEndOfContent )
1833 // we have reached the EndOfContent node - nothing to do!
1834 continue;
1835 else if( !pCurrentNode->m_pStartOfSection->IsSectionNode() )
1836 {
1837 // create a section at the original InsertPosition
1838 SwNodeRange aTmpRg( aOrigInsPos, SwNodeOffset(1), aInsPos );
1839 rDoc.GetNodes().SectionDown( &aTmpRg,
1840 pCurrentNode->m_pStartOfSection->GetStartNodeType() );
1841 }
1842 break;
1843
1844 case SwNodeType::Text:
1845 case SwNodeType::Grf:
1846 case SwNodeType::Ole:
1847 {
1848 static_cast<SwContentNode*>(pCurrentNode)->MakeCopy(
1849 rDoc, aInsPos, bNewFrames);
1850 }
1851 break;
1852
1855 {
1856 // than a SectionNode (start/end) is needed at the current
1857 // InsPos; if so skip it, otherwise ignore current node
1858 SwNode *const pTmpNd = & aInsPos.GetNode();
1859 if( pTmpNd->IsSectionNode() ||
1860 pTmpNd->StartOfSectionNode()->IsSectionNode() )
1861 ++aInsPos; // skip
1862 }
1863 else {
1864 assert(!"How can this node be in the node array?");
1865 }
1866 break;
1867
1868 default:
1869 assert(false);
1870 }
1871 ++aRg.aStart;
1872 }
1873}
1874
1876{
1877 SwNodeIndex aIdx( rRg.aStart );
1878 while( aIdx.GetIndex() < rRg.aEnd.GetIndex() )
1879 {
1881 RemoveNode( aIdx.GetIndex(), SwNodeOffset(1), true );
1882 else
1883 ++aIdx;
1884 }
1885}
1886
1888 SwStartNodeType eSttNdTyp )
1889{
1890 SwStartNode* pSttNd = new SwStartNode( rIdx, SwNodeType::Start, eSttNdTyp );
1891 new SwEndNode( rIdx, *pSttNd );
1892 return pSttNd;
1893}
1894
1896 SwStartNodeType eSttNdTyp,
1897 SwTextFormatColl *pColl )
1898{
1899 SwStartNode* pSttNd = new SwStartNode( rWhere, SwNodeType::Start, eSttNdTyp );
1900 new SwEndNode( rWhere, *pSttNd );
1901 MakeTextNode( SwNodeIndex( rWhere, - 1 ), pColl );
1902 return pSttNd;
1903}
1904
1905//TODO: provide better documentation
1919 bool bSkipHidden, bool bSkipProtect ) const
1920{
1921 bool bFirst = true;
1922 SwNodeIndex aTmp( *pIdx );
1923 const SwNode* pNd;
1924 while( aTmp < Count() - 1 )
1925 {
1926 pNd = & aTmp.GetNode();
1927 if (SwNodeType::Section == pNd->GetNodeType())
1928 {
1929 const SwSection& rSect = static_cast<const SwSectionNode*>(pNd)->GetSection();
1930 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
1931 (bSkipProtect && rSect.IsProtectFlag()) )
1932 // than skip the section
1933 aTmp = *pNd->EndOfSectionNode();
1934 }
1935 else if( bFirst )
1936 {
1937 if( pNd->m_pStartOfSection->IsSectionNode() )
1938 {
1939 const SwSection& rSect = static_cast<SwSectionNode*>(pNd->
1940 m_pStartOfSection)->GetSection();
1941 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
1942 (bSkipProtect && rSect.IsProtectFlag()) )
1943 // than skip the section
1944 aTmp = *pNd->EndOfSectionNode();
1945 }
1946 }
1947 else if( SwNodeType::ContentMask & pNd->GetNodeType() )
1948 {
1949 const SwSectionNode* pSectNd;
1950 if( ( bSkipHidden || bSkipProtect ) &&
1951 nullptr != (pSectNd = pNd->FindSectionNode() ) &&
1952 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
1953 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
1954 {
1955 aTmp = *pSectNd->EndOfSectionNode();
1956 }
1957 else
1958 {
1959 (*pIdx) = aTmp;
1960 return const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd));
1961 }
1962 }
1963 ++aTmp;
1964 bFirst = false;
1965 }
1966 return nullptr;
1967}
1968
1971 bool bSkipHidden, bool bSkipProtect )
1972{
1973 bool bFirst = true;
1974 SwNodeIndex aTmp( *pIdx );
1975 const SwNode* pNd;
1976 while( aTmp > SwNodeOffset(0) )
1977 {
1978 pNd = & aTmp.GetNode();
1979 if (SwNodeType::End == pNd->GetNodeType())
1980 {
1981 if( pNd->m_pStartOfSection->IsSectionNode() )
1982 {
1983 const SwSection& rSect = static_cast<SwSectionNode*>(pNd->
1984 m_pStartOfSection)->GetSection();
1985 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
1986 (bSkipProtect && rSect.IsProtectFlag()) )
1987 // than skip section
1988 aTmp = *pNd->StartOfSectionNode();
1989 }
1990 bFirst = false;
1991 }
1992 else if( bFirst )
1993 {
1994 bFirst = false;
1995 if( pNd->m_pStartOfSection->IsSectionNode() )
1996 {
1997 const SwSection& rSect = static_cast<SwSectionNode*>(pNd->
1998 m_pStartOfSection)->GetSection();
1999 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2000 (bSkipProtect && rSect.IsProtectFlag()) )
2001 // than skip section
2002 aTmp = *pNd->StartOfSectionNode();
2003 }
2004 }
2005 else if( SwNodeType::ContentMask & pNd->GetNodeType() )
2006 {
2007 const SwSectionNode* pSectNd;
2008 if( ( bSkipHidden || bSkipProtect ) &&
2009 nullptr != (pSectNd = pNd->FindSectionNode() ) &&
2010 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
2011 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2012 {
2013 aTmp = *pSectNd;
2014 }
2015 else
2016 {
2017 (*pIdx) = aTmp;
2018 return const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd));
2019 }
2020 }
2021 --aTmp;
2022 }
2023 return nullptr;
2024}
2025
2026//TODO: The inventor of the "single responsibility principle" will be crying if you ever show this code to him!
2038 SwNode const*const pEnd,
2039 SwRootFrame const*const pLayout) const
2040{
2041 assert(pEnd != nullptr); // every caller currently
2042
2043 SwNode* pFrameNd = nullptr;
2044
2045 // no layout -> skip
2046 if( GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell() )
2047 {
2048 SwNode *const pSttNd = &rFrameIdx.GetNode();
2049
2050 // inside a hidden section?
2051 SwSectionNode *const pSectNd = pSttNd->IsSectionNode()
2052 ? pSttNd->StartOfSectionNode()->FindSectionNode()
2053 : pSttNd->FindSectionNode();
2054 if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag() ) )
2055 {
2056 // in a table in table situation we have to assure that we don't leave the
2057 // outer table cell when the inner table is looking for a PrvNxt...
2058 SwTableNode *const pTableNd = pSttNd->IsTableNode()
2059 ? pSttNd->StartOfSectionNode()->FindTableNode()
2060 : pSttNd->FindTableNode();
2061 SwNodeIndex aIdx( rFrameIdx );
2062
2063 // search backward for a content or table node
2064
2065 --aIdx;
2066 pFrameNd = &aIdx.GetNode();
2067
2068 do
2069 {
2070 if (pFrameNd->IsContentNode())
2071 {
2072 // TODO why does this not check for nested tables like forward direction
2073 rFrameIdx = aIdx;
2074 return pFrameNd;
2075 }
2076 else if (pFrameNd->IsEndNode() && pFrameNd->StartOfSectionNode()->IsTableNode())
2077 {
2078 if (pLayout == nullptr
2079 || !pLayout->HasMergedParas()
2081 {
2082 pFrameNd = pFrameNd->StartOfSectionNode();
2083 rFrameIdx = *pFrameNd;
2084 return pFrameNd;
2085 }
2086 else
2087 {
2088 aIdx = *pFrameNd->StartOfSectionNode();
2089 --aIdx;
2090 pFrameNd = &aIdx.GetNode();
2091 }
2092 }
2093 else
2094 {
2095 pFrameNd = GoPrevSection( &aIdx, true, false );
2096 if ( nullptr != pFrameNd && !(
2097 ::CheckNodesRange( aIdx, rFrameIdx, true ) &&
2098 // Never out of the table at the start
2099 pFrameNd->FindTableNode() == pTableNd &&
2100 // Bug 37652: Never out of the table at the end
2101 (!pFrameNd->FindTableNode() || pFrameNd->FindTableBoxStartNode()
2102 == pSttNd->FindTableBoxStartNode() ) &&
2103 (!pSectNd || pSttNd->IsSectionNode() ||
2104 pSectNd->GetIndex() < pFrameNd->GetIndex())
2105 ))
2106 {
2107 pFrameNd = nullptr; // no preceding content node, stop search
2108 }
2109 }
2110 }
2111 while (pFrameNd != nullptr);
2112
2113 // search forward for a content or table node
2114
2115 aIdx = pEnd->GetIndex() + 1;
2116 pFrameNd = &aIdx.GetNode();
2117
2118 do
2119 {
2120 if (pFrameNd->IsContentNode())
2121 {
2122 // Undo when merging a table with one before, if there is also one after it.
2123 // However, if the node is in a table, it needs to be returned if the
2124 // SttNode is a section or a table!
2125 SwTableNode *const pTableNode = pFrameNd->FindTableNode();
2126 if (pSttNd->IsTableNode() &&
2127 nullptr != pTableNode &&
2128 // TABLE IN TABLE:
2129 pTableNode != pSttNd->StartOfSectionNode()->FindTableNode())
2130 {
2131 pFrameNd = pTableNode;
2132 rFrameIdx = *pFrameNd;
2133 }
2134 else
2135 {
2136 rFrameIdx = aIdx;
2137 }
2138 return pFrameNd;
2139 }
2140 else if (pFrameNd->IsTableNode())
2141 {
2142 if (pLayout == nullptr
2143 || !pLayout->HasMergedParas()
2145 {
2146 rFrameIdx = *pFrameNd;
2147 return pFrameNd;
2148 }
2149 else
2150 {
2151 aIdx = *pFrameNd->EndOfSectionNode();
2152 ++aIdx;
2153 pFrameNd = &aIdx.GetNode();
2154 }
2155 }
2156 else
2157 {
2158 pFrameNd = GoNextSection( &aIdx, true, false );
2159 // NEVER leave the section when doing this!
2160 if (pFrameNd
2161 && !(::CheckNodesRange(aIdx, rFrameIdx, true)
2162 && (pFrameNd->FindTableNode() == pTableNd &&
2163 // NEVER go out of the table cell at the end
2164 (!pFrameNd->FindTableNode() || pFrameNd->FindTableBoxStartNode()
2165 == pSttNd->FindTableBoxStartNode()))
2166 && (!pSectNd || pSttNd->IsSectionNode() ||
2167 pSectNd->EndOfSectionIndex() > pFrameNd->GetIndex()))
2168 )
2169 {
2170 pFrameNd = nullptr; // no following content node, stop search
2171 }
2172 }
2173 }
2174 while (pFrameNd != nullptr);
2175
2176 // probably this is dead code, because the GoNextSection()
2177 // should have ended up in the first text node in the table and
2178 // then checked it's in a table?
2179 {
2180 aIdx = pEnd->GetIndex() + 1;
2181
2182 pFrameNd = &aIdx.GetNode();
2183 {
2184 pFrameNd = nullptr;
2185
2186 // is there some sectionnodes before a tablenode?
2187 while( aIdx.GetNode().IsSectionNode() )
2188 {
2189 const SwSection& rSect = aIdx.GetNode().
2190 GetSectionNode()->GetSection();
2191 if( rSect.IsHiddenFlag() )
2192 aIdx = aIdx.GetNode().EndOfSectionIndex()+1;
2193 else
2194 ++aIdx;
2195 }
2196 if( aIdx.GetNode().IsTableNode() )
2197 {
2198 rFrameIdx = aIdx;
2199 pFrameNd = &aIdx.GetNode();
2200 assert(!"this isn't dead code?");
2201 }
2202 }
2203 }
2204 }
2205 }
2206 return pFrameNd;
2207}
2208
2210 FnForEach_SwNodes fn, void* pArgs )
2211{
2212 if( nEnd > SwNodeOffset(m_nSize) )
2213 nEnd = SwNodeOffset(m_nSize);
2214
2215 if( nStart >= nEnd )
2216 return;
2217
2218 sal_uInt16 cur = Index2Block( sal_Int32(nStart) );
2219 BlockInfo** pp = m_ppInf.get() + cur;
2220 BlockInfo* p = *pp;
2221 sal_uInt16 nElem = sal_uInt16( sal_Int32(nStart) - p->nStart );
2222 auto pElem = p->mvData.begin() + nElem;
2223 nElem = p->nElem - nElem;
2224 for(;;)
2225 {
2226 if( !(*fn)( static_cast<SwNode *>(*pElem++), pArgs ) || ++nStart >= nEnd )
2227 break;
2228
2229 // next element
2230 if( !--nElem )
2231 {
2232 // new block
2233 p = *++pp;
2234 pElem = p->mvData.begin();
2235 nElem = p->nElem;
2236 }
2237 }
2238}
2239
2240void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
2241 FnForEach_SwNodes fnForEach, void* pArgs )
2242{
2243 ForEach( rStart.GetIndex(), rEnd.GetIndex(), fnForEach, pArgs );
2244}
2245
2246void SwNodes::RemoveNode( SwNodeOffset nDelPos, SwNodeOffset nSz, bool bDel )
2247{
2248#ifndef NDEBUG
2249 SwNode *const pFirst((*this)[nDelPos]);
2250#endif
2251 for (SwNodeOffset nCnt(0); nCnt < nSz; nCnt++)
2252 {
2253 SwNode* pNode = (*this)[ nDelPos + nCnt ];
2254 SwTextNode * pTextNd = pNode->GetTextNode();
2255
2256 if (pTextNd)
2257 {
2258 pTextNd->RemoveFromList();
2259 // remove RndStdIds::FLY_AS_CHAR *before* adjusting SwNodeIndex
2260 // so their anchor still points to correct node when deleted!
2261 // NOTE: this will call RemoveNode() recursively!
2262 // so adjust our indexes to account for removed nodes
2263 SwNodeOffset const nPos = pTextNd->GetIndex();
2264 SwpHints *const pHints(pTextNd->GetpSwpHints());
2265 if (pHints)
2266 {
2267 std::vector<SwTextAttr*> flys;
2268 for (size_t i = 0; i < pHints->Count(); ++i)
2269 {
2270 SwTextAttr *const pHint(pHints->Get(i));
2271 if (RES_TXTATR_FLYCNT == pHint->Which())
2272 {
2273 flys.push_back(pHint);
2274 }
2275 }
2276 for (SwTextAttr * pHint : flys)
2277 {
2278 pTextNd->DeleteAttribute(pHint);
2279 } // pHints may be dead now
2280 SwNodeOffset const nDiff = nPos - pTextNd->GetIndex();
2281 if (nDiff)
2282 {
2283 nDelPos -= nDiff;
2284 }
2285 assert(pTextNd == (*this)[nDelPos + nCnt]);
2286 assert(pFirst == (*this)[nDelPos]);
2287 }
2288 }
2289 SwTableNode* pTableNode = pNode->GetTableNode();
2290 if (pTableNode)
2291 {
2292 // The node that is deleted is a table node.
2293 // Need to make sure that all the redlines that are
2294 // related to this table are removed from the
2295 // 'Extra Redlines' array
2296 pTableNode->RemoveRedlines();
2297 }
2298 }
2299
2300 SwNodeOffset nEnd = nDelPos + nSz;
2301 SwNode* pNew = (*this)[ nEnd ];
2302
2303 for (SwNodeIndex& rIndex : m_vIndices->GetRingContainer())
2304 {
2305 SwNodeOffset const nIdx = rIndex.GetIndex();
2306 if (nDelPos <= nIdx && nIdx < nEnd)
2307 rIndex = *pNew;
2308 }
2309
2310 std::vector<BigPtrEntry> aTempEntries;
2311 if( bDel )
2312 {
2313 SwNodeOffset nCnt = nSz;
2314 BigPtrEntry *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ];
2315
2316 // set temporary object
2317 // JP 24.08.98: this should actually be removed because one could
2318 // call Remove recursively, e.g. for character bound frames. However,
2319 // since there happens way too much here, this temporary object was
2320 // inserted that will be deleted in Remove again (see Bug 55406)
2321 aTempEntries.resize(sal_Int32(nCnt));
2322
2323 while( nCnt-- )
2324 {
2325 delete pDel;
2326 // coverity[use_after_free : FALSE] - pPrev will be reassigned if there will be another iteration to the loop
2327 pDel = pPrev;
2328 sal_uLong nPrevNdIdx = pPrev->GetPos();
2329 BigPtrEntry* pTempEntry = &aTempEntries[sal_Int32(nCnt)];
2330 BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
2331 if( nCnt )
2332 pPrev = BigPtrArray::operator []( nPrevNdIdx - 1 );
2333 // the accessed element can be a naked BigPtrEntry from
2334 // aTempEntries, so the downcast to SwNode* in
2335 // SwNodes::operator[] would be illegal (and unnecessary)
2336 }
2337 nDelPos = SwNodeOffset(pDel->GetPos() + 1);
2338 }
2339
2340 BigPtrArray::Remove( sal_Int32(nDelPos), sal_Int32(nSz) );
2341}
2342
2343void SwNodes::InsertNode( SwNode* pNode, const SwNodeIndex& rPos )
2344{
2345 BigPtrEntry* pIns = pNode;
2346 BigPtrArray::Insert( pIns, sal_Int32(rPos.GetIndex()) );
2347}
2348
2350{
2351 BigPtrEntry* pIns = pNode;
2352 BigPtrArray::Insert( pIns, sal_Int32(nPos) );
2353}
2354
2355// ->#112139#
2357{
2358 if (nullptr != pNode)
2359 {
2360 SwNodeIndex aIdx(*pNode);
2361
2362 if (aIdx <= (*this)[SwNodeOffset(0)]->EndOfSectionIndex())
2363 pNode = (*this)[SwNodeOffset(0)];
2364 else
2365 {
2366 while ((*this)[SwNodeOffset(0)] != pNode->StartOfSectionNode())
2367 pNode = pNode->StartOfSectionNode();
2368 }
2369 }
2370
2371 return pNode;
2372}
2373
2375{
2377}
2378
2380{
2381 return this == &m_rMyDoc.GetNodes();
2382}
2383
2385{
2386 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwNodes"));
2387 for (SwNodeOffset i(0); i < Count(); ++i)
2388 (*this)[i]->dumpAsXml(pWriter);
2389 (void)xmlTextWriterEndElement(pWriter);
2390}
2391
2392/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
struct _xmlTextWriter * xmlTextWriterPtr
std::unique_ptr< BlockInfo *[]> m_ppInf
block info
Definition: bparr.hxx:69
void Insert(BigPtrEntry *p, sal_Int32 pos)
Definition: bparr.cxx:201
void Remove(sal_Int32 pos, sal_Int32 n=1)
Definition: bparr.cxx:306
void Replace(sal_Int32 pos, BigPtrEntry *p)
Definition: bparr.cxx:390
sal_uInt16 Index2Block(sal_Int32) const
block search
Definition: bparr.cxx:91
sal_Int32 m_nSize
number of elements
Definition: bparr.hxx:70
BigPtrEntry * operator[](sal_Int32) const
Definition: bparr.cxx:82
void Move(sal_Int32 from, sal_Int32 to)
Definition: bparr.cxx:70
sal_Int32 GetPos() const
Definition: bparr.hxx:98
virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart)=0
Split a node at rPos (implemented only for TextNode).
virtual bool SetFieldsDirty(bool b, const SwNode *pChk, SwNodeOffset nLen)=0
virtual void InsDelFieldInFieldLst(bool bIns, const SwTextField &rField)=0
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
virtual bool IsUndoNodes(SwNodes const &rNodes) const =0
void Broadcast(const SfxHint &rHint)
bool InvalidateNumRule()
Invalidates NumRule at the node.
Definition: node.cxx:1189
void DelFrames(SwRootFrame const *pLayout)
Method deletes all views of document for the node.
Definition: node.cxx:1404
void ChkCondColl(const SwTextFormatColl *pColl=nullptr)
Definition: node.cxx:1978
void IncRefCnt()
Definition: ddefld.hxx:97
void DecRefCnt()
Definition: ddefld.hxx:98
Definition: doc.hxx:188
SwNumRule * FindNumRulePtr(const OUString &rName) const
Definition: docnum.cxx:2473
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
SwNodes & GetNodes()
Definition: doc.hxx:408
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
SwDocShell * GetDocShell()
Definition: doc.hxx:1351
sal_uInt16 MakeNumRule(const OUString &rName, const SwNumRule *pCpy=nullptr, bool bBroadcast=false, const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode=SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
Definition: docnum.cxx:2507
Ends a section of nodes in the document model.
Definition: node.hxx:344
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:242
SwFieldIds Which() const
Definition: fldbas.hxx:273
SwFieldType * GetTyp() const
Definition: fldbas.hxx:398
bool IsFieldInDoc() const
Definition: atrfld.cxx:419
const SwField * GetField() const
Definition: fmtfld.hxx:116
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
Style of a layout element.
Definition: frmfmt.hxx:61
Marks a character position inside a document model node.
Definition: index.hxx:34
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
sal_Int32 GetIndex() const
Definition: index.hxx:91
Layout frame for SwNoTextNode, i.e. graphics and OLE nodes (including charts).
Definition: ndnotxt.hxx:30
Marks a node in the document model.
Definition: ndindex.hxx:31
const SwNodes & GetNodes() const
Definition: ndindex.hxx:165
SwNode & GetNode() const
Definition: ndindex.hxx:128
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:161
SwNodeIndex aStart
Definition: ndindex.hxx:141
SwNodeIndex aEnd
Definition: ndindex.hxx:142
Base class of the Writer document model elements.
Definition: node.hxx:83
SwStartNode * GetStartNode()
Definition: node.hxx:603
sal_uInt16 GetSectionLevel() const
Returns the section level at the position given by aIndex.
Definition: node.cxx:271
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:871
SwSectionNode * GetSectionNode()
Definition: node.hxx:619
SwNodeOffset GetIndex() const
Definition: node.hxx:292
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:198
SwStartNode * m_pStartOfSection
Definition: node.hxx:114
bool IsNoTextNode() const
Definition: node.hxx:660
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:705
bool IsContentNode() const
Definition: node.hxx:640
SwDoc & GetDoc()
Definition: node.hxx:213
bool IsEndNode() const
Definition: node.hxx:644
bool IsStartNode() const
Definition: node.hxx:636
SwNodeOffset StartOfSectionIndex() const
Definition: node.hxx:685
bool IsSectionNode() const
Definition: node.hxx:656
bool IsTableNode() const
Definition: node.hxx:652
bool IsTextNode() const
Definition: node.hxx:648
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:358
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:985
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:133
Merge GetRedlineMergeFlag() const
Definition: node.hxx:99
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:689
SwContentNode * GetContentNode()
Definition: node.hxx:627
SwTableNode * GetTableNode()
Definition: node.hxx:611
SwNodeType GetNodeType() const
Definition: node.hxx:146
SwEndNode * GetEndNode()
Definition: node.hxx:595
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:694
void ForEach(FnForEach_SwNodes fnForEach, void *pArgs=nullptr)
Definition: ndarr.hxx:142
SwNode * DocumentSectionStartNode(SwNode *pNode) const
Definition: nodes.cxx:2356
friend class SwNodeIndex
Definition: ndarr.hxx:93
void MoveRange(SwPaM &, SwPosition &, SwNodes &rNodes)
move a range
Definition: nodes.cxx:1435
SwNode * DocumentSectionEndNode(SwNode *pNode) const
Definition: nodes.cxx:2374
bool m_bInNodesDel
In Case of recursive calling.
Definition: ndarr.hxx:111
static void GoEndOfSection(SwNodeIndex *)
Definition: nodes.cxx:1294
std::unique_ptr< SwOutlineNodes > m_pOutlineNodes
Array of all outline nodes.
Definition: ndarr.hxx:109
bool m_bInDelUpdOutline
Flag for updating of Outline.
Definition: ndarr.hxx:113
SwNode * m_pEndOfAutotext
Definition: ndarr.hxx:106
void dumpAsXml(xmlTextWriterPtr pWriter) const
Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by...
Definition: nodes.cxx:2384
void SectionUp(SwNodeRange *)
increase level of the given range
Definition: nodes.cxx:966
void UpdateOutlineIdx(const SwNode &)
Update all OutlineNodes starting from Node.
Definition: ndnum.cxx:77
void DelDummyNodes(const SwNodeRange &rRg)
Definition: nodes.cxx:1875
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:162
std::unique_ptr< SwNode > m_pEndOfContent
Definition: ndarr.hxx:107
SwNode * FindPrvNxtFrameNode(SwNodeIndex &rFrameIdx, const SwNode *pEnd, SwRootFrame const *pLayout=nullptr) const
Search previous / next content node or table node with frames.
Definition: nodes.cxx:2037
bool IsDocNodes() const
Is the NodesArray the regular one of Doc? (and not the UndoNds, ...) Implementation in doc....
Definition: nodes.cxx:2379
void ChgNode(SwNodeIndex const &rDelPos, SwNodeOffset nSize, SwNodeIndex &rInsPos, bool bNewFrames)
Definition: nodes.cxx:124
void Delete(const SwNodeIndex &rPos, SwNodeOffset nNodes=SwNodeOffset(1))
delete nodes
Definition: nodes.cxx:1085
SwNode * m_pEndOfInserts
These are the fixed ranges.
Definition: ndarr.hxx:105
static SwStartNode * MakeEmptySection(const SwNodeIndex &rIdx, SwStartNodeType=SwNormalStartNode)
Create an empty section of Start- and EndNote.
Definition: nodes.cxx:1887
void CopyNodes(const SwNodeRange &, const SwNodeIndex &, bool bNewFrames, bool bTableInsDummyNode=false) const
Definition: nodes.cxx:1662
void RemoveNode(SwNodeOffset nDelPos, SwNodeOffset nLen, bool bDel)
Definition: nodes.cxx:2246
SwNode * m_pEndOfPostIts
Definition: ndarr.hxx:105
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1317
static void GoStartOfSection(SwNodeIndex *)
Definition: nodes.cxx:1276
SwNode & GetEndOfRedlines() const
Section for all Redlines.
Definition: ndarr.hxx:157
static sal_uInt16 GetSectionLevel(const SwNodeIndex &rIndex)
get section level at the given position
Definition: nodes.cxx:1268
SwTextNode * MakeTextNode(const SwNodeIndex &rWhere, SwTextFormatColl *pColl, bool bNewFrames=true)
Implementations of "Make...Node" are in the given .cxx-files.
Definition: ndtxt.cxx:103
SwStartNode * MakeTextSection(const SwNodeIndex &rWhere, SwStartNodeType eSttNdTyp, SwTextFormatColl *pColl)
Definition: nodes.cxx:1895
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1300
void SectionDown(SwNodeRange *pRange, SwStartNodeType=SwNormalStartNode)
create a start/end section pair
Definition: nodes.cxx:912
void DelNodes(const SwNodeIndex &rStart, SwNodeOffset nCnt=SwNodeOffset(1))
Delete a number of nodes.
Definition: nodes.cxx:1339
SwNode * m_pEndOfRedlines
Definition: ndarr.hxx:106
void InsertNode(SwNode *pNode, const SwNodeIndex &rPos)
Definition: nodes.cxx:2343
SwContentNode * GoNextSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true) const
Go to next content-node that is not protected or hidden (Both set FALSE ==> GoNext/GoPrevious!...
Definition: nodes.cxx:1918
bool MoveNodes(const SwNodeRange &, SwNodes &rNodes, const SwNodeIndex &, bool bNewFrames=true)
move the node pointer
Definition: nodes.cxx:409
SwNodes(SwNodes const &)=delete
friend class SwStartNode
Definition: ndarr.hxx:94
SwNode & GetEndOfInserts() const
Section for all footnotes.
Definition: ndarr.hxx:153
~SwNodes()
Destructor.
Definition: nodes.cxx:93
SwDoc & GetDoc()
Which Doc contains the nodes-array?
Definition: ndarr.hxx:301
SwDoc & m_rMyDoc
This Doc contains the nodes-array.
Definition: ndarr.hxx:103
SwNodeIndex * m_vIndices
ring of all indices on nodes.
Definition: ndarr.hxx:97
static SwContentNode * GoPrevSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true)
Definition: nodes.cxx:1970
static void SectionUpDown(const SwNodeIndex &aStart, const SwNodeIndex &aEnd)
correct indices after movement
Definition: nodes.cxx:1037
SwNodeOffset Count() const
Definition: ndarr.hxx:141
void SetInvalidRule(bool bFlag)
Definition: number.cxx:957
const OUString & GetName() const
Definition: numrule.hxx:224
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:138
const SwPosition * End() const
Definition: pam.hxx:218
void DeleteMark()
Definition: pam.hxx:178
const SwPosition * Start() const
Definition: pam.hxx:213
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:206
This class is internal, used only during DocumentContentOperationsManager::CopyWithFlyInFly(),...
Definition: node.hxx:589
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
bool HasMergedParas() const
Definition: rootfrm.hxx:425
void NodesArrChgd()
Set pointer in format of section on itself.
Definition: ndsect.cxx:1350
const SwSection & GetSection() const
Definition: node.hxx:551
void DelFrames(SwRootFrame const *pLayout=nullptr, bool bForce=false)
Method deletes all views of document for the node.
Definition: ndsect.cxx:1193
void MakeFramesForAdjacentContentNode(const SwNodeIndex &rIdx)
Method creates all views of document for the previous node.
Definition: ndsect.cxx:1050
void MakeOwnFrames(SwNodeIndex *pIdxBehind, SwNodeIndex *pEnd=nullptr)
Creates the frms for the SectionNode (i.e.
Definition: ndsect.cxx:1173
bool IsProtectFlag() const
Definition: section.hxx:187
bool IsHiddenFlag() const
Definition: section.hxx:186
bool IsHidden() const
Definition: section.hxx:177
bool CalcHiddenFlag() const
Definition: section.cxx:314
Starts a section of nodes in the document model.
Definition: node.hxx:314
SwEndNode * m_pEndOfSection
Definition: node.hxx:319
SwStartNodeType GetStartNodeType() const
Definition: node.hxx:330
const SwTable & GetTable() const
Definition: node.hxx:506
void MakeOwnFrames(SwNodeIndex *pIdxBehind)
Creates the frms for the table node (i.e. the TabFrames).
Definition: ndtbl.cxx:2396
void RemoveRedlines()
Definition: ndtbl.cxx:2497
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndtbl.cxx:2439
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:204
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
const SfxPoolItem & GetAttr() const
Definition: txatbase.hxx:167
sal_uInt16 Which() const
Definition: txatbase.hxx:116
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:199
Represents the style of a paragraph.
Definition: fmtcol.hxx:59
void ChgTextNode(SwTextNode *const pNode)
Definition: txtatr2.cxx:302
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:84
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:276
void CutText(SwTextNode *const pDest, const SwIndex &rStart, const sal_Int32 nLen)
Definition: ndtxt.cxx:2416
void DeleteAttribute(SwTextAttr *const pTextAttr)
delete the attribute pTextAttr
Definition: thints.cxx:1739
bool IsOutline() const
Returns if this text node is an outline.
Definition: ndtxt.cxx:4031
void RemoveFromList()
Definition: ndtxt.cxx:4395
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2833
void AddToList()
Definition: ndtxt.cxx:4310
SwTextNode * SplitContentNode(const SwPosition &, std::function< void(SwTextNode *, sw::mark::RestoreMode, bool AtStart)> const *pContentIndexRestore)
Definition: ndtxt.cxx:413
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:228
void CopyCollFormat(SwTextNode &rDestNd, bool bUndoForChgFormatColl=true)
Copy collection with all auto formats to dest-node.
Definition: ndcopy.cxx:336
const OUString & GetText() const
Definition: ndtxt.hxx:220
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:865
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:68
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
size_t Count() const
Definition: ndhints.hxx:142
SvtBroadcaster & GetNotifier()
Definition: calbck.hxx:101
ring_container GetRingContainer()
Definition: ring.hxx:240
static SwNode * GetStartNode(SwOutlineNodes const *pOutlNds, int nOutlineLevel, SwOutlineNodes::size_type *nOutl)
Definition: docglbl.cxx:89
std::deque< AttacherIndex_Impl > aIndex
constexpr TypedWhichId< SwFormatFootnote > RES_TXTATR_FTN(59)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(60)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(58)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_METAFIELD(49)
constexpr TypedWhichId< SwFormatRefMark > RES_TXTATR_REFMARK(RES_TXTATR_WITHEND_BEGIN)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_META(48)
constexpr TypedWhichId< SwConditionTextFormatColl > RES_CONDTXTFMTCOLL(160)
constexpr TypedWhichId< SwTOXMark > RES_TXTATR_TOXMARK(47)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_INPUTFIELD(55)
sal_Int32 nIndex
void * p
sal_Int64 n
sal_uInt16 nPos
int i
bool HasNumberingWhichNeedsLayoutUpdate(const SwTextNode &rTextNode)
Decides if rTextNode has a numbering which has layout-level values (e.g.
Definition: ndtxt.cxx:948
bool(* FnForEach_SwNodes)(SwNode *, void *pArgs)
Definition: ndarr.hxx:69
SwStartNodeType
Definition: ndtyp.hxx:51
@ SwNormalStartNode
Definition: ndtyp.hxx:52
@ Table
SwTableNode is derived from SwStartNode.
@ Section
SwSectionNode is derived from SwStartNode.
o3tl::strong_int< sal_Int32, struct Tag_SwNodeOffset > SwNodeOffset
Definition: nodeoffset.hxx:16
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
static sal_uInt16 HighestLevel(SwNodes &rNodes, const SwNodeRange &rRange)
Calculate the highest level in a range.
Definition: nodes.cxx:1421
std::vector< SwStartNode * > SwStartNodePointers
Definition: nodes.cxx:49
static bool IsInsertOutline(SwNodes const &rNodes, SwNodeOffset const nIndex)
Definition: nodes.cxx:114
static bool lcl_HighestLevel(SwNode *pNode, void *pPara)
Definition: nodes.cxx:1402
bool CheckNodesRange(const SwNodeIndex &rStt, const SwNodeIndex &rEnd, bool bChkSection)
Check if the given range is inside one of the defined top-level sections.
Definition: pam.cxx:258
sal_uIntPtr sal_uLong
Marks a position in the document model.
Definition: pam.hxx:37
SwNodeIndex nNode
Definition: pam.hxx:38
SwIndex nContent
Definition: pam.hxx:39