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