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 
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  return;
353 
354  // get the frames:
355  SwNodeIndex aIdx( *pPrevInsNd, 1 );
356  SwNodeIndex aFrameNdIdx( aIdx );
357  SwNode* pFrameNd = rNds.FindPrvNxtFrameNode( aFrameNdIdx,
358  rNds[ rInsPos.GetIndex() - 1 ] );
359 
360  if( !pFrameNd )
361  return;
362 
363  while( aIdx != rInsPos )
364  {
365  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
366  if( pCNd )
367  {
368  if( pFrameNd->IsTableNode() )
369  static_cast<SwTableNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(aIdx);
370  else if( pFrameNd->IsSectionNode() )
371  static_cast<SwSectionNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(aIdx);
372  else
373  static_cast<SwContentNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(*pCNd);
374  pFrameNd = pCNd;
375  }
376  ++aIdx;
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  // tdf#132326 do not let frames survive in undo nodes
667  if (!GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNodes))
668  {
669  bNewFrames = false;
670  }
671  }
672  }
673  }
674  break;
675 
676  case SwNodeType::Section:
677  if( !nLevel &&
678  GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNodes))
679  {
680  // here, a SectionDummyNode needs to be inserted at the current position
681  if( nInsPos ) // move everything until here
682  {
683  // delete and copy. CAUTION: all indices after
684  // "aRg.aEnd+1" will be moved as well!
685  SwNodeIndex aSwIndex( aRg.aEnd, 1 );
686  ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
687  aIdx -= nInsPos;
688  nInsPos = 0;
689  }
690  new SwPlaceholderNode(aIdx);
691  --aRg.aEnd;
692  --aIdx;
693  break;
694  }
695  [[fallthrough]];
696  case SwNodeType::Table:
697  case SwNodeType::Start:
698  {
699  // empty section -> nothing to do
700  // and only if it's a top level section
701  if( !nInsPos && !nLevel )
702  {
703  --aRg.aEnd;
704  break;
705  }
706 
707  if( !nLevel ) // level is decreasing
708  {
709  // create decrease
710  SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 );
711  SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx,
713  static_cast<SwStartNode*>(pCurrentNode)->GetStartNodeType() );
714 
715  --aTmpSIdx;
716 
717  SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd );
718  new SwEndNode( aTmpEIdx, *pTmpStt );
719  --aTmpEIdx;
720  ++aTmpSIdx;
721 
722  // set correct StartOfSection
723  ++aRg.aEnd;
724  {
725  SwNodeIndex aCntIdx( aRg.aEnd );
726  for( sal_uLong n = 0; n < nInsPos; n++, ++aCntIdx)
727  aCntIdx.GetNode().m_pStartOfSection = pTmpStt;
728  }
729 
730  // also set correct StartNode for all decreased nodes
731  while( aTmpSIdx < aTmpEIdx )
732  if( nullptr != (( pCurrentNode = &aTmpEIdx.GetNode())->GetEndNode()) )
733  aTmpEIdx = pCurrentNode->StartOfSectionIndex();
734  else
735  {
736  pCurrentNode->m_pStartOfSection = pTmpStt;
737  --aTmpEIdx;
738  }
739 
740  --aIdx; // after the inserted StartNode
741  --aRg.aEnd; // before StartNode
742  // copy array. CAUTION: all indices after
743  // "aRg.aEnd+1" will be moved as well!
744  SwNodeIndex aSwIndex( aRg.aEnd, 1 );
745  ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
746  aIdx -= nInsPos+1;
747  nInsPos = 0;
748  }
749  else // all nodes between StartNode and EndNode were moved
750  {
751  OSL_ENSURE( pCurrentNode == aSttNdStack[nLevel] ||
752  ( pCurrentNode->IsStartNode() &&
753  aSttNdStack[nLevel]->IsSectionNode()),
754  "wrong StartNode" );
755 
756  SwNodeIndex aSwIndex( aRg.aEnd, 1 );
757  ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
758  aIdx -= nInsPos+1; // before inserted StartNode
759  nInsPos = 0;
760 
761  // remove pointer from node array
762  RemoveNode( aRg.aEnd.GetIndex(), 1, true );
763  --aRg.aEnd;
764 
765  SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode();
766  if( pSectNd && !--nSectNdCnt )
767  {
768  SwNodeIndex aTmp( *pSectNd );
769  pSectNd->MakeOwnFrames(&aTmp);
770  bNewFrames = bSaveNewFrames;
771  }
772  aSttNdStack.erase( aSttNdStack.begin() + nLevel ); // remove from stack
773  nLevel--;
774  }
775 
776  // delete all resulting empty start/end node pairs
777  SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode();
778  if( pTmpNode && SwNodeType::Start == (pCurrentNode = &aRg.aEnd.GetNode())
779  ->GetNodeType() && pCurrentNode->StartOfSectionIndex() &&
780  pTmpNode->StartOfSectionNode() == pCurrentNode )
781  {
782  DelNodes( aRg.aEnd, 2 );
783  --aRg.aEnd;
784  }
785  }
786  break;
787 
788  case SwNodeType::Text:
789  //Add special function to text node.
790  {
791  if( bNewFrames && pCurrentNode->GetContentNode() )
792  static_cast<SwContentNode*>(pCurrentNode)->DelFrames(nullptr);
793  pCurrentNode->m_pStartOfSection = aSttNdStack[ nLevel ];
794  nInsPos++;
795  --aRg.aEnd;
796  }
797  break;
798  case SwNodeType::Grf:
799  case SwNodeType::Ole:
800  {
801  if( bNewFrames && pCurrentNode->GetContentNode() )
802  static_cast<SwContentNode*>(pCurrentNode)->DelFrames(nullptr);
803 
804  pCurrentNode->m_pStartOfSection = aSttNdStack[ nLevel ];
805  nInsPos++;
806  --aRg.aEnd;
807  }
808  break;
809 
811  if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
812  {
813  if( &rNodes == this ) // inside UndoNodesArray
814  {
815  // move everything
816  pCurrentNode->m_pStartOfSection = aSttNdStack[ nLevel ];
817  nInsPos++;
818  }
819  else // move into "normal" node array
820  {
821  // than a SectionNode (start/end) is needed at the current
822  // InsPos; if so skip it, otherwise ignore current node
823  if( nInsPos ) // move everything until here
824  {
825  // delete and copy. CAUTION: all indices after
826  // "aRg.aEnd+1" will be moved as well!
827  SwNodeIndex aSwIndex( aRg.aEnd, 1 );
828  ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
829  aIdx -= nInsPos;
830  nInsPos = 0;
831  }
832  SwNode* pTmpNd = &aIdx.GetNode();
833  if( pTmpNd->IsSectionNode() ||
834  pTmpNd->StartOfSectionNode()->IsSectionNode() )
835  --aIdx; // skip
836  }
837  }
838  else {
839  assert(!"How can this node be in the node array?");
840  }
841  --aRg.aEnd;
842  break;
843 
844  default:
845  assert(!"Unknown node type");
846  break;
847  }
848  }
849 
850  if( nInsPos ) // copy remaining rest
851  {
852  // rest should be ok
853  SwNodeIndex aSwIndex( aRg.aEnd, 1 );
854  ChgNode( aSwIndex, nInsPos, aIdx, bNewFrames );
855  }
856  ++aRg.aEnd; // again, exclusive end
857 
858  // delete all resulting empty start/end node pairs
859  if( ( pCurrentNode = &aRg.aStart.GetNode())->GetStartNode() &&
860  pCurrentNode->StartOfSectionIndex() &&
861  aRg.aEnd.GetNode().GetEndNode() )
862  DelNodes( aRg.aStart, 2 );
863 
864  // initialize numbering update
865  ++aOrigInsPos.aStart;
866  // Moved in same node array? Then call update top down!
867  if( this == &rNodes &&
868  aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() )
869  {
870  UpdateOutlineIdx( aOrigInsPos.aStart.GetNode() );
871  UpdateOutlineIdx( aRg.aEnd.GetNode() );
872  }
873  else
874  {
875  UpdateOutlineIdx( aRg.aEnd.GetNode() );
876  rNodes.UpdateOutlineIdx( aOrigInsPos.aStart.GetNode() );
877  }
878 
879  return true;
880 }
881 
899 {
900  if( pRange->aStart >= pRange->aEnd ||
901  pRange->aEnd >= Count() ||
902  !::CheckNodesRange(pRange->aStart, pRange->aEnd, false))
903  {
904  return;
905  }
906 
907  // If the beginning of a range is before or at a start node position, so
908  // delete it, otherwise empty S/E or E/S nodes would be created.
909  // For other nodes, create a new start node.
910  SwNode * pCurrentNode = &pRange->aStart.GetNode();
911  SwNodeIndex aTmpIdx( *pCurrentNode->StartOfSectionNode() );
912 
913  if( pCurrentNode->GetEndNode() )
914  DelNodes( pRange->aStart ); // prevent empty section
915  else
916  {
917  // insert a new StartNode
918  SwNode* pSttNd = new SwStartNode( pRange->aStart, SwNodeType::Start, eSttNdTyp );
919  pRange->aStart = *pSttNd;
920  aTmpIdx = pRange->aStart;
921  }
922 
923  // If the end of a range is before or at a StartNode, so delete it,
924  // otherwise empty S/E or E/S nodes would be created.
925  // For other nodes, insert a new end node.
926  --pRange->aEnd;
927  if( pRange->aEnd.GetNode().GetStartNode() )
928  DelNodes( pRange->aEnd );
929  else
930  {
931  ++pRange->aEnd;
932  // insert a new EndNode
933  new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() );
934  }
935  --pRange->aEnd;
936 
937  SectionUpDown( aTmpIdx, pRange->aEnd );
938 }
939 
953 {
954  if( pRange->aStart >= pRange->aEnd ||
955  pRange->aEnd >= Count() ||
956  !::CheckNodesRange(pRange->aStart, pRange->aEnd, false) ||
957  ( HighestLevel( *this, *pRange ) <= 1 ))
958  {
959  return;
960  }
961 
962  // If the beginning of a range is before or at a start node position, so
963  // delete it, otherwise empty S/E or E/S nodes would be created.
964  // For other nodes, create a new start node.
965  SwNode * pCurrentNode = &pRange->aStart.GetNode();
966  SwNodeIndex aIdx( *pCurrentNode->StartOfSectionNode() );
967  if( pCurrentNode->IsStartNode() ) // is StartNode itself
968  {
969  SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode();
970  if (pEndNd && pCurrentNode == pEndNd->m_pStartOfSection)
971  {
972  // there was a pairwise reset, adjust only those in the range
973  SwStartNode* pTmpSttNd = pCurrentNode->m_pStartOfSection;
974  RemoveNode( pRange->aStart.GetIndex(), 1, true );
975  RemoveNode( pRange->aEnd.GetIndex(), 1, true );
976 
977  SwNodeIndex aTmpIdx( pRange->aStart );
978  while( aTmpIdx < pRange->aEnd )
979  {
980  pCurrentNode = &aTmpIdx.GetNode();
981  pCurrentNode->m_pStartOfSection = pTmpSttNd;
982  if( pCurrentNode->IsStartNode() )
983  aTmpIdx = pCurrentNode->EndOfSectionIndex() + 1;
984  else
985  ++aTmpIdx;
986  }
987  return ;
988  }
989  DelNodes( pRange->aStart );
990  }
991  else if( aIdx == pRange->aStart.GetIndex()-1 ) // before StartNode
992  DelNodes( aIdx );
993  else
994  new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() );
995 
996  // If the end of a range is before or at a StartNode, so delete it,
997  // otherwise empty S/E or E/S nodes would be created.
998  // For other nodes, insert a new end node.
999  SwNodeIndex aTmpIdx( pRange->aEnd );
1000  if( pRange->aEnd.GetNode().IsEndNode() )
1001  DelNodes( pRange->aEnd );
1002  else
1003  {
1004  new SwStartNode( pRange->aEnd );
1005 /*?? which NodeType ??*/
1006  aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode();
1007  --pRange->aEnd;
1008  }
1009 
1010  SectionUpDown( aIdx, aTmpIdx );
1011 }
1012 
1023 void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd )
1024 {
1025  SwNodeIndex aTmpIdx( aStart, +1 );
1026  // array forms a stack, holding all StartOfSelections
1027  SwStartNodePointers aSttNdStack;
1028  SwStartNode* pTmp = aStart.GetNode().GetStartNode();
1029  aSttNdStack.push_back( pTmp );
1030 
1031  // loop until the first start node that needs to be change was found
1032  // (the indices are updated from the end node backwards to the start)
1033  for( ;; ++aTmpIdx )
1034  {
1035  SwNode * pCurrentNode = &aTmpIdx.GetNode();
1036  pCurrentNode->m_pStartOfSection = aSttNdStack[ aSttNdStack.size()-1 ];
1037 
1038  if( pCurrentNode->GetStartNode() )
1039  {
1040  pTmp = static_cast<SwStartNode*>(pCurrentNode);
1041  aSttNdStack.push_back( pTmp );
1042  }
1043  else if( pCurrentNode->GetEndNode() )
1044  {
1045  SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.size() - 1 ];
1046  pSttNd->m_pEndOfSection = static_cast<SwEndNode*>(pCurrentNode);
1047  aSttNdStack.pop_back();
1048  if( !aSttNdStack.empty() )
1049  continue; // still enough EndNodes on the stack
1050 
1051  else if( aTmpIdx < aEnd ) // too many StartNodes
1052  // if the end is not reached, yet, get the start of the section above
1053  {
1054  aSttNdStack.insert( aSttNdStack.begin(), pSttNd->m_pStartOfSection );
1055  }
1056  else // finished, as soon as out of the range
1057  break;
1058  }
1059  }
1060 }
1061 
1071 void SwNodes::Delete(const SwNodeIndex &rIndex, sal_uLong nNodes)
1072 {
1073  int nLevel = 0; // level counter
1074  SwNode * pCurrentNode;
1075 
1076  sal_uLong nCnt = Count() - rIndex.GetIndex() - 1;
1077  if( nCnt > nNodes ) nCnt = nNodes;
1078 
1079  if( nCnt == 0 ) // no count -> return
1080  return;
1081 
1082  SwNodeRange aRg( rIndex, 0, rIndex, nCnt-1 );
1083  // check if [rIndex..rIndex + nCnt] is larger than the range
1084  if( ( !aRg.aStart.GetNode().StartOfSectionIndex() &&
1085  !aRg.aStart.GetIndex() ) ||
1086  !::CheckNodesRange(aRg.aStart, aRg.aEnd, false))
1087  {
1088  return;
1089  }
1090 
1091  // if aEnd is not on a ContentNode, search the previous one
1092  while( ( pCurrentNode = &aRg.aEnd.GetNode())->GetStartNode() ||
1093  ( pCurrentNode->GetEndNode() &&
1094  !pCurrentNode->m_pStartOfSection->IsTableNode() ))
1095  --aRg.aEnd;
1096 
1097  nCnt = 0;
1098 //TODO: check/improve comment
1099  // increase start so that we are able to use "<" (using "<=" might cause
1100  // problems if aEnd == aStart and aEnd is deleted, so aEnd <= aStart)
1101  --aRg.aStart;
1102 
1103  bool bSaveInNodesDel = m_bInNodesDel;
1104  m_bInNodesDel = true;
1105  bool bUpdateOutline = false;
1106 
1107  // loop until everything is deleted
1108  while( aRg.aStart < aRg.aEnd )
1109  {
1110  pCurrentNode = &aRg.aEnd.GetNode();
1111 
1112  if( pCurrentNode->GetEndNode() )
1113  {
1114  // delete the whole section?
1115  if( pCurrentNode->StartOfSectionIndex() > aRg.aStart.GetIndex() )
1116  {
1117  SwTableNode* pTableNd = pCurrentNode->m_pStartOfSection->GetTableNode();
1118  if( pTableNd )
1119  pTableNd->DelFrames();
1120 
1121  SwNode *pNd, *pChkNd = pCurrentNode->m_pStartOfSection;
1122  SwOutlineNodes::size_type nIdxPos;
1123  do {
1124  pNd = &aRg.aEnd.GetNode();
1125 
1126  if( pNd->IsTextNode() )
1127  {
1128  SwTextNode *const pTextNode(pNd->GetTextNode());
1129  if (pTextNode->IsOutline() &&
1130  m_pOutlineNodes->Seek_Entry( pNd, &nIdxPos ))
1131  {
1132  // remove outline indices
1133  m_pOutlineNodes->erase(nIdxPos);
1134  bUpdateOutline = true;
1135  }
1136  pTextNode->InvalidateNumRule();
1137  }
1138  else if( pNd->IsEndNode() &&
1139  pNd->m_pStartOfSection->IsTableNode() )
1140  static_cast<SwTableNode*>(pNd->m_pStartOfSection)->DelFrames();
1141 
1142  --aRg.aEnd;
1143  nCnt++;
1144 
1145  } while( pNd != pChkNd );
1146  }
1147  else
1148  {
1149  RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, true ); // delete
1150  nCnt = 0;
1151  --aRg.aEnd; // before the EndNode
1152  nLevel++;
1153  }
1154  }
1155  else if( pCurrentNode->GetStartNode() ) // found StartNode
1156  {
1157  if( nLevel == 0 ) // decrease one level
1158  {
1159  if( nCnt )
1160  {
1161  // now delete array
1162  ++aRg.aEnd;
1163  RemoveNode( aRg.aEnd.GetIndex(), nCnt, true );
1164  nCnt = 0;
1165  }
1166  }
1167  else // remove all nodes between start and end node (incl. both)
1168  {
1169  RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, true ); // delete array
1170  nCnt = 0;
1171  nLevel--;
1172  }
1173 
1174  // after deletion, aEnd might point to an EndNode...
1175  // delete all empty start/end node pairs
1176  SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1177  --aRg.aEnd;
1178  while( pTmpNode &&
1179  ( pCurrentNode = &aRg.aEnd.GetNode())->GetStartNode() &&
1180  pCurrentNode->StartOfSectionIndex() )
1181  {
1182  // remove end and start node
1183  DelNodes( aRg.aEnd, 2 );
1184  pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1185  --aRg.aEnd;
1186  }
1187  }
1188  else // "normal" node, so insert into TmpArray
1189  {
1190  SwTextNode* pTextNd = pCurrentNode->GetTextNode();
1191  if( pTextNd )
1192  {
1193  if( pTextNd->IsOutline())
1194  {
1195  // delete outline indices
1196  m_pOutlineNodes->erase( pTextNd );
1197  bUpdateOutline = true;
1198  }
1199  pTextNd->InvalidateNumRule();
1200  }
1201  else if( pCurrentNode->IsContentNode() )
1202  static_cast<SwContentNode*>(pCurrentNode)->InvalidateNumRule();
1203 
1204  --aRg.aEnd;
1205  nCnt++;
1206  }
1207  }
1208 
1209  ++aRg.aEnd;
1210  if( nCnt != 0 )
1211  RemoveNode( aRg.aEnd.GetIndex(), nCnt, true ); // delete the rest
1212 
1213  // delete all empty start/end node pairs
1214  while( aRg.aEnd.GetNode().GetEndNode() &&
1215  ( pCurrentNode = &aRg.aStart.GetNode())->GetStartNode() &&
1216  pCurrentNode->StartOfSectionIndex() )
1217  // but none of the holy 5. (???)
1218  {
1219  DelNodes( aRg.aStart, 2 ); // delete start and end node
1220  --aRg.aStart;
1221  }
1222 
1223  m_bInNodesDel = bSaveInNodesDel;
1224 
1225  if( !m_bInNodesDel )
1226  {
1227  // update numbering
1228  if( bUpdateOutline || m_bInDelUpdOutline )
1229  {
1230  UpdateOutlineIdx( aRg.aEnd.GetNode() );
1231  m_bInDelUpdOutline = false;
1232  }
1233 
1234  }
1235  else
1236  {
1237  if( bUpdateOutline )
1238  m_bInDelUpdOutline = true;
1239  }
1240 }
1241 
1251 sal_uInt16 SwNodes::GetSectionLevel(const SwNodeIndex &rIdx)
1252 {
1253  // special treatment for 1st Node
1254  if(rIdx == 0) return 1;
1255  // no recursion! This calls a SwNode::GetSectionLevel (missing "s")
1256  return rIdx.GetNode().GetSectionLevel();
1257 }
1258 
1260 {
1261  // after the next start node
1262  SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 );
1263 
1264  // If index points to no ContentNode, then go to one.
1265  // If there is no further available, do not change the index' position!
1266  while( !aTmp.GetNode().IsContentNode() )
1267  { // go from this StartNode (can only be one) to its end
1268  if( *pIdx <= aTmp )
1269  return; // ERROR: already after the section
1270  aTmp = aTmp.GetNode().EndOfSectionIndex()+1;
1271  if( *pIdx <= aTmp )
1272  return; // ERROR: already after the section
1273  }
1274  (*pIdx) = aTmp; // is on a ContentNode
1275 }
1276 
1278 {
1279  if( !pIdx->GetNode().IsEndNode() )
1280  (*pIdx) = *pIdx->GetNode().EndOfSectionNode();
1281 }
1282 
1284 {
1285  if( pIdx->GetIndex() >= Count() - 1 )
1286  return nullptr;
1287 
1288  SwNodeIndex aTmp(*pIdx, +1);
1289  SwNode* pNd = nullptr;
1290  while( aTmp < Count()-1 && !( pNd = &aTmp.GetNode())->IsContentNode() )
1291  ++aTmp;
1292 
1293  if( aTmp == Count()-1 )
1294  pNd = nullptr;
1295  else
1296  (*pIdx) = aTmp;
1297  return static_cast<SwContentNode*>(pNd);
1298 }
1299 
1301 {
1302  if( !pIdx->GetIndex() )
1303  return nullptr;
1304 
1305  SwNodeIndex aTmp( *pIdx, -1 );
1306  SwNode* pNd = nullptr;
1307  while( aTmp.GetIndex() && !( pNd = &aTmp.GetNode())->IsContentNode() )
1308  --aTmp;
1309 
1310  if( !aTmp.GetIndex() )
1311  pNd = nullptr;
1312  else
1313  (*pIdx) = aTmp;
1314  return static_cast<SwContentNode*>(pNd);
1315 }
1316 
1322 void SwNodes::DelNodes( const SwNodeIndex & rStart, sal_uLong nCnt )
1323 {
1324  sal_uLong nSttIdx = rStart.GetIndex();
1325 
1326  if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 )
1327  {
1328  // The whole nodes array will be destroyed, you're in the Doc's DTOR!
1329  // The initial start/end nodes should be only destroyed in the SwNodes' DTOR!
1330  SwNode* aEndNdArr[] = { m_pEndOfContent.get(),
1333  nullptr
1334  };
1335 
1336  SwNode** ppEndNdArr = aEndNdArr;
1337  while( *ppEndNdArr )
1338  {
1339  nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1;
1340  sal_uLong nEndIdx = (*ppEndNdArr)->GetIndex();
1341 
1342  if( nSttIdx != nEndIdx )
1343  RemoveNode( nSttIdx, nEndIdx - nSttIdx, true );
1344 
1345  ++ppEndNdArr;
1346  }
1347  }
1348  else
1349  {
1350  int bUpdateNum = 0;
1351  for( sal_uLong n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n )
1352  {
1353  SwNode* pNd = (*this)[ n ];
1354 
1355  if (pNd->IsTextNode() && pNd->GetTextNode()->IsOutline())
1356  {
1357  // remove the outline indices
1358  SwOutlineNodes::size_type nIdxPos;
1359  if( m_pOutlineNodes->Seek_Entry( pNd, &nIdxPos ))
1360  {
1361  m_pOutlineNodes->erase(nIdxPos);
1362  bUpdateNum = 1;
1363  }
1364  }
1365  if( pNd->IsContentNode() )
1366  {
1367  static_cast<SwContentNode*>(pNd)->InvalidateNumRule();
1368  static_cast<SwContentNode*>(pNd)->DelFrames(nullptr);
1369  }
1370  }
1371  RemoveNode( nSttIdx, nCnt, true );
1372 
1373  // update numbering
1374  if( bUpdateNum )
1375  UpdateOutlineIdx( rStart.GetNode() );
1376  }
1377 }
1378 
1379 namespace {
1380 
1381 struct HighLevel
1382 {
1383  sal_uInt16 nLevel, nTop;
1384  explicit HighLevel( sal_uInt16 nLv ) : nLevel( nLv ), nTop( nLv ) {}
1385 };
1386 
1387 }
1388 
1389 static bool lcl_HighestLevel( const SwNodePtr& rpNode, void * pPara )
1390 {
1391  HighLevel * pHL = static_cast<HighLevel*>(pPara);
1392  if( rpNode->GetStartNode() )
1393  pHL->nLevel++;
1394  else if( rpNode->GetEndNode() )
1395  pHL->nLevel--;
1396  if( pHL->nTop > pHL->nLevel )
1397  pHL->nTop = pHL->nLevel;
1398  return true;
1399 
1400 }
1401 
1408 sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1409 {
1410  HighLevel aPara( SwNodes::GetSectionLevel( rRange.aStart ));
1411  rNodes.ForEach( rRange.aStart, rRange.aEnd, lcl_HighestLevel, &aPara );
1412  return aPara.nTop;
1413 
1414 }
1415 
1422 void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
1423 {
1424  SwPosition * const pStt = rPam.Start();
1425  SwPosition * const pEnd = rPam.End();
1426 
1427  if( !rPam.HasMark() || *pStt >= *pEnd )
1428  return;
1429 
1430  if( this == &rNodes && *pStt <= rPos && rPos < *pEnd )
1431  return;
1432 
1433  SwNodeIndex aEndIdx( pEnd->nNode );
1434  SwNodeIndex aSttIdx( pStt->nNode );
1435  SwTextNode *const pSrcNd = aSttIdx.GetNode().GetTextNode();
1436  SwTextNode * pDestNd = rPos.nNode.GetNode().GetTextNode();
1437  bool bSplitDestNd = true;
1438  bool bCopyCollFormat = pDestNd && pDestNd->GetText().isEmpty();
1439 
1440  if( pSrcNd )
1441  {
1442  // if the first node is a TextNode, then there must
1443  // be also a TextNode in the NodesArray to store the content
1444  if( !pDestNd )
1445  {
1446  pDestNd = rNodes.MakeTextNode( rPos.nNode, pSrcNd->GetTextColl() );
1447  --rPos.nNode;
1448  rPos.nContent.Assign( pDestNd, 0 );
1449  bCopyCollFormat = true;
1450  }
1451  bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() ||
1452  pEnd->nNode.GetNode().IsTextNode();
1453 
1454  // move the content into the new node
1455  bool bOneNd = pStt->nNode == pEnd->nNode;
1456  const sal_Int32 nLen =
1457  ( bOneNd ? std::min(pEnd->nContent.GetIndex(), pSrcNd->Len()) : pSrcNd->Len() )
1458  - pStt->nContent.GetIndex();
1459 
1460  if( !pEnd->nNode.GetNode().IsContentNode() )
1461  {
1462  bOneNd = true;
1463  sal_uLong nSttNdIdx = pStt->nNode.GetIndex() + 1;
1464  const sal_uLong nEndNdIdx = pEnd->nNode.GetIndex();
1465  for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx )
1466  {
1467  if( (*this)[ nSttNdIdx ]->IsContentNode() )
1468  {
1469  bOneNd = false;
1470  break;
1471  }
1472  }
1473  }
1474 
1475  // templates must be copied/set after a split
1476  if( !bOneNd && bSplitDestNd )
1477  {
1478  if( !rPos.nContent.GetIndex() )
1479  {
1480  bCopyCollFormat = true;
1481  }
1482  if( rNodes.IsDocNodes() )
1483  {
1484  SwDoc* const pInsDoc = pDestNd->GetDoc();
1485  ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
1486  pInsDoc->getIDocumentContentOperations().SplitNode( rPos, false );
1487  }
1488  else
1489  {
1490  pDestNd->SplitContentNode(rPos, nullptr);
1491  }
1492 
1493  if( rPos.nNode == aEndIdx )
1494  {
1495  --aEndIdx;
1496  }
1497  bSplitDestNd = true;
1498 
1499  pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTextNode();
1500  if( nLen )
1501  {
1502  pSrcNd->CutText( pDestNd, SwIndex( pDestNd, pDestNd->Len()),
1503  pStt->nContent, nLen );
1504  }
1505  }
1506  else if ( nLen )
1507  {
1508  pSrcNd->CutText( pDestNd, rPos.nContent, pStt->nContent, nLen );
1509  }
1510 
1511  if( bCopyCollFormat )
1512  {
1513  SwDoc* const pInsDoc = pDestNd->GetDoc();
1514  ::sw::UndoGuard const undoGuard(pInsDoc->GetIDocumentUndoRedo());
1515  pSrcNd->CopyCollFormat( *pDestNd );
1516  bCopyCollFormat = false;
1517  }
1518 
1519  if( bOneNd )
1520  {
1521  // Correct the PaM, because it might have happened that the move
1522  // went over the node borders (so the data might be in different nodes).
1523  // Also, a selection is invalidated.
1524  pEnd->nContent = pStt->nContent;
1525  rPam.DeleteMark();
1526  GetDoc()->GetDocShell()->Broadcast( SwFormatFieldHint( nullptr,
1528  return;
1529  }
1530 
1531  ++aSttIdx;
1532  }
1533  else if( pDestNd )
1534  {
1535  if( rPos.nContent.GetIndex() )
1536  {
1537  if( rPos.nContent.GetIndex() == pDestNd->Len() )
1538  {
1539  ++rPos.nNode;
1540  }
1541  else if( rPos.nContent.GetIndex() )
1542  {
1543  // if the EndNode is split than correct the EndIdx
1544  const bool bCorrEnd = aEndIdx == rPos.nNode;
1545 
1546  // if no text is attached to the TextNode, split it
1547  if( rNodes.IsDocNodes() )
1548  {
1549  SwDoc* const pInsDoc = pDestNd->GetDoc();
1550  ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
1551  pInsDoc->getIDocumentContentOperations().SplitNode( rPos, false );
1552  }
1553  else
1554  {
1555  pDestNd->SplitContentNode(rPos, nullptr);
1556  }
1557 
1558  if ( bCorrEnd )
1559  {
1560  --aEndIdx;
1561  }
1562  }
1563  }
1564  // at the end only an empty TextNode is left over
1565  bSplitDestNd = true;
1566  }
1567 
1568  SwTextNode* const pEndSrcNd = aEndIdx.GetNode().GetTextNode();
1569  if ( pEndSrcNd )
1570  {
1571  // at the end of this range a new TextNode will be created
1572  if( !bSplitDestNd )
1573  {
1574  if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() )
1575  {
1576  ++rPos.nNode;
1577  }
1578 
1579  pDestNd =
1580  rNodes.MakeTextNode( rPos.nNode, pEndSrcNd->GetTextColl() );
1581  --rPos.nNode;
1582  rPos.nContent.Assign( pDestNd, 0 );
1583  }
1584  else
1585  {
1586  pDestNd = rPos.nNode.GetNode().GetTextNode();
1587  }
1588 
1589  if (pDestNd && pEnd->nContent.GetIndex())
1590  {
1591  // move the content into the new node
1592  SwIndex aIdx( pEndSrcNd, 0 );
1593  pEndSrcNd->CutText( pDestNd, rPos.nContent, aIdx,
1594  pEnd->nContent.GetIndex());
1595  }
1596 
1597  if (pDestNd && bCopyCollFormat)
1598  {
1599  SwDoc* const pInsDoc = pDestNd->GetDoc();
1600  ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
1601  pEndSrcNd->CopyCollFormat( *pDestNd );
1602  }
1603  }
1604  else
1605  {
1606  if ( pSrcNd && aEndIdx.GetNode().IsContentNode() )
1607  {
1608  ++aEndIdx;
1609  }
1610  if( !bSplitDestNd )
1611  {
1612  ++rPos.nNode;
1613  rPos.nContent.Assign( rPos.nNode.GetNode().GetContentNode(), 0 );
1614  }
1615  }
1616 
1617  if( aEndIdx != aSttIdx )
1618  {
1619  // move the nodes into the NodesArary
1620  const sal_uLong nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex();
1621  SwNodeRange aRg( aSttIdx, aEndIdx );
1622  MoveNodes( aRg, rNodes, rPos.nNode );
1623 
1624  // if in the same node array, all indices are now at new positions (so correct them)
1625  if( &rNodes == this )
1626  {
1627  pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff;
1628  }
1629  }
1630 
1631  // if the StartNode was moved to whom the cursor pointed, so
1632  // the content must be registered in the current content!
1633  if ( &pStt->nNode.GetNode() == &GetEndOfContent() )
1634  {
1635  const bool bSuccess = GoPrevious( &pStt->nNode );
1636  OSL_ENSURE( bSuccess, "Move() - no ContentNode here" );
1637  }
1638  pStt->nContent.Assign( pStt->nNode.GetNode().GetContentNode(),
1639  pStt->nContent.GetIndex() );
1640  // Correct the PaM, because it might have happened that the move
1641  // went over the node borders (so the data might be in different nodes).
1642  // Also, a selection is invalidated.
1643  *pEnd = *pStt;
1644  rPam.DeleteMark();
1645  GetDoc()->GetDocShell()->Broadcast( SwFormatFieldHint( nullptr,
1647 }
1648 
1650 void SwNodes::CopyNodes( const SwNodeRange& rRange,
1651  const SwNodeIndex& rIndex, bool bNewFrames, bool bTableInsDummyNode ) const
1652 {
1653  SwDoc* pDoc = rIndex.GetNode().GetDoc();
1654 
1655  SwNode * pCurrentNode;
1656  if( rIndex == 0 ||
1657  ( (pCurrentNode = &rIndex.GetNode())->GetStartNode() &&
1658  !pCurrentNode->StartOfSectionIndex() ))
1659  return;
1660 
1661  SwNodeRange aRg( rRange );
1662 
1663  // skip "simple" StartNodes or EndNodes
1664  while( SwNodeType::Start == (pCurrentNode = & aRg.aStart.GetNode())->GetNodeType()
1665  || ( pCurrentNode->IsEndNode() &&
1666  !pCurrentNode->m_pStartOfSection->IsSectionNode() ) )
1667  ++aRg.aStart;
1668 
1669  const SwNode *aEndNode = &aRg.aEnd.GetNode();
1670  int nIsEndOfContent = (aEndNode == &aEndNode->GetNodes().GetEndOfContent()) ? 1 : 0;
1671 
1672  if (0 == nIsEndOfContent)
1673  {
1674  // if aEnd-1 points to no ContentNode, search previous one
1675  --aRg.aEnd;
1676  // #i107142#: if aEnd is start node of a special section, do nothing.
1677  // Otherwise this could lead to crash: going through all previous
1678  // special section nodes and then one before the first.
1679  if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0)
1680  {
1681  while( ((pCurrentNode = & aRg.aEnd.GetNode())->GetStartNode() &&
1682  !pCurrentNode->IsSectionNode() ) ||
1683  ( pCurrentNode->IsEndNode() &&
1684  SwNodeType::Start == pCurrentNode->m_pStartOfSection->GetNodeType()) )
1685  {
1686  --aRg.aEnd;
1687  }
1688  }
1689  ++aRg.aEnd;
1690  }
1691 
1692  // is there anything left to copy?
1693  if( aRg.aStart >= aRg.aEnd )
1694  return;
1695 
1696  // when inserting into the source range, nothing need to be done
1697  OSL_ENSURE( &aRg.aStart.GetNodes() == this,
1698  "aRg should use this node array" );
1699  OSL_ENSURE( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(),
1700  "Range across different nodes arrays? You deserve punishment!");
1701  if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() &&
1702  rIndex.GetIndex() >= aRg.aStart.GetIndex() &&
1703  rIndex.GetIndex() < aRg.aEnd.GetIndex() )
1704  return;
1705 
1706  SwNodeIndex aInsPos( rIndex );
1707  SwNodeIndex aOrigInsPos( rIndex, -1 ); // original insertion position
1708  int nLevel = 0; // level counter
1709 
1710  for( long nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
1711  nNodeCnt > 0; --nNodeCnt )
1712  {
1713  pCurrentNode = &aRg.aStart.GetNode();
1714  switch( pCurrentNode->GetNodeType() )
1715  {
1716  case SwNodeType::Table:
1717  // Does it copy a table in(to) a footnote?
1718  if( aInsPos < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
1720  < aInsPos.GetIndex() )
1721  {
1722  const long nDistance =
1723  pCurrentNode->EndOfSectionIndex() -
1724  aRg.aStart.GetIndex();
1725  if (nDistance < nNodeCnt)
1726  nNodeCnt -= nDistance;
1727  else
1728  nNodeCnt = 1;
1729 
1730  // insert a DummyNode for a TableNode
1731  if( bTableInsDummyNode )
1732  new SwPlaceholderNode(aInsPos);
1733 
1734  // copy all of the table's nodes into the current cell
1735  for( ++aRg.aStart; aRg.aStart.GetIndex() <
1736  pCurrentNode->EndOfSectionIndex();
1737  ++aRg.aStart )
1738  {
1739  // insert a DummyNode for the box-StartNode?
1740  if( bTableInsDummyNode )
1741  new SwPlaceholderNode(aInsPos);
1742 
1743  SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode();
1744  CopyNodes( SwNodeRange( *pSttNd, + 1,
1745  *pSttNd->EndOfSectionNode() ),
1746  aInsPos, bNewFrames );
1747 
1748  // insert a DummyNode for the box-EndNode?
1749  if( bTableInsDummyNode )
1750  new SwPlaceholderNode(aInsPos);
1751  aRg.aStart = *pSttNd->EndOfSectionNode();
1752  }
1753  // insert a DummyNode for the table-EndNode
1754  if( bTableInsDummyNode )
1755  new SwPlaceholderNode(aInsPos);
1756  aRg.aStart = *pCurrentNode->EndOfSectionNode();
1757  }
1758  else
1759  {
1760  SwNodeIndex nStt( aInsPos, -1 );
1761  SwTableNode* pTableNd = static_cast<SwTableNode*>(pCurrentNode)->
1762  MakeCopy( pDoc, aInsPos );
1763  const long nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
1764  if (nDistance < nNodeCnt)
1765  nNodeCnt -= nDistance;
1766  else
1767  nNodeCnt = 1 - nIsEndOfContent;
1768 
1769  aRg.aStart = pCurrentNode->EndOfSectionIndex();
1770 
1771  if( bNewFrames && pTableNd )
1772  {
1773  nStt = aInsPos;
1774  pTableNd->MakeOwnFrames(&nStt);
1775  }
1776  }
1777  break;
1778 
1779  case SwNodeType::Section:
1780  // If the end of the section is outside the copy range,
1781  // the section node will skipped, not copied!
1782  // If someone want to change this behaviour, he has to adjust the function
1783  // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
1784  if( pCurrentNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
1785  {
1786  // copy of the whole section, so create a new SectionNode
1787  SwNodeIndex nStt( aInsPos, -1 );
1788  SwSectionNode* pSectNd = static_cast<SwSectionNode*>(pCurrentNode)->
1789  MakeCopy( pDoc, aInsPos );
1790 
1791  const long nDistance = aInsPos.GetIndex() - nStt.GetIndex() - 2;
1792  if (nDistance < nNodeCnt)
1793  nNodeCnt -= nDistance;
1794  else
1795  nNodeCnt = 1 - nIsEndOfContent;
1796  aRg.aStart = pCurrentNode->EndOfSectionIndex();
1797 
1798  if( bNewFrames && pSectNd &&
1799  !pSectNd->GetSection().IsHidden() )
1800  pSectNd->MakeOwnFrames(&nStt);
1801  }
1802  break;
1803 
1804  case SwNodeType::Start:
1805  {
1806  SwStartNode* pTmp = new SwStartNode( aInsPos, SwNodeType::Start,
1807  static_cast<SwStartNode*>(pCurrentNode)->GetStartNodeType() );
1808  new SwEndNode( aInsPos, *pTmp );
1809  --aInsPos;
1810  nLevel++;
1811  }
1812  break;
1813 
1814  case SwNodeType::End:
1815  if( nLevel ) // complete section
1816  {
1817  --nLevel;
1818  ++aInsPos; // EndNode already exists
1819  }
1820  else if( 1 == nNodeCnt && 1 == nIsEndOfContent )
1821  // we have reached the EndOfContent node - nothing to do!
1822  continue;
1823  else if( !pCurrentNode->m_pStartOfSection->IsSectionNode() )
1824  {
1825  // create a section at the original InsertPosition
1826  SwNodeRange aTmpRg( aOrigInsPos, 1, aInsPos );
1827  pDoc->GetNodes().SectionDown( &aTmpRg,
1828  pCurrentNode->m_pStartOfSection->GetStartNodeType() );
1829  }
1830  break;
1831 
1832  case SwNodeType::Text:
1833  case SwNodeType::Grf:
1834  case SwNodeType::Ole:
1835  {
1836  static_cast<SwContentNode*>(pCurrentNode)->MakeCopy(
1837  pDoc, aInsPos, bNewFrames);
1838  }
1839  break;
1840 
1842  if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
1843  {
1844  // than a SectionNode (start/end) is needed at the current
1845  // InsPos; if so skip it, otherwise ignore current node
1846  SwNode *const pTmpNd = & aInsPos.GetNode();
1847  if( pTmpNd->IsSectionNode() ||
1848  pTmpNd->StartOfSectionNode()->IsSectionNode() )
1849  ++aInsPos; // skip
1850  }
1851  else {
1852  assert(!"How can this node be in the node array?");
1853  }
1854  break;
1855 
1856  default:
1857  assert(false);
1858  }
1859  ++aRg.aStart;
1860  }
1861 }
1862 
1864 {
1865  SwNodeIndex aIdx( rRg.aStart );
1866  while( aIdx.GetIndex() < rRg.aEnd.GetIndex() )
1867  {
1869  RemoveNode( aIdx.GetIndex(), 1, true );
1870  else
1871  ++aIdx;
1872  }
1873 }
1874 
1876  SwStartNodeType eSttNdTyp )
1877 {
1878  SwStartNode* pSttNd = new SwStartNode( rIdx, SwNodeType::Start, eSttNdTyp );
1879  new SwEndNode( rIdx, *pSttNd );
1880  return pSttNd;
1881 }
1882 
1884  SwStartNodeType eSttNdTyp,
1885  SwTextFormatColl *pColl )
1886 {
1887  SwStartNode* pSttNd = new SwStartNode( rWhere, SwNodeType::Start, eSttNdTyp );
1888  new SwEndNode( rWhere, *pSttNd );
1889  MakeTextNode( SwNodeIndex( rWhere, - 1 ), pColl );
1890  return pSttNd;
1891 }
1892 
1893 //TODO: provide better documentation
1907  bool bSkipHidden, bool bSkipProtect ) const
1908 {
1909  bool bFirst = true;
1910  SwNodeIndex aTmp( *pIdx );
1911  const SwNode* pNd;
1912  while( aTmp < Count() - 1 )
1913  {
1914  pNd = & aTmp.GetNode();
1915  if (SwNodeType::Section == pNd->GetNodeType())
1916  {
1917  const SwSection& rSect = static_cast<const SwSectionNode*>(pNd)->GetSection();
1918  if( (bSkipHidden && rSect.IsHiddenFlag()) ||
1919  (bSkipProtect && rSect.IsProtectFlag()) )
1920  // than skip the section
1921  aTmp = *pNd->EndOfSectionNode();
1922  }
1923  else if( bFirst )
1924  {
1925  if( pNd->m_pStartOfSection->IsSectionNode() )
1926  {
1927  const SwSection& rSect = static_cast<SwSectionNode*>(pNd->
1928  m_pStartOfSection)->GetSection();
1929  if( (bSkipHidden && rSect.IsHiddenFlag()) ||
1930  (bSkipProtect && rSect.IsProtectFlag()) )
1931  // than skip the section
1932  aTmp = *pNd->EndOfSectionNode();
1933  }
1934  }
1935  else if( SwNodeType::ContentMask & pNd->GetNodeType() )
1936  {
1937  const SwSectionNode* pSectNd;
1938  if( ( bSkipHidden || bSkipProtect ) &&
1939  nullptr != (pSectNd = pNd->FindSectionNode() ) &&
1940  ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
1941  ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
1942  {
1943  aTmp = *pSectNd->EndOfSectionNode();
1944  }
1945  else
1946  {
1947  (*pIdx) = aTmp;
1948  return const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd));
1949  }
1950  }
1951  ++aTmp;
1952  bFirst = false;
1953  }
1954  return nullptr;
1955 }
1956 
1959  bool bSkipHidden, bool bSkipProtect )
1960 {
1961  bool bFirst = true;
1962  SwNodeIndex aTmp( *pIdx );
1963  const SwNode* pNd;
1964  while( aTmp > 0 )
1965  {
1966  pNd = & aTmp.GetNode();
1967  if (SwNodeType::End == pNd->GetNodeType())
1968  {
1969  if( pNd->m_pStartOfSection->IsSectionNode() )
1970  {
1971  const SwSection& rSect = static_cast<SwSectionNode*>(pNd->
1972  m_pStartOfSection)->GetSection();
1973  if( (bSkipHidden && rSect.IsHiddenFlag()) ||
1974  (bSkipProtect && rSect.IsProtectFlag()) )
1975  // than skip section
1976  aTmp = *pNd->StartOfSectionNode();
1977  }
1978  bFirst = false;
1979  }
1980  else if( bFirst )
1981  {
1982  bFirst = false;
1983  if( pNd->m_pStartOfSection->IsSectionNode() )
1984  {
1985  const SwSection& rSect = static_cast<SwSectionNode*>(pNd->
1986  m_pStartOfSection)->GetSection();
1987  if( (bSkipHidden && rSect.IsHiddenFlag()) ||
1988  (bSkipProtect && rSect.IsProtectFlag()) )
1989  // than skip section
1990  aTmp = *pNd->StartOfSectionNode();
1991  }
1992  }
1993  else if( SwNodeType::ContentMask & pNd->GetNodeType() )
1994  {
1995  const SwSectionNode* pSectNd;
1996  if( ( bSkipHidden || bSkipProtect ) &&
1997  nullptr != (pSectNd = pNd->FindSectionNode() ) &&
1998  ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
1999  ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2000  {
2001  aTmp = *pSectNd;
2002  }
2003  else
2004  {
2005  (*pIdx) = aTmp;
2006  return const_cast<SwContentNode*>(static_cast<const SwContentNode*>(pNd));
2007  }
2008  }
2009  --aTmp;
2010  }
2011  return nullptr;
2012 }
2013 
2014 //TODO: improve documentation
2015 //TODO: The inventor of the "single responsibility principle" will be crying if you ever show this code to him!
2026  const SwNode* pEnd ) const
2027 {
2028  SwNode* pFrameNd = nullptr;
2029 
2030  // no layout -> skip
2031  if( GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() )
2032  {
2033  SwNode* pSttNd = &rFrameIdx.GetNode();
2034 
2035  // move of a hidden section?
2036  SwSectionNode* pSectNd = pSttNd->IsSectionNode()
2037  ? pSttNd->StartOfSectionNode()->FindSectionNode()
2038  : pSttNd->FindSectionNode();
2039  if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag() ) )
2040  {
2041  // in a table in table situation we have to assure that we don't leave the
2042  // outer table cell when the inner table is looking for a PrvNxt...
2043  SwTableNode* pTableNd = pSttNd->IsTableNode()
2044  ? pSttNd->StartOfSectionNode()->FindTableNode()
2045  : pSttNd->FindTableNode();
2046  SwNodeIndex aIdx( rFrameIdx );
2047  SwNode* pNd;
2048  if( pEnd )
2049  {
2050  --aIdx;
2051  pNd = &aIdx.GetNode();
2052  }
2053  else
2054  pNd = pSttNd;
2055 
2056  if( ( pFrameNd = pNd )->IsContentNode() )
2057  rFrameIdx = aIdx;
2058 
2059  // search forward or backward for a content node
2060  else if( nullptr != ( pFrameNd = GoPrevSection( &aIdx, true, false )) &&
2061  ::CheckNodesRange( aIdx, rFrameIdx, true ) &&
2062  // Never out of the table at the start
2063  pFrameNd->FindTableNode() == pTableNd &&
2064  // Bug 37652: Never out of the table at the end
2065  (!pFrameNd->FindTableNode() || pFrameNd->FindTableBoxStartNode()
2066  == pSttNd->FindTableBoxStartNode() ) &&
2067  (!pSectNd || pSttNd->IsSectionNode() ||
2068  pSectNd->GetIndex() < pFrameNd->GetIndex())
2069  )
2070  {
2071  rFrameIdx = aIdx;
2072  }
2073  else
2074  {
2075  if( pEnd )
2076  aIdx = pEnd->GetIndex() + 1;
2077  else
2078  aIdx = rFrameIdx;
2079 
2080  // NEVER leave the section when doing this!
2081  if( ( pEnd && ( pFrameNd = &aIdx.GetNode())->IsContentNode() ) ||
2082  ( nullptr != ( pFrameNd = GoNextSection( &aIdx, true, false )) &&
2083  ::CheckNodesRange( aIdx, rFrameIdx, true ) &&
2084  ( pFrameNd->FindTableNode() == pTableNd &&
2085  // NEVER go out of the table cell at the end
2086  (!pFrameNd->FindTableNode() || pFrameNd->FindTableBoxStartNode()
2087  == pSttNd->FindTableBoxStartNode() ) ) &&
2088  (!pSectNd || pSttNd->IsSectionNode() ||
2089  pSectNd->EndOfSectionIndex() > pFrameNd->GetIndex())
2090  ))
2091  {
2092  // Undo when merging a table with one before, if there is also one after it.
2093  // However, if the node is in a table, it needs to be returned if the
2094  // SttNode is a section or a table!
2095  SwTableNode* pTableNode;
2096  if (pSttNd->IsTableNode() &&
2097  nullptr != (pTableNode = pFrameNd->FindTableNode()) &&
2098  // TABLE IN TABLE:
2099  pTableNode != pSttNd->StartOfSectionNode()->FindTableNode())
2100  {
2101  pFrameNd = pTableNode;
2102  rFrameIdx = *pFrameNd;
2103  }
2104  else
2105  rFrameIdx = aIdx;
2106  }
2107  else if( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
2108  {
2109  pFrameNd = pNd->StartOfSectionNode();
2110  rFrameIdx = *pFrameNd;
2111  }
2112  else
2113  {
2114  if( pEnd )
2115  aIdx = pEnd->GetIndex() + 1;
2116  else
2117  aIdx = rFrameIdx.GetIndex() + 1;
2118 
2119  if( (pFrameNd = &aIdx.GetNode())->IsTableNode() )
2120  rFrameIdx = aIdx;
2121  else
2122  {
2123  pFrameNd = nullptr;
2124 
2125  // is there some sectionnodes before a tablenode?
2126  while( aIdx.GetNode().IsSectionNode() )
2127  {
2128  const SwSection& rSect = aIdx.GetNode().
2129  GetSectionNode()->GetSection();
2130  if( rSect.IsHiddenFlag() )
2131  aIdx = aIdx.GetNode().EndOfSectionIndex()+1;
2132  else
2133  ++aIdx;
2134  }
2135  if( aIdx.GetNode().IsTableNode() )
2136  {
2137  rFrameIdx = aIdx;
2138  pFrameNd = &aIdx.GetNode();
2139  }
2140  }
2141  }
2142  }
2143  }
2144  }
2145  return pFrameNd;
2146 }
2147 
2149  FnForEach_SwNodes fn, void* pArgs )
2150 {
2151  if( nEnd > m_nSize )
2152  nEnd = m_nSize;
2153 
2154  if( nStart >= nEnd )
2155  return;
2156 
2157  sal_uInt16 cur = Index2Block( nStart );
2158  BlockInfo** pp = m_ppInf.get() + cur;
2159  BlockInfo* p = *pp;
2160  sal_uInt16 nElem = sal_uInt16( nStart - p->nStart );
2161  auto pElem = p->mvData.begin() + nElem;
2162  nElem = p->nElem - nElem;
2163  for(;;)
2164  {
2165  if( !(*fn)( static_cast<SwNode *>(*pElem++), pArgs ) || ++nStart >= nEnd )
2166  break;
2167 
2168  // next element
2169  if( !--nElem )
2170  {
2171  // new block
2172  p = *++pp;
2173  pElem = p->mvData.begin();
2174  nElem = p->nElem;
2175  }
2176  }
2177 }
2178 
2179 void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
2180  FnForEach_SwNodes fnForEach, void* pArgs )
2181 {
2182  ForEach( rStart.GetIndex(), rEnd.GetIndex(), fnForEach, pArgs );
2183 }
2184 
2185 void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, bool bDel )
2186 {
2187 #ifndef NDEBUG
2188  SwNode *const pFirst((*this)[nDelPos]);
2189 #endif
2190  for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++)
2191  {
2192  SwNode* pNode = (*this)[ nDelPos + nCnt ];
2193  SwTextNode * pTextNd = pNode->GetTextNode();
2194 
2195  if (pTextNd)
2196  {
2197  pTextNd->RemoveFromList();
2198  // remove RndStdIds::FLY_AS_CHAR *before* adjusting SwNodeIndex
2199  // so their anchor still points to correct node when deleted!
2200  // NOTE: this will call RemoveNode() recursively!
2201  // so adjust our indexes to account for removed nodes
2202  sal_uLong const nPos = pTextNd->GetIndex();
2203  SwpHints *const pHints(pTextNd->GetpSwpHints());
2204  if (pHints)
2205  {
2206  std::vector<SwTextAttr*> flys;
2207  for (size_t i = 0; i < pHints->Count(); ++i)
2208  {
2209  SwTextAttr *const pHint(pHints->Get(i));
2210  if (RES_TXTATR_FLYCNT == pHint->Which())
2211  {
2212  flys.push_back(pHint);
2213  }
2214  }
2215  for (SwTextAttr * pHint : flys)
2216  {
2217  pTextNd->DeleteAttribute(pHint);
2218  } // pHints may be dead now
2219  sal_uLong const nDiff = nPos - pTextNd->GetIndex();
2220  if (nDiff)
2221  {
2222  nDelPos -= nDiff;
2223  }
2224  assert(pTextNd == (*this)[nDelPos + nCnt]);
2225  assert(pFirst == (*this)[nDelPos]);
2226  }
2227  }
2228  SwTableNode* pTableNode = pNode->GetTableNode();
2229  if (pTableNode)
2230  {
2231  // The node that is deleted is a table node.
2232  // Need to make sure that all the redlines that are
2233  // related to this table are removed from the
2234  // 'Extra Redlines' array
2235  pTableNode->RemoveRedlines();
2236  }
2237  }
2238 
2239  sal_uLong nEnd = nDelPos + nSz;
2240  SwNode* pNew = (*this)[ nEnd ];
2241 
2242  for (SwNodeIndex& rIndex : m_vIndices->GetRingContainer())
2243  {
2244  sal_uLong const nIdx = rIndex.GetIndex();
2245  if (nDelPos <= nIdx && nIdx < nEnd)
2246  rIndex = *pNew;
2247  }
2248 
2249  std::vector<BigPtrEntry> aTempEntries;
2250  if( bDel )
2251  {
2252  sal_uLong nCnt = nSz;
2253  BigPtrEntry *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ];
2254 
2255  // set temporary object
2256  // JP 24.08.98: this should actually be removed because one could
2257  // call Remove recursively, e.g. for character bound frames. However,
2258  // since there happens way too much here, this temporary object was
2259  // inserted that will be deleted in Remove again (see Bug 55406)
2260  aTempEntries.resize(nCnt);
2261 
2262  while( nCnt-- )
2263  {
2264  delete pDel;
2265  pDel = pPrev;
2266  sal_uLong nPrevNdIdx = pPrev->GetPos();
2267  BigPtrEntry* pTempEntry = &aTempEntries[nCnt];
2268  BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
2269  if( nCnt )
2270  pPrev = BigPtrArray::operator []( nPrevNdIdx - 1 );
2271  // the accessed element can be a naked BigPtrEntry from
2272  // aTempEntries, so the downcast to SwNode* in
2273  // SwNodes::operator[] would be illegal (and unnecessary)
2274  }
2275  nDelPos = pDel->GetPos() + 1;
2276  }
2277 
2278  BigPtrArray::Remove( nDelPos, nSz );
2279 }
2280 
2281 void SwNodes::InsertNode( const SwNodePtr pNode,
2282  const SwNodeIndex& rPos )
2283 {
2284  BigPtrEntry* pIns = pNode;
2285  BigPtrArray::Insert( pIns, rPos.GetIndex() );
2286 }
2287 
2288 void SwNodes::InsertNode( const SwNodePtr pNode,
2289  sal_uLong nPos )
2290 {
2291  BigPtrEntry* pIns = pNode;
2292  BigPtrArray::Insert( pIns, nPos );
2293 }
2294 
2295 // ->#112139#
2297 {
2298  if (nullptr != pNode)
2299  {
2300  SwNodeIndex aIdx(*pNode);
2301 
2302  if (aIdx <= (*this)[0]->EndOfSectionIndex())
2303  pNode = (*this)[0];
2304  else
2305  {
2306  while ((*this)[0] != pNode->StartOfSectionNode())
2307  pNode = pNode->StartOfSectionNode();
2308  }
2309  }
2310 
2311  return pNode;
2312 }
2313 
2315 {
2316  return DocumentSectionStartNode(pNode)->EndOfSectionNode();
2317 }
2318 
2320 {
2321  return this == &m_pMyDoc->GetNodes();
2322 }
2323 
2325 {
2326  xmlTextWriterStartElement(pWriter, BAD_CAST("SwNodes"));
2327  for (sal_uLong i = 0; i < Count(); ++i)
2328  (*this)[i]->dumpAsXml(pWriter);
2329  xmlTextWriterEndElement(pWriter);
2330 }
2331 
2332 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:961
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:240
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:154
sal_uLong GetIndex() const
Definition: node.hxx:282
SwStartNode * m_pStartOfSection
Definition: node.hxx:112
sal_uLong Count() const
Definition: ndarr.hxx:142
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
const SwField * GetField() const
Definition: fmtfld.hxx:111
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:2436
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_METAFIELD(49)
const OUString & GetText() const
Definition: ndtxt.hxx:211
bool IsOutline() const
Returns if this text node is an outline.
Definition: ndtxt.cxx:3995
SwDocShell * GetDocShell()
Definition: doc.hxx:1348
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:219
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_META(48)
SwNodeIndex nNode
Definition: pam.hxx:37
static sal_uInt16 HighestLevel(SwNodes &rNodes, const SwNodeRange &rRange)
Calculate the highest level in a range.
Definition: nodes.cxx:1408
void AddToList()
Definition: ndtxt.cxx:4283
static sal_uInt16 GetSectionLevel(const SwNodeIndex &rIndex)
get section level at the given position
Definition: nodes.cxx:1251
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:275
sal_uIntPtr sal_uLong
SwNode * DocumentSectionStartNode(SwNode *pNode) const
Definition: nodes.cxx:2296
sal_Int64 n
Definition: doc.hxx:184
static SwContentNode * GoPrevSection(SwNodeIndex *, bool bSkipHidden=true, bool bSkipProtect=true)
Definition: nodes.cxx:1958
SwNode * m_pEndOfInserts
These are the fixed ranges.
Definition: ndarr.hxx:106
void CutText(SwTextNode *const pDest, const SwIndex &rStart, const sal_Int32 nLen)
Definition: ndtxt.cxx:2398
SwSectionNode is derived from SwStartNode.
void DelDummyNodes(const SwNodeRange &rRg)
Definition: nodes.cxx:1863
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(57)
static SwContentNode * GoPrevious(SwNodeIndex *)
Definition: nodes.cxx:1300
SwNode & GetNode() const
Definition: ndindex.hxx:119
bool(* FnForEach_SwNodes)(const SwNodePtr &, void *pArgs)
Definition: ndarr.hxx:68
const OUString & GetName() const
Definition: numrule.hxx:222
SwNode * DocumentSectionEndNode(SwNode *pNode) const
Definition: nodes.cxx:2314
~SwNodes()
Destructor.
Definition: nodes.cxx:93
void RemoveRedlines()
Definition: ndtbl.cxx:2489
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:412
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
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(59)
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:1341
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:356
void Delete(const SwNodeIndex &rPos, sal_uLong nNodes=1)
delete nodes
Definition: nodes.cxx:1071
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:93
SwNodeIndex aStart
Definition: ndindex.hxx:132
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
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:1141
void Replace(sal_uLong pos, BigPtrEntry *p)
Definition: bparr.cxx:390
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
virtual bool IsUndoNodes(SwNodes const &rNodes) const =0
bool IsStartNode() const
Definition: node.hxx:624
virtual bool SetFieldsDirty(bool b, const SwNode *pChk, sal_uLong nLen)=0
static void GoEndOfSection(SwNodeIndex *)
Definition: nodes.cxx:1277
bool CheckNodesRange(const SwNodeIndex &rStt, const SwNodeIndex &rEnd, bool bChkSection)
Check if the given range is inside one of the defined top-level sections.
Definition: pam.cxx:256
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:1322
bool IsProtectFlag() const
Definition: section.hxx:188
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:191
constexpr TypedWhichId< SwFormatFootnote > RES_TXTATR_FTN(58)
void ChgTextNode(SwTextNode *const pNode)
Definition: txtatr2.cxx:305
std::unique_ptr< SwNode > m_pEndOfContent
Definition: ndarr.hxx:108
std::unique_ptr< SwOutlineNodes > m_pOutlineNodes
Array of all outline nodes.
Definition: ndarr.hxx:110
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:163
SwStartNode * MakeTextSection(const SwNodeIndex &rWhere, SwStartNodeType eSttNdTyp, SwTextFormatColl *pColl)
Definition: nodes.cxx:1883
static bool lcl_HighestLevel(const SwNodePtr &rpNode, void *pPara)
Definition: nodes.cxx:1389
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:4331
struct _xmlTextWriter * xmlTextWriterPtr
SwNumRule * FindNumRulePtr(const OUString &rName) const
Definition: docnum.cxx:2416
static SwNodePtr GetStartNode(SwOutlineNodes const *pOutlNds, int nOutlineLevel, SwOutlineNodes::size_type *nOutl)
Definition: docglbl.cxx:89
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
SwDoc * m_pMyDoc
This Doc contains the nodes-array.
Definition: ndarr.hxx:104
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:898
void Broadcast(const SfxHint &rHint)
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
int i
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:143
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
void Insert(BigPtrEntry *p, sal_uLong pos)
Definition: bparr.cxx:201
bool IsHidden() const
Definition: section.hxx:178
static void GoStartOfSection(SwNodeIndex *)
Definition: nodes.cxx:1259
bool IsHiddenFlag() const
Definition: section.hxx:187
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:33
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2806
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:2397
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:96
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:396
void DeleteAttribute(SwTextAttr *const pTextAttr)
delete the attribute pTextAttr
Definition: thints.cxx:1666
SwDoc * GetDoc()
Which Doc contains the nodes-array?
Definition: ndarr.hxx:302
bool CalcHiddenFlag() const
Definition: section.cxx:339
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:1023
bool IsFieldInDoc() const
Definition: atrfld.cxx:394
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
void CopyCollFormat(SwTextNode &rDestNd)
Copy collection with all auto formats to dest-node.
Definition: ndcopy.cxx:334
BigPtrEntry * operator[](sal_uLong) const
Definition: bparr.cxx:82
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
SwNode * m_pEndOfPostIts
Definition: ndarr.hxx:106
void dumpAsXml(xmlTextWriterPtr pWriter) const
Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by...
Definition: nodes.cxx:2324
bool m_bInNodesDel
In Case of recursive calling.
Definition: ndarr.hxx:112
void SetInvalidRule(bool bFlag)
Definition: number.cxx:907
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:67
void ChkCondColl()
Definition: node.cxx:2002
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:952
sal_uLong GetPos() const
Definition: bparr.hxx:97
SwEndNode * m_pEndOfSection
Definition: node.hxx:309
sal_Int32 GetIndex() const
Definition: index.hxx:91
SwNodes & GetNodes()
Definition: doc.hxx:403
const SwPosition * End() const
Definition: pam.hxx:217
SwNodeIndex aEnd
Definition: ndindex.hxx:133
void InsertNode(const SwNodePtr pNode, const SwNodeIndex &rPos)
Definition: nodes.cxx:2281
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndsect.cxx:1161
SwTableNode is derived from SwStartNode.
void * p
sal_uInt16 MakeNumRule(const OUString &rName, const SwNumRule *pCpy=nullptr, bool bBroadcast=false, const SvxNumberFormat::SvxNumPositionAndSpaceMode eDefaultNumberFormatPositionAndSpaceMode=SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
Definition: docnum.cxx:2450
constexpr TypedWhichId< SwConditionTextFormatColl > RES_CONDTXTFMTCOLL(158)
constexpr TypedWhichId< SwTOXMark > RES_TXTATR_TOXMARK(47)
SwNode * m_pEndOfAutotext
Definition: ndarr.hxx:106
constexpr TypedWhichId< SwFormatField > RES_TXTATR_INPUTFIELD(55)
SwStartNodeType
Definition: ndtyp.hxx:50
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:196
bool InvalidateNumRule()
Invalidates NumRule at the node.
Definition: node.cxx:1175
SwTableNode * FindTableNode()
Search table node, in which it is.
Definition: node.cxx:352
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:1906
bool IsDocNodes() const
Is the NodesArray the regular one of Doc? (and not the UndoNds, ...) Implementation in doc...
Definition: nodes.cxx:2319
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:1650
Ends a section of nodes in the document model.
Definition: node.hxx:333
constexpr TypedWhichId< SwFormatRefMark > RES_TXTATR_REFMARK(RES_TXTATR_WITHEND_BEGIN)
sal_uInt16 GetSectionLevel() const
Returns the section level at the position given by aIndex.
Definition: node.cxx:267
SwNode & GetEndOfRedlines() const
Section for all Redlines.
Definition: ndarr.hxx:158
bool m_bInDelUpdOutline
Flag for updating of Outline.
Definition: ndarr.hxx:114
std::vector< SwNode * >::size_type size_type
This class is internal, used only during DocumentContentOperationsManager::CopyWithFlyInFly(), and for undo.
Definition: node.hxx:576
bool IsTextNode() const
Definition: node.hxx:636
SwFieldIds Which() const
Definition: fldbas.hxx:272
SwNode * FindPrvNxtFrameNode(SwNodeIndex &rFrameIdx, const SwNode *pEnd) const
Search previous / next content node or table node with frames.
Definition: nodes.cxx:2025
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1283
void IncRefCnt()
Definition: ddefld.hxx:98
sal_uInt16 nPos
void RemoveNode(sal_uLong nDelPos, sal_uLong nLen, bool bDel)
Definition: nodes.cxx:2185
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:844
friend class SwNodeIndex
Definition: ndarr.hxx:92
SwTextNode * MakeTextNode(const SwNodeIndex &rWhere, SwTextFormatColl *pColl, bool bNewFrames=true)
Implementations of "Make...Node" are in the given .cxx-files.
Definition: ndtxt.cxx:105
bool MoveNodes(const SwNodeRange &, SwNodes &rNodes, const SwNodeIndex &, bool bNewFrames=true)
move the node pointer
Definition: nodes.cxx:396
SwNode * m_pEndOfRedlines
Definition: ndarr.hxx:106
static SwStartNode * MakeEmptySection(const SwNodeIndex &rIdx, SwStartNodeType=SwNormalStartNode)
Create an empty section of Start- and EndNote.
Definition: nodes.cxx:1875
Base class of the Writer document model elements.
Definition: node.hxx:79
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:838
void MoveRange(SwPaM &, SwPosition &, SwNodes &rNodes)
move a range
Definition: nodes.cxx:1422