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