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