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