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