merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / docnode / nodes.cxx
blobdd5a91b2bafce9256de30b07d77727ca95bee43b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: nodes.cxx,v $
10 * $Revision: 1.35 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <stdlib.h>
35 #include <node.hxx>
36 #include <doc.hxx>
37 #include <pam.hxx>
38 #include <txtfld.hxx>
39 #include <fmtfld.hxx>
40 #include <hints.hxx>
41 #include <numrule.hxx>
42 #include <ndtxt.hxx>
43 #include <ndnotxt.hxx>
44 #include <swtable.hxx> // fuer erzuegen / loeschen der Table-Frames
45 #include <tblsel.hxx>
46 #include <section.hxx>
47 #include <ddefld.hxx>
48 #include <swddetbl.hxx>
49 #include <frame.hxx>
50 #include <fmtmeta.hxx>
52 #include <docsh.hxx>
53 #include <svtools/smplhint.hxx>
55 extern BOOL CheckNodesRange( const SwNodeIndex& rStt,
56 const SwNodeIndex& rEnd, BOOL bChkSection );
58 SV_DECL_PTRARR(SwSttNdPtrs,SwStartNode*,2,2)
61 //#define JP_DEBUG
62 #ifdef JP_DEBUG
63 #include "shellio.hxx"
64 #endif
67 // Funktion zum bestimmen des hoechsten Levels innerhalb des Bereiches
69 USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange );
71 //-----------------------------------------------------------------------
73 /*******************************************************************
74 |* SwNodes::SwNodes
76 |* Beschreibung
77 |* Konstruktor; legt die vier Grundsektions (PostIts,
78 |* Inserts, Icons, Inhalt) an
79 *******************************************************************/
80 SwNodes::SwNodes( SwDoc* pDocument )
81 : pRoot( 0 ), pMyDoc( pDocument )
83 bInNodesDel = bInDelUpdOutl = bInDelUpdNum = FALSE;
85 ASSERT( pMyDoc, "in welchem Doc stehe ich denn?" );
87 ULONG nPos = 0;
88 SwStartNode* pSttNd = new SwStartNode( *this, nPos++ );
89 pEndOfPostIts = new SwEndNode( *this, nPos++, *pSttNd );
91 SwStartNode* pTmp = new SwStartNode( *this, nPos++ );
92 pEndOfInserts = new SwEndNode( *this, nPos++, *pTmp );
94 pTmp = new SwStartNode( *this, nPos++ );
95 pTmp->pStartOfSection = pSttNd;
96 pEndOfAutotext = new SwEndNode( *this, nPos++, *pTmp );
98 pTmp = new SwStartNode( *this, nPos++ );
99 pTmp->pStartOfSection = pSttNd;
100 pEndOfRedlines = new SwEndNode( *this, nPos++, *pTmp );
102 pTmp = new SwStartNode( *this, nPos++ );
103 pTmp->pStartOfSection = pSttNd;
104 pEndOfContent = new SwEndNode( *this, nPos++, *pTmp );
106 pOutlineNds = new SwOutlineNodes;
109 /*******************************************************************
111 |* SwNodes::~SwNodes
113 |* Beschreibung
114 |* dtor, loescht alle Nodes, deren Pointer in diesem dynamischen
115 |* Array sind. Ist kein Problem, da Nodes ausserhalb dieses
116 |* Arrays nicht erzeugt werden koennen und somit auch nicht
117 |* in mehreren drin sein koennen
119 |* Ersterstellung
120 |* VER0100 vb 901214
122 |* Stand
123 |* VER0100 vb 901214
125 *******************************************************************/
127 SwNodes::~SwNodes()
129 delete pOutlineNds;
132 SwNode *pNode;
133 SwNodeIndex aNdIdx( *this );
134 while( TRUE )
136 pNode = &aNdIdx.GetNode();
137 if( pNode == pEndOfContent )
138 break;
140 aNdIdx++;
141 delete pNode;
145 // jetzt muessen alle SwNodeIndizies abgemeldet sein!!!
146 delete pEndOfContent;
149 void SwNodes::ChgNode( SwNodeIndex& rDelPos, ULONG nSz,
150 SwNodeIndex& rInsPos, BOOL bNewFrms )
152 // im UndoBereich brauchen wir keine Frames
153 SwNodes& rNds = rInsPos.GetNodes();
154 const SwNode* pPrevInsNd = rNds[ rInsPos.GetIndex() -1 ];
156 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
157 // Idle-Handler des Docs
158 if( GetDoc()->SetFieldsDirty( TRUE, &rDelPos.GetNode(), nSz ) &&
159 rNds.GetDoc() != GetDoc() )
160 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
162 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
163 ULONG nNd = rInsPos.GetIndex();
164 BOOL bInsOutlineIdx = !(
165 rNds.GetEndOfRedlines().StartOfSectionNode()->GetIndex() < nNd &&
166 nNd < rNds.GetEndOfRedlines().GetIndex() );
168 if( &rNds == this ) // im gleichen Nodes-Array -> moven !!
170 // wird von vorne nach hinten gemovt, so wird nach vorne immer
171 // nachgeschoben, d.H. die Loeschposition ist immer gleich
172 USHORT nDiff = rDelPos.GetIndex() < rInsPos.GetIndex() ? 0 : 1;
174 for( ULONG n = rDelPos.GetIndex(); nSz; n += nDiff, --nSz )
176 SwNodeIndex aDelIdx( *this, n );
177 SwNode& rNd = aDelIdx.GetNode();
179 // --> OD 2005-11-16 #i57920#
180 // correction of refactoring done by cws swnumtree:
181 // - <SwTxtNode::SetLevel( NO_NUMBERING ) is deprecated and
182 // set <IsCounted> state of the text node to <false>, which
183 // isn't correct here.
184 if ( rNd.IsTxtNode() )
186 SwTxtNode* pTxtNode = rNd.GetTxtNode();
187 // --> OD 2008-03-13 #refactorlists#
188 // pTxtNode->UnregisterNumber();
189 pTxtNode->RemoveFromList();
190 // <--
192 //if ( pTxtNode->GetTxtColl()->GetOutlineLevel() != NO_NUMBERING )//#outline level,zhaojianwei
193 if ( pTxtNode->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
195 const SwNodePtr pSrch = (SwNodePtr)&rNd;
196 pOutlineNds->Remove( pSrch );
199 // <--
201 BigPtrArray::Move( aDelIdx.GetIndex(), rInsPos.GetIndex() );
203 if( rNd.IsTxtNode() )
205 SwTxtNode& rTxtNd = (SwTxtNode&)rNd;
206 // --> OD 2008-03-13 #refactorlists#
207 // rTxtNd.SyncNumberAndNumRule();
208 rTxtNd.AddToList();
209 // <--
211 if( bInsOutlineIdx &&
212 //NO_NUMBERING != rTxtNd.GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
213 0 != rTxtNd.GetAttrOutlineLevel() )//<-end,zhaojianwei
215 const SwNodePtr pSrch = (SwNodePtr)&rNd;
216 pOutlineNds->Insert( pSrch );
218 rTxtNd.InvalidateNumRule();
220 //FEATURE::CONDCOLL
221 if( RES_CONDTXTFMTCOLL == rTxtNd.GetTxtColl()->Which() )
222 rTxtNd.ChkCondColl();
223 //FEATURE::CONDCOLL
225 else if( rNd.IsCntntNode() )
226 ((SwCntntNode&)rNd).InvalidateNumRule();
229 else
231 int bSavePersData = GetDoc()->GetUndoNds() == &rNds;
232 int bRestPersData = GetDoc()->GetUndoNds() == this;
233 SwDoc* pDestDoc = rNds.GetDoc() != GetDoc() ? rNds.GetDoc() : 0;
234 if( !bRestPersData && !bSavePersData && pDestDoc )
235 bSavePersData = bRestPersData = TRUE;
237 String sNumRule;
238 SwNodeIndex aInsPos( rInsPos );
239 for( ULONG n = 0; n < nSz; n++ )
241 SwNode* pNd = &rDelPos.GetNode();
243 // NoTextNode muessen ihre Persitenten Daten mitnehmen
244 if( pNd->IsNoTxtNode() )
246 if( bSavePersData )
247 ((SwNoTxtNode*)pNd)->SavePersistentData();
249 else if( pNd->IsTxtNode() )
251 SwTxtNode* pTxtNd = (SwTxtNode*)pNd;
253 // loesche die Gliederungs-Indizies aus dem alten Nodes-Array
254 //if( NO_NUMBERING != pTxtNd->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
255 if( 0 != pTxtNd->GetAttrOutlineLevel() )//<-end,zhaojianwei
256 pOutlineNds->Remove( pNd );
258 // muss die Rule kopiere werden?
259 if( pDestDoc )
261 const SwNumRule* pNumRule = pTxtNd->GetNumRule();
262 if( pNumRule && sNumRule != pNumRule->GetName() )
264 sNumRule = pNumRule->GetName();
265 SwNumRule* pDestRule = pDestDoc->FindNumRulePtr( sNumRule );
266 if( pDestRule )
267 pDestRule->SetInvalidRule( TRUE );
268 else
269 pDestDoc->MakeNumRule( sNumRule, pNumRule );
272 else
273 // wenns ins UndoNodes-Array gemoved wird, sollten die
274 // Numerierungen auch aktualisiert werden.
275 pTxtNd->InvalidateNumRule();
277 // --> OD 2008-03-13 #refactorlists#
278 // pTxtNd->UnregisterNumber();
279 pTxtNd->RemoveFromList();
280 // <--
283 RemoveNode( rDelPos.GetIndex(), 1, FALSE ); // Indizies verschieben !!
284 SwCntntNode * pCNd = pNd->GetCntntNode();
285 rNds.InsertNode( pNd, aInsPos );
287 if( pCNd )
289 SwTxtNode* pTxtNd = pCNd->GetTxtNode();
290 if( pTxtNd )
292 SwpHints * const pHts = pTxtNd->GetpSwpHints();
293 // setze die OultineNodes im neuen Nodes-Array
294 //if( bInsOutlineIdx && NO_NUMBERING != //#outline level,removed by zhaojianwei
295 // pTxtNd->GetTxtColl()->GetOutlineLevel() )
296 if( bInsOutlineIdx &&
297 0 != pTxtNd->GetAttrOutlineLevel() ) //#outline level,added by zhaojianwei
299 rNds.pOutlineNds->Insert( pTxtNd );
302 // --> OD 2008-03-13 #refactorlists#
303 // pTxtNd->SyncNumberAndNumRule();
304 pTxtNd->AddToList();
305 // <--
307 // Sonderbehandlung fuer die Felder!
308 if( pHts && pHts->Count() )
310 int bToUndo = &pDestDoc->GetNodes() != &rNds;
311 for( USHORT i = pHts->Count(); i; )
313 USHORT nDelMsg = 0;
314 SwTxtAttr * const pAttr = pHts->GetTextHint( --i );
315 switch ( pAttr->Which() )
317 case RES_TXTATR_FIELD:
319 SwTxtFld* pTxtFld =
320 static_cast<SwTxtFld*>(pAttr);
321 rNds.GetDoc()->InsDelFldInFldLst( !bToUndo, *pTxtFld );
323 const SwFieldType* pTyp = pTxtFld->GetFld().GetFld()->GetTyp();
324 if ( RES_POSTITFLD == pTyp->Which() )
326 rNds.GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( &pTxtFld->GetFld(), pTxtFld->GetFld().IsFldInDoc() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
328 else
329 if( RES_DDEFLD == pTyp->Which() )
331 if( bToUndo )
332 ((SwDDEFieldType*)pTyp)->DecRefCnt();
333 else
334 ((SwDDEFieldType*)pTyp)->IncRefCnt();
336 nDelMsg = RES_FIELD_DELETED;
338 break;
339 case RES_TXTATR_FTN:
340 nDelMsg = RES_FOOTNOTE_DELETED;
341 break;
343 case RES_TXTATR_TOXMARK:
344 nDelMsg = RES_TOXMARK_DELETED;
345 break;
347 case RES_TXTATR_REFMARK:
348 nDelMsg = RES_REFMARK_DELETED;
349 break;
351 case RES_TXTATR_META:
352 case RES_TXTATR_METAFIELD:
353 static_cast<SwFmtMeta&>(pAttr->GetAttr())
354 .NotifyRemoval();
355 break;
357 default:
358 break;
360 if( nDelMsg && bToUndo )
362 SwPtrMsgPoolItem aMsgHint( nDelMsg,
363 (void*)&pAttr->GetAttr() );
364 rNds.GetDoc()->GetUnoCallBack()->
365 Modify( &aMsgHint, &aMsgHint );
369 //FEATURE::CONDCOLL
370 if( RES_CONDTXTFMTCOLL == pTxtNd->GetTxtColl()->Which() )
371 pTxtNd->ChkCondColl();
372 //FEATURE::CONDCOLL
374 else
376 // in unterschiedliche Docs gemoved ?
377 // dann die Daten wieder persistent machen
378 if( pCNd->IsNoTxtNode() && bRestPersData )
379 ((SwNoTxtNode*)pCNd)->RestorePersistentData();
385 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
386 // Idle-Handler des Docs
387 GetDoc()->SetFieldsDirty( true, NULL, 0 );
388 if( rNds.GetDoc() != GetDoc() )
389 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
392 if( bNewFrms )
393 bNewFrms = &GetDoc()->GetNodes() == (const SwNodes*)&rNds &&
394 GetDoc()->GetRootFrm();
395 if( bNewFrms )
397 // Frames besorgen:
398 SwNodeIndex aIdx( *pPrevInsNd, 1 );
399 SwNodeIndex aFrmNdIdx( aIdx );
400 SwNode* pFrmNd = rNds.FindPrvNxtFrmNode( aFrmNdIdx,
401 rNds[ rInsPos.GetIndex() - 1 ] );
403 if( !pFrmNd && aFrmNdIdx > rNds.GetEndOfExtras().GetIndex() )
405 ASSERT( !this, "ob das so richtig ist ??" );
406 aFrmNdIdx = rNds.GetEndOfContent();
407 pFrmNd = rNds.GoPrevSection( &aFrmNdIdx, TRUE, FALSE );
408 if( pFrmNd && !((SwCntntNode*)pFrmNd)->GetDepends() )
409 pFrmNd = 0;
411 #ifndef PRODUCT
412 if( !pFrmNd )
413 ASSERT( !this, "ChgNode() - kein FrameNode gefunden" );
414 #endif
416 if( pFrmNd )
417 while( aIdx != rInsPos )
419 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
420 if( pCNd )
422 if( pFrmNd->IsTableNode() )
423 ((SwTableNode*)pFrmNd)->MakeFrms( aIdx );
424 else if( pFrmNd->IsSectionNode() )
425 ((SwSectionNode*)pFrmNd)->MakeFrms( aIdx );
426 else
427 ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd );
428 pFrmNd = pCNd;
430 aIdx++;
436 /***********************************************************************
438 |* SwNodes::Move
440 |* Beschreibung
441 |* Move loescht die Node-Pointer ab und einschliesslich der Startposition
442 |* bis zu und ausschliesslich der Endposition und fuegt sie an
443 |* der vor der Zielposition ein.
444 |* Wenn das Ziel vor dem ersten oder dem letzten zu bewegenden Element oder
445 |* dazwischen liegt, geschieht nichts.
446 |* Wenn der zu bewegende Bereich leer ist oder das Ende vor
447 |* dem Anfang liegt, geschieht nichts.
449 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
450 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
454 ***********************************************************************/
456 BOOL SwNodes::_MoveNodes( const SwNodeRange& aRange, SwNodes & rNodes,
457 const SwNodeIndex& aIndex, BOOL bNewFrms )
459 SwNode * pAktNode;
460 if( aIndex == 0 ||
461 ( (pAktNode = &aIndex.GetNode())->GetStartNode() &&
462 !pAktNode->StartOfSectionIndex() ))
463 return FALSE;
465 SwNodeRange aRg( aRange );
467 // "einfache" StartNodes oder EndNodes ueberspringen
468 while( ND_STARTNODE == (pAktNode = &aRg.aStart.GetNode())->GetNodeType()
469 || ( pAktNode->IsEndNode() &&
470 !pAktNode->pStartOfSection->IsSectionNode() ) )
471 aRg.aStart++;
472 aRg.aStart--;
474 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
475 aRg.aEnd--;
476 while( ( (( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
477 !pAktNode->IsSectionNode() ) ||
478 ( pAktNode->IsEndNode() &&
479 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) ) &&
480 aRg.aEnd > aRg.aStart )
481 aRg.aEnd--;
484 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
485 if( aRg.aStart >= aRg.aEnd )
486 return FALSE;
488 if( this == &rNodes )
490 if( ( aIndex.GetIndex()-1 >= aRg.aStart.GetIndex() &&
491 aIndex.GetIndex()-1 < aRg.aEnd.GetIndex()) ||
492 ( aIndex.GetIndex()-1 == aRg.aEnd.GetIndex() ) )
493 return FALSE;
496 USHORT nLevel = 0; // Level-Counter
497 ULONG nInsPos = 0; // Cnt fuer das TmpArray
499 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
500 SwSttNdPtrs aSttNdStack( 1, 5 );
502 // setze den Start-Index
503 SwNodeIndex aIdx( aIndex );
505 --- JP 17.11.94: sollte ueberholt sein, wird im ChgNode schon erledigt!
506 BOOL bCorrNum = pSect && pSect->aStart.GetIndex() == aIdx.GetIndex();
509 SwStartNode* pStartNode = aIdx.GetNode().pStartOfSection;
510 aSttNdStack.C40_INSERT( SwStartNode, pStartNode, 0 );
511 // aSttNdStack.Insert( rNodes[ aIdx ]->pStartOfSection, 0 );
512 SwNodeRange aOrigInsPos( aIdx, -1, aIdx ); // Originale Insert Pos
514 //JP 16.01.98: SectionNodes: DelFrms/MakeFrms beim obersten SectionNode!
515 USHORT nSectNdCnt = 0;
516 BOOL bSaveNewFrms = bNewFrms;
518 // bis alles verschoben ist
519 while( aRg.aStart < aRg.aEnd )
520 switch( (pAktNode = &aRg.aEnd.GetNode())->GetNodeType() )
522 case ND_ENDNODE:
524 if( nInsPos ) // verschieb schon mal alle bis hier her
526 // loeschen und kopieren. ACHTUNG: die Indizies ab
527 // "aRg.aEnd+1" werden mit verschoben !!
528 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
529 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
530 aIdx -= nInsPos;
531 nInsPos = 0;
534 SwStartNode* pSttNd = pAktNode->pStartOfSection;
535 if( pSttNd->IsTableNode() )
537 SwTableNode* pTblNd = (SwTableNode*)pSttNd;
539 // dann bewege die gesamte Tabelle/den Bereich !!
540 nInsPos = (aRg.aEnd.GetIndex() -
541 pSttNd->GetIndex() )+1;
542 aRg.aEnd -= nInsPos;
544 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
545 ULONG nNd = aIdx.GetIndex();
546 BOOL bInsOutlineIdx = !( rNodes.GetEndOfRedlines().
547 StartOfSectionNode()->GetIndex() < nNd &&
548 nNd < rNodes.GetEndOfRedlines().GetIndex() );
550 if( bNewFrms )
551 // loesche erstmal die Frames
552 pTblNd->DelFrms();
553 if( &rNodes == this ) // in sich selbst moven ??
555 // dann bewege alle Start/End/ContentNodes. Loesche
556 // bei den ContentNodes auch die Frames !!
557 pTblNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
558 for( ULONG n = 0; n < nInsPos; ++n )
560 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
561 SwCntntNode* pCNd = 0;
562 SwNode* pTmpNd = &aMvIdx.GetNode();
563 if( pTmpNd->IsCntntNode() )
565 pCNd = (SwCntntNode*)pTmpNd;
566 if( pTmpNd->IsTxtNode() )
567 ((SwTxtNode*)pTmpNd)->RemoveFromList();
569 // if( bNewFrms )
570 // pCNd->DelFrms();
572 // setze bei Start/EndNodes die richtigen Indizies
573 // loesche die Gliederungs-Indizies aus
574 // dem alten Nodes-Array
575 //if( pCNd->IsTxtNode() && NO_NUMBERING != //#outline level,zhaojianwei
576 // ((SwTxtNode*)pCNd)->GetTxtColl()->GetOutlineLevel() )
577 if( pCNd->IsTxtNode() && 0 !=
578 ((SwTxtNode*)pCNd)->GetAttrOutlineLevel() )//<-end,by zhaojianwei
579 pOutlineNds->Remove( pCNd );
580 else
581 pCNd = 0;
583 // else if( bNewFrms && pTmpNd->IsSectionNode() )
584 // ((SwSectionNode*)pTmpNd)->DelFrms();
585 BigPtrArray::Move( aMvIdx.GetIndex(), aIdx.GetIndex() );
587 if( bInsOutlineIdx && pCNd )
588 pOutlineNds->Insert( pCNd );
589 if( pTmpNd->IsTxtNode() )
590 ((SwTxtNode*)pTmpNd)->AddToList();
593 else
595 // StartNode holen
596 // Even aIdx points to a startnode, we need the startnode
597 // of the environment of aIdx (#i80941)
598 SwStartNode* pSttNode = aIdx.GetNode().pStartOfSection;
600 // Hole alle Boxen mit Inhalt. Deren Indizies auf die
601 // StartNodes muessen umgemeldet werden !!
602 // (Array kopieren und alle gefunden wieder loeschen;
603 // erleichtert das suchen!!)
604 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
605 for( ULONG n = 0; n < nInsPos; ++n )
607 SwNode* pNd = &aMvIdx.GetNode();
608 /* if( bNewFrms )
610 if( pNd->IsCntntNode() )
611 ((SwCntntNode*)pNd)->DelFrms();
612 else if( pNd->IsSectionNode() )
613 ((SwSectionNode*)pNd)->DelFrms();
616 //BOOL bOutlNd = pNd->IsTxtNode() && NO_NUMBERING !=//#outline level,zhaojianwei
617 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel();
618 const bool bOutlNd = pNd->IsTxtNode() &&
619 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel();//<-end,zhaojianwei
620 // loesche die Gliederungs-Indizies aus
621 // dem alten Nodes-Array
622 if( bOutlNd )
623 pOutlineNds->Remove( pNd );
625 RemoveNode( aMvIdx.GetIndex(), 1, FALSE );
626 pNd->pStartOfSection = pSttNode;
627 rNodes.InsertNode( pNd, aIdx );
629 // setze bei Start/EndNodes die richtigen Indizies
630 if( bInsOutlineIdx && bOutlNd )
631 // und setze sie im neuen Nodes-Array
632 rNodes.pOutlineNds->Insert( pNd );
633 else if( pNd->IsStartNode() )
634 pSttNode = (SwStartNode*)pNd;
635 else if( pNd->IsEndNode() )
637 pSttNode->pEndOfSection = (SwEndNode*)pNd;
638 if( pSttNode->IsSectionNode() )
639 ((SwSectionNode*)pSttNode)->NodesArrChgd();
640 pSttNode = pSttNode->pStartOfSection;
644 if( pTblNd->GetTable().IsA( TYPE( SwDDETable ) ))
646 SwDDEFieldType* pTyp = ((SwDDETable&)pTblNd->
647 GetTable()).GetDDEFldType();
648 if( pTyp )
650 if( rNodes.IsDocNodes() )
651 pTyp->IncRefCnt();
652 else
653 pTyp->DecRefCnt();
657 if( GetDoc()->GetUndoNds() == &rNodes )
659 SwFrmFmt* pTblFmt = pTblNd->GetTable().GetFrmFmt();
660 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
661 pTblFmt );
662 pTblFmt->Modify( &aMsgHint, &aMsgHint );
665 if( bNewFrms )
667 SwNodeIndex aTmp( aIdx );
668 pTblNd->MakeFrms( &aTmp );
670 aIdx -= nInsPos;
671 nInsPos = 0;
673 else if( pSttNd->GetIndex() < aRg.aStart.GetIndex() )
675 // SectionNode: es wird nicht die gesamte Section
676 // verschoben, also bewege nur die
677 // ContentNodes
678 // StartNode: erzeuge an der Postion eine neue Section
679 do { // middle check loop
680 if( !pSttNd->IsSectionNode() )
682 // Start und EndNode an der InsertPos erzeugen
683 SwStartNode* pTmp = new SwStartNode( aIdx,
684 ND_STARTNODE,
685 /*?? welcher NodeTyp ??*/
686 SwNormalStartNode );
688 nLevel++; // den Index auf StartNode auf den Stack
689 aSttNdStack.C40_INSERT( SwStartNode, pTmp, nLevel );
691 // noch den EndNode erzeugen
692 new SwEndNode( aIdx, *pTmp );
694 else if( (const SwNodes*)&rNodes ==
695 GetDoc()->GetUndoNds() )
697 // im UndoNodes-Array spendieren wir einen
698 // Platzhalter
699 new SwNode( aIdx, ND_SECTIONDUMMY );
701 else
703 // JP 18.5.2001: neue Section anlegen?? Bug 70454
704 aRg.aEnd--;
705 break;
709 aRg.aEnd--;
710 aIdx--;
711 } while( FALSE );
713 else
715 // Start und EndNode komplett verschieben
716 // s. u. SwIndex aOldStt( pSttNd->theIndex );
717 //JP 21.05.97: sollte der Start genau der Start des Bereiches sein, so muss
718 // der Node auf jedenfall noch besucht werden!
719 if( &aRg.aStart.GetNode() == pSttNd )
720 --aRg.aStart;
722 SwSectionNode* pSctNd = pSttNd->GetSectionNode();
723 if( bNewFrms && pSctNd )
724 pSctNd->DelFrms();
726 RemoveNode( aRg.aEnd.GetIndex(), 1, FALSE ); // EndNode loeschen
727 ULONG nSttPos = pSttNd->GetIndex();
729 // dieser StartNode wird spaeter wieder entfernt!
730 SwStartNode* pTmpSttNd = new SwStartNode( *this, nSttPos+1 );
731 pTmpSttNd->pStartOfSection = pSttNd->pStartOfSection;
733 RemoveNode( nSttPos, 1, FALSE ); // SttNode loeschen
735 pSttNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
736 rNodes.InsertNode( pSttNd, aIdx );
737 rNodes.InsertNode( pAktNode, aIdx );
738 aIdx--;
739 pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
741 aRg.aEnd--;
743 nLevel++; // den Index auf StartNode auf den Stack
744 aSttNdStack.C40_INSERT( SwStartNode, pSttNd, nLevel );
746 // SectionNode muss noch ein paar Indizies ummelden
747 if( pSctNd )
749 pSctNd->NodesArrChgd();
750 ++nSectNdCnt;
751 bNewFrms = FALSE;
755 break;
759 case ND_SECTIONNODE:
760 if( !nLevel &&
761 ( (const SwNodes*)&rNodes == GetDoc()->GetUndoNds() ) )
763 // dann muss an der akt. InsPos ein SectionDummyNode
764 // eingefuegt werden
765 if( nInsPos ) // verschieb schon mal alle bis hier her
767 // loeschen und kopieren. ACHTUNG: die Indizies ab
768 // "aRg.aEnd+1" werden mit verschoben !!
769 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
770 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
771 aIdx -= nInsPos;
772 nInsPos = 0;
774 new SwNode( aIdx, ND_SECTIONDUMMY );
775 aRg.aEnd--;
776 aIdx--;
777 break;
779 // kein break !!
780 case ND_TABLENODE:
781 case ND_STARTNODE:
783 // Bug #78589# - empty section -> nothing to do
784 // and only if it's a top level section
785 if( !nInsPos && !nLevel )
787 aRg.aEnd--;
788 break;
791 if( !nLevel ) // es wird eine Stufe runter gestuft
793 // erzeuge die Runterstufung
794 SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 );
795 SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx,
796 ND_STARTNODE,
797 ((SwStartNode*)pAktNode)->GetStartNodeType() );
799 aTmpSIdx--;
801 SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd );
802 new SwEndNode( aTmpEIdx, *pTmpStt );
803 aTmpEIdx--;
804 aTmpSIdx++;
806 // setze die StartOfSection richtig
807 aRg.aEnd++;
809 SwNodeIndex aCntIdx( aRg.aEnd );
810 for( ULONG n = 0; n < nInsPos; n++, aCntIdx++)
811 aCntIdx.GetNode().pStartOfSection = pTmpStt;
814 // Setze auch bei allen runtergestuften den richtigen StartNode
815 while( aTmpSIdx < aTmpEIdx )
816 if( 0 != (( pAktNode = &aTmpEIdx.GetNode())->GetEndNode()) )
817 aTmpEIdx = pAktNode->StartOfSectionIndex();
818 else
820 pAktNode->pStartOfSection = pTmpStt;
821 aTmpEIdx--;
824 aIdx--; // hinter den eingefuegten StartNode
825 aRg.aEnd--; // vor den StartNode
826 // kopiere jetzt das Array. ACHTUNG: die Indizies ab
827 // "aRg.aEnd+1" werden mit verschoben !!
828 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
829 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
830 aIdx -= nInsPos+1;
831 nInsPos = 0;
833 else // es wurden alle Nodes innerhalb eines
834 { // Start- und End-Nodes verschoben
835 ASSERT( pAktNode == aSttNdStack[nLevel] ||
836 ( pAktNode->IsStartNode() &&
837 aSttNdStack[nLevel]->IsSectionNode()),
838 "falscher StartNode" );
840 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
841 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
842 aIdx -= nInsPos+1; // vor den eingefuegten StartNode
843 nInsPos = 0;
845 // loesche nur noch den Pointer aus dem Nodes-Array.
846 // RemoveNode( aRg.aEnd.GetIndex(), 1, FALSE );
847 RemoveNode( aRg.aEnd.GetIndex(), 1, TRUE );
848 aRg.aEnd--;
850 SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode();
851 if( pSectNd && !--nSectNdCnt )
853 SwNodeIndex aTmp( *pSectNd );
854 pSectNd->MakeFrms( &aTmp );
855 bNewFrms = bSaveNewFrms;
857 aSttNdStack.Remove( nLevel ); // vom Stack loeschen
858 nLevel--;
861 // loesche alle entstehenden leeren Start-/End-Node-Paare
862 SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode();
863 if( pTmpNode && ND_STARTNODE == (pAktNode = &aRg.aEnd.GetNode())
864 ->GetNodeType() && pAktNode->StartOfSectionIndex() &&
865 pTmpNode->StartOfSectionNode() == pAktNode )
867 DelNodes( aRg.aEnd, 2 );
868 aRg.aEnd--;
870 // aRg.aEnd--;
872 break;
874 case ND_TEXTNODE:
875 case ND_GRFNODE:
876 case ND_OLENODE:
878 if( bNewFrms && pAktNode->GetCntntNode() )
879 ((SwCntntNode*)pAktNode)->DelFrms();
881 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
882 nInsPos++;
883 aRg.aEnd--;
885 break;
887 case ND_SECTIONDUMMY:
888 if( (const SwNodes*)this == GetDoc()->GetUndoNds() )
890 if( &rNodes == this ) // innerhalb vom UndoNodesArray
892 // mit verschieben
893 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
894 nInsPos++;
896 else // in ein "normales" Nodes-Array verschieben
898 // dann muss an der akt. InsPos auch ein SectionNode
899 // (Start/Ende) stehen; dann diesen ueberspringen.
900 // Andernfalls nicht weiter beachten.
901 if( nInsPos ) // verschieb schon mal alle bis hier her
903 // loeschen und kopieren. ACHTUNG: die Indizies ab
904 // "aRg.aEnd+1" werden mit verschoben !!
905 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
906 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
907 aIdx -= nInsPos;
908 nInsPos = 0;
910 SwNode* pTmpNd = &aIdx.GetNode();
911 if( pTmpNd->IsSectionNode() ||
912 pTmpNd->StartOfSectionNode()->IsSectionNode() )
913 aIdx--; // ueberspringen
916 else {
917 ASSERT( FALSE, "wie kommt diser Node ins Nodes-Array??" );
919 aRg.aEnd--;
920 break;
922 default:
923 ASSERT( FALSE, "was ist das fuer ein Node??" );
924 break;
927 if( nInsPos ) // kopiere den Rest
929 // der Rest muesste so stimmen
930 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
931 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
933 aRg.aEnd++; // wieder exklusive Ende
935 // loesche alle leeren Start-/End-Node-Paare
936 if( ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
937 pAktNode->StartOfSectionIndex() &&
938 aRg.aEnd.GetNode().GetEndNode() )
939 DelNodes( aRg.aStart, 2 );
941 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
942 aOrigInsPos.aStart++;
943 // im gleichen Nodes-Array verschoben ??,
944 // dann von oben nach unten das Update aufrufen !!
945 if( this == &rNodes &&
946 aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() )
948 UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
949 UpdtOutlineIdx( aRg.aEnd.GetNode() );
951 else
953 UpdtOutlineIdx( aRg.aEnd.GetNode() );
954 rNodes.UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
957 #ifdef JP_DEBUG
959 extern Writer* GetDebugWriter(const String&);
961 Writer* pWriter = GetDebugWriter(aEmptyStr);
962 if( pWriter )
964 int nError;
965 SvFileStream aStrm( "c:\\$$move.db", STREAM_WRITE );
966 SwWriter aWriter( aStrm, *pMyDoc );
967 aWriter.Write( &nError, pWriter );
970 #endif
972 return TRUE;
976 /*******************************************************************
978 |* SwNodes::SectionDown
980 |* Beschreibung
981 |* SectionDown() legt ein Paar von Start- und EndSection-Node
982 |* (andere Nodes koennen dazwischen liegen) an.
984 |* Zustand des SRange beim Verlassen der Funktion: nStart ist der
985 |* Index des ersten Node hinter dem Start Section Node, nEnd ist
986 |* der Index des End Section Nodes. Beispiel: Wird Insert Section
987 |* mehrmals hintereinander aufgerufen, so werden mehrere
988 |* unmittelbar geschachtelte Sections (keine Content Nodes
989 |* zwischen Start- bzw. End Nodes) angelegt.
991 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
992 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
994 |* Parameter
995 |* SwRange &rRange
996 |* IO:
997 |* IN
998 |* rRange.aStart: Einfuegeposition des StartNodes
999 |* rRange.aEnd: Einfuegeposition des EndNodes
1000 |* OUT
1001 |* rRange.aStart: steht hinter dem eingefuegten Startnode
1002 |* rRange.aEnd: steht auf dem eingefuegen Endnode
1004 |* Ausnahmen
1005 |* 1. SRange-Anfang und SRange-Ende muessen auf dem gleichen Level sein
1006 |* 2. duerfen nicht auf dem obersten Level sein
1007 |* Ist dies nicht der Fall, wird die
1008 |* Funktion durch Aufruf von ERR_RAISE verlassen.
1010 |* Debug-Funktionen
1011 |* die Debugging Tools geben rRange beim Eintritt und beim
1012 |* Verlassen der Funktion aus
1014 |* Ersterstellung
1015 |* VER0100 vb 901214
1017 |* Stand
1018 |* VER0100 vb 901214
1020 *******************************************************************/
1021 void SwNodes::SectionDown(SwNodeRange *pRange, SwStartNodeType eSttNdTyp )
1023 if( pRange->aStart >= pRange->aEnd ||
1024 pRange->aEnd >= Count() ||
1025 !CheckNodesRange( pRange->aStart, pRange->aEnd ))
1026 return;
1028 // Ist der Anfang vom Bereich vor oder auf einem EndNode, so loesche
1029 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
1030 // Bei anderen Nodes wird eine neuer StartNode eingefuegt
1031 SwNode * pAktNode = &pRange->aStart.GetNode();
1032 SwNodeIndex aTmpIdx( *pAktNode->StartOfSectionNode() );
1034 if( pAktNode->GetEndNode() )
1035 DelNodes( pRange->aStart, 1 ); // verhinder leere Section
1036 else
1038 // fuege einen neuen StartNode ein
1039 SwNode* pSttNd = new SwStartNode( pRange->aStart, ND_STARTNODE, eSttNdTyp );
1040 pRange->aStart = *pSttNd;
1041 aTmpIdx = pRange->aStart;
1044 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
1045 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen
1046 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1047 pRange->aEnd--;
1048 if( pRange->aEnd.GetNode().GetStartNode() )
1049 DelNodes( pRange->aEnd, 1 );
1050 else
1052 pRange->aEnd++;
1053 // fuege einen neuen EndNode ein
1054 new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() );
1056 pRange->aEnd--;
1058 SectionUpDown( aTmpIdx, pRange->aEnd );
1061 /*******************************************************************
1063 |* SwNodes::SectionUp
1065 |* Beschreibung
1066 |* Der von rRange umspannte Bereich wird auf die naechst hoehere
1067 |* Ebene gehoben. Das geschieht dadurch, dass bei
1068 |* rRange.aStart ein Endnode und bei rRange.aEnd ein
1069 |* Startnode eingefuegt wird. Die Indices fuer den Bereich
1070 |* innerhalb von rRange werden geupdated.
1072 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
1073 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
1075 |* Parameter
1076 |* SwRange &rRange
1077 |* IO:
1078 |* IN
1079 |* rRange.aStart: Anfang des hoeher zubewegenden Bereiches
1080 |* rRange.aEnd: der 1.Node hinter dem Bereich
1081 |* OUT
1082 |* rRange.aStart: an der ersten Position innerhalb des
1083 |* hochbewegten Bereiches
1084 |* rRange.aEnd: an der letzten Position innerhalb des
1085 |* hochbewegten Bereiches
1087 |* Debug-Funktionen
1088 |* die Debugging Tools geben rRange beim Eintritt und beim
1089 |* Verlassen der Funktion aus
1091 |* Ersterstellung
1092 |* VER0100 vb 901214
1094 |* Stand
1095 |* VER0100 vb 901214
1097 *******************************************************************/
1098 void SwNodes::SectionUp(SwNodeRange *pRange)
1100 if( pRange->aStart >= pRange->aEnd ||
1101 pRange->aEnd >= Count() ||
1102 !CheckNodesRange( pRange->aStart, pRange->aEnd ) ||
1103 !( HighestLevel( *this, *pRange ) > 1 ))
1104 return;
1106 // Ist der Anfang vom Bereich vor oder auf einem StartNode, so loesche
1107 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
1108 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1109 SwNode * pAktNode = &pRange->aStart.GetNode();
1110 SwNodeIndex aIdx( *pAktNode->StartOfSectionNode() );
1111 if( pAktNode->IsStartNode() ) // selbst StartNode
1113 SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode();
1114 if( pAktNode == pEndNd->pStartOfSection )
1116 // dann wurde paarig aufgehoben, also nur die im Berich neu anpassen
1117 SwStartNode* pTmpSttNd = pAktNode->pStartOfSection;
1118 RemoveNode( pRange->aStart.GetIndex(), 1, TRUE );
1119 RemoveNode( pRange->aEnd.GetIndex(), 1, TRUE );
1121 SwNodeIndex aTmpIdx( pRange->aStart );
1122 while( aTmpIdx < pRange->aEnd )
1124 pAktNode = &aTmpIdx.GetNode();
1125 pAktNode->pStartOfSection = pTmpSttNd;
1126 if( pAktNode->IsStartNode() )
1127 aTmpIdx = pAktNode->EndOfSectionIndex() + 1;
1128 else
1129 aTmpIdx++;
1131 return ;
1133 DelNodes( pRange->aStart, 1 );
1135 else if( aIdx == pRange->aStart.GetIndex()-1 ) // vor StartNode
1136 DelNodes( aIdx, 1 );
1137 else
1138 new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() );
1140 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
1141 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes entstehen
1142 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1143 SwNodeIndex aTmpIdx( pRange->aEnd );
1144 if( pRange->aEnd.GetNode().IsEndNode() )
1145 DelNodes( pRange->aEnd, 1 );
1146 else
1148 pAktNode = new SwStartNode( pRange->aEnd );
1149 /*?? welcher NodeTyp ??*/
1150 aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode();
1151 pRange->aEnd--;
1154 SectionUpDown( aIdx, aTmpIdx );
1158 /*************************************************************************
1160 |* SwNodes::SectionUpDown()
1162 |* Beschreibung
1163 |* Methode setzt die Indizies die bei SectionUp oder SectionDwon
1164 |* veraendert wurden wieder richtig, sodass die Ebenen wieder
1165 |* Konsistent sind.
1167 |* Parameter
1168 |* SwIndex & aStart StartNode !!!
1169 |* SwIndex & aEnd EndPunkt
1171 |* Ersterstellung JP 23.04.91
1172 |* Letzte Aenderung JP 23.04.91
1174 *************************************************************************/
1175 void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd )
1177 SwNode * pAktNode;
1178 SwNodeIndex aTmpIdx( aStart, +1 );
1179 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
1180 SwSttNdPtrs aSttNdStack( 1, 5 );
1181 SwStartNode* pTmp = aStart.GetNode().GetStartNode();
1182 aSttNdStack.C40_INSERT( SwStartNode, pTmp, 0 );
1184 // durchlaufe bis der erste zu aendernde Start-Node gefunden wurde
1185 // ( Es wird vom eingefuegten EndNode bis nach vorne die Indexe gesetzt )
1186 for( ;; aTmpIdx++ )
1188 pAktNode = &aTmpIdx.GetNode();
1189 pAktNode->pStartOfSection = aSttNdStack[ aSttNdStack.Count()-1 ];
1191 if( pAktNode->GetStartNode() )
1193 pTmp = (SwStartNode*)pAktNode;
1194 aSttNdStack.C40_INSERT( SwStartNode, pTmp, aSttNdStack.Count() );
1196 else if( pAktNode->GetEndNode() )
1198 SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.Count() - 1 ];
1199 pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
1200 aSttNdStack.Remove( aSttNdStack.Count() - 1 );
1201 if( aSttNdStack.Count() )
1202 continue; // noch genuegend EndNodes auf dem Stack
1204 else if( aTmpIdx < aEnd ) // Uebergewicht an StartNodes
1205 // ist das Ende noch nicht erreicht, so hole den Start von
1206 // der uebergeordneten Section
1208 aSttNdStack.C40_INSERT( SwStartNode, pSttNd->pStartOfSection, 0 );
1210 else // wenn ueber den Bereich hinaus, dann Ende
1211 break;
1219 /*******************************************************************
1221 |* SwNodes::Delete
1223 |* Beschreibung
1224 |* Spezielle Implementierung der Delete-Funktion des
1225 |* variablen Array. Diese spezielle Implementierung ist
1226 |* notwendig, da durch das Loeschen von Start- bzw.
1227 |* Endnodes Inkonsistenzen entstehen koennen. Diese werden
1228 |* durch diese Funktion beseitigt.
1230 |* Parameter
1231 |* IN
1232 |* SwIndex &rIndex bezeichnet die Position, an der
1233 |* geloescht wird
1234 |* rIndex ist nach Aufruf der Funktion unveraendert (Kopie?!)
1235 |* USHORT nNodes bezeichnet die Anzahl der zu loeschenden
1236 |* Nodes; ist auf 1 defaulted
1238 |* Debug-Funktionen
1239 |* geben beim Eintritt in die Funktion Position und Anzahl
1240 |* der zu loeschenden Nodes aus.
1242 |* Ersterstellung
1243 |* VER0100 vb 901214
1245 |* Stand
1246 |* VER0100 vb 901214
1248 *******************************************************************/
1249 void SwNodes::Delete(const SwNodeIndex &rIndex, ULONG nNodes)
1251 USHORT nLevel = 0; // Level-Counter
1252 SwNode * pAktNode;
1254 ULONG nCnt = Count() - rIndex.GetIndex() - 1;
1255 if( nCnt > nNodes ) nCnt = nNodes;
1257 if( nCnt == 0 ) // keine Anzahl -> return
1258 return;
1260 SwNodeRange aRg( rIndex, 0, rIndex, nCnt-1 );
1261 // ueberprufe ob rIndex..rIndex + nCnt ueber einen Bereich hinausragt !!
1262 if( ( !aRg.aStart.GetNode().StartOfSectionIndex() &&
1263 !aRg.aStart.GetIndex() ) ||
1264 ! CheckNodesRange( aRg.aStart, aRg.aEnd ) )
1265 return;
1268 // falls aEnd auf keinem ContentNode steht, dann suche den vorherigen
1269 while( ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() ||
1270 ( pAktNode->GetEndNode() &&
1271 !pAktNode->pStartOfSection->IsTableNode() ))
1272 aRg.aEnd--;
1274 nCnt = 0;
1275 // Start erhoehen, damit auf < abgefragt wird. ( bei <= kann es zu
1276 // Problemen fuehren; ist aEnd == aStart und wird aEnd geloscht,
1277 // so ist aEnd <= aStart
1278 aRg.aStart--;
1280 BOOL bSaveInNodesDel = bInNodesDel;
1281 bInNodesDel = TRUE;
1282 BOOL bUpdateOutline = FALSE;
1284 // bis alles geloescht ist
1285 while( aRg.aStart < aRg.aEnd )
1287 pAktNode = &aRg.aEnd.GetNode();
1289 if( pAktNode->GetEndNode() )
1291 // die gesamte Section loeschen ?
1292 if( pAktNode->StartOfSectionIndex() > aRg.aStart.GetIndex() )
1294 SwTableNode* pTblNd = pAktNode->pStartOfSection->GetTableNode();
1295 if( pTblNd )
1296 pTblNd->DelFrms();
1298 SwNode *pNd, *pChkNd = pAktNode->pStartOfSection;
1299 USHORT nIdxPos;
1300 do {
1301 pNd = &aRg.aEnd.GetNode();
1303 if( pNd->IsTxtNode() )
1305 //if( NO_NUMBERING != //#outline level,zhaojianwei
1306 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() &&
1307 if( 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() &&//<-end,zhaojianwei
1308 pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
1310 // loesche die Gliederungs-Indizies.
1311 pOutlineNds->Remove( nIdxPos );
1312 bUpdateOutline = TRUE;
1314 ((SwTxtNode*)pNd)->InvalidateNumRule();
1316 else if( pNd->IsEndNode() &&
1317 pNd->pStartOfSection->IsTableNode() )
1318 ((SwTableNode*)pNd->pStartOfSection)->DelFrms();
1320 aRg.aEnd--;
1321 nCnt++;
1323 } while( pNd != pChkNd );
1325 else
1327 RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, TRUE ); // loesche
1328 nCnt = 0;
1329 aRg.aEnd--; // vor den EndNode
1330 nLevel++;
1333 else if( pAktNode->GetStartNode() ) // StartNode gefunden
1335 if( nLevel == 0 ) // es wird eine Stufe runter gestuft
1337 if( nCnt )
1339 // loesche jetzt das Array
1340 aRg.aEnd++;
1341 RemoveNode( aRg.aEnd.GetIndex(), nCnt, TRUE );
1342 nCnt = 0;
1345 else // es werden alle Nodes Innerhalb eines Start- und
1346 { // End-Nodes geloescht, loesche mit Start/EndNode
1347 RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, TRUE ); // loesche Array
1348 nCnt = 0;
1349 nLevel--;
1352 // nach dem loeschen kann aEnd auf einem EndNode stehen
1353 // loesche alle leeren Start-/End-Node-Paare
1354 SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1355 aRg.aEnd--;
1356 while( pTmpNode &&
1357 ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
1358 pAktNode->StartOfSectionIndex() )
1360 // loesche den EndNode und StartNode
1361 DelNodes( aRg.aEnd, 2 );
1362 pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1363 aRg.aEnd--;
1366 else // normaler Node, also ins TmpArray einfuegen
1368 SwTxtNode* pTxtNd = pAktNode->GetTxtNode();
1369 if( pTxtNd )
1371 if( pTxtNd->IsOutline())
1372 { // loesche die Gliederungs-Indizies.
1373 pOutlineNds->Remove( pTxtNd );
1374 bUpdateOutline = TRUE;
1376 pTxtNd->InvalidateNumRule();
1378 else if( pAktNode->IsCntntNode() )
1379 ((SwCntntNode*)pAktNode)->InvalidateNumRule();
1381 aRg.aEnd--;
1382 nCnt++;
1386 aRg.aEnd++;
1387 if( nCnt != 0 )
1388 RemoveNode( aRg.aEnd.GetIndex(), nCnt, TRUE ); // loesche den Rest
1390 // loesche alle leeren Start-/End-Node-Paare
1391 while( aRg.aEnd.GetNode().GetEndNode() &&
1392 ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
1393 pAktNode->StartOfSectionIndex() )
1394 // aber ja keinen der heiligen 5.
1396 DelNodes( aRg.aStart, 2 ); // loesche den Start- und EndNode
1397 aRg.aStart--;
1400 bInNodesDel = bSaveInNodesDel;
1402 if( !bInNodesDel )
1404 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
1405 if( bUpdateOutline || bInDelUpdOutl )
1407 UpdtOutlineIdx( aRg.aEnd.GetNode() );
1408 bInDelUpdOutl = FALSE;
1412 else
1414 if( bUpdateOutline )
1415 bInDelUpdOutl = TRUE;
1419 /*******************************************************************
1421 |* SwNodes::GetSectionLevel
1423 |* Beschreibung
1424 |* Die Funktion liefert den Sectionlevel an der durch
1425 |* aIndex bezeichneten Position. Die Funktion ruft die
1426 |* GetSectionlevel-Funktion des durch aIndex bezeichneten
1427 |* Nodes. Diese ist eine virtuelle Funktion, die fuer
1428 |* Endnodes speziell implementiert werden musste.
1429 |* Die Sectionlevels werden ermittelt, indem rekursiv durch
1430 |* die Nodesstruktur (jeweils zum naechsten theEndOfSection)
1431 |* gegangen wird, bis die oberste Ebene erreicht ist
1432 |* (theEndOfSection == 0)
1434 |* Parameter
1435 |* aIndex bezeichnet die Position des Nodes, dessen
1436 |* Sectionlevel ermittelt werden soll. Hier wird eine Kopie
1437 |* uebergeben, da eine Veraenderung der Variablen in der
1438 |* rufenden Funktion nicht wuenschenswert ist.
1440 |* Ausnahmen
1441 |* Der erste Node im Array sollte immer ein Startnode sein.
1442 |* Dieser erfaehrt in der Funktion SwNodes::GetSectionLevel()
1443 |* eine Sonderbehandlung; es wird davon ausgegangen, dass der
1444 |* erste Node auch ein Startnode ist.
1446 |* Ersterstellung
1447 |* VER0100 vb 901214
1449 |* Stand
1450 |* VER0100 vb 901214
1452 *******************************************************************/
1453 USHORT SwNodes::GetSectionLevel(const SwNodeIndex &rIdx) const {
1454 // Sonderbehandlung 1. Node
1455 if(rIdx == 0) return 1;
1457 * Keine Rekursion! - hier wird das SwNode::GetSectionLevel
1458 * aufgerufen
1460 return (*this)[rIdx]->GetSectionLevel();
1464 void SwNodes::GoStartOfSection(SwNodeIndex *pIdx) const
1466 // hinter den naechsten Startnode
1467 SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 );
1469 // steht der Index auf keinem ContentNode, dann gehe dahin. Ist aber
1470 // kein weiterer vorhanden, dann lasse den Index an alter Pos stehen !!!
1471 while( !aTmp.GetNode().IsCntntNode() )
1472 { // gehe vom StartNode ( es kann nur ein StartNode sein ! ) an sein
1473 // Ende
1474 if( *pIdx <= aTmp )
1475 return; // FEHLER: Steht schon hinter der Sektion
1476 aTmp = aTmp.GetNode().EndOfSectionIndex()+1;
1477 if( *pIdx <= aTmp )
1478 return; // FEHLER: Steht schon hinter der Sektion
1480 (*pIdx) = aTmp; // steht auf einem ContentNode
1483 void SwNodes::GoEndOfSection(SwNodeIndex *pIdx) const
1485 // falls er vor einem Endnode steht --> nichts tun
1486 if( !pIdx->GetNode().IsEndNode() )
1487 (*pIdx) = *pIdx->GetNode().EndOfSectionNode();
1490 SwCntntNode* SwNodes::GoNext(SwNodeIndex *pIdx) const
1492 if( pIdx->GetIndex() >= Count() - 1 )
1493 return 0;
1495 SwNodeIndex aTmp(*pIdx, +1);
1496 SwNode* pNd = 0;
1497 while( aTmp < Count()-1 && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
1498 aTmp++;
1500 if( aTmp == Count()-1 )
1501 pNd = 0;
1502 else
1503 (*pIdx) = aTmp;
1504 return (SwCntntNode*)pNd;
1507 SwCntntNode* SwNodes::GoPrevious(SwNodeIndex *pIdx) const
1509 if( !pIdx->GetIndex() )
1510 return 0;
1512 SwNodeIndex aTmp( *pIdx, -1 );
1513 SwNode* pNd = 0;
1514 while( aTmp.GetIndex() && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
1515 aTmp--;
1517 if( !aTmp.GetIndex() )
1518 pNd = 0;
1519 else
1520 (*pIdx) = aTmp;
1521 return (SwCntntNode*)pNd;
1524 SwNode* SwNodes::GoNextWithFrm(SwNodeIndex *pIdx) const
1526 if( pIdx->GetIndex() >= Count() - 1 )
1527 return 0;
1529 SwNodeIndex aTmp(*pIdx, +1);
1530 SwNode* pNd = 0;
1531 while( aTmp < Count()-1 )
1533 pNd = &aTmp.GetNode();
1534 SwModify *pMod = 0;
1535 if ( pNd->IsCntntNode() )
1536 pMod = (SwCntntNode*)pNd;
1537 else if ( pNd->IsTableNode() )
1538 pMod = ((SwTableNode*)pNd)->GetTable().GetFrmFmt();
1539 else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() )
1541 pNd = 0;
1542 break;
1544 if ( pMod && pMod->GetDepends() )
1546 SwClientIter aIter( *pMod );
1547 if( aIter.First( TYPE(SwFrm) ) )
1548 break;
1550 aTmp++;
1552 if( aTmp == Count()-1 )
1553 pNd = 0;
1554 else if( pNd )
1555 (*pIdx) = aTmp;
1556 return pNd;
1559 SwNode* SwNodes::GoPreviousWithFrm(SwNodeIndex *pIdx) const
1561 if( !pIdx->GetIndex() )
1562 return 0;
1564 SwNodeIndex aTmp( *pIdx, -1 );
1565 SwNode* pNd(0);
1566 while( aTmp.GetIndex() )
1568 pNd = &aTmp.GetNode();
1569 SwModify *pMod = 0;
1570 if ( pNd->IsCntntNode() )
1571 pMod = (SwCntntNode*)pNd;
1572 else if ( pNd->IsTableNode() )
1573 pMod = ((SwTableNode*)pNd)->GetTable().GetFrmFmt();
1574 else if( pNd->IsStartNode() && !pNd->IsSectionNode() )
1576 pNd = 0;
1577 break;
1579 if ( pMod && pMod->GetDepends() )
1581 SwClientIter aIter( *pMod );
1582 if( aIter.First( TYPE(SwFrm) ) )
1583 break;
1585 aTmp--;
1588 if( !aTmp.GetIndex() )
1589 pNd = 0;
1590 else if( pNd )
1591 (*pIdx) = aTmp;
1592 return pNd;
1597 /*************************************************************************
1599 |* BOOL SwNodes::CheckNodesRange()
1601 |* Beschreibung
1602 |* Teste ob der uebergene SRange nicht ueber die Grenzen der
1603 |* einzelnen Bereiche (PosIts, Autotext, Content, Icons und Inserts )
1604 |* hinaus reicht.
1605 |* Nach Wahrscheinlichkeit des Ranges sortiert.
1607 |* Alg.: Da festgelegt ist, das aRange.aEnd den 1.Node hinter dem Bereich
1608 |* bezeichnet, wird hier auf aEnd <= End.. getestet !!
1610 |* Parameter SwIndex & Start-Index vom Bereich
1611 |* SwIndex & End-Index vom Bereich
1612 |* BOOL TRUE: Start+End in gleicher Section!
1613 |* FALSE: Start+End in verschiedenen Sect.
1614 |* Return-Wert BOOL TRUE: gueltiger SRange
1615 |* FALSE: ungueltiger SRange
1617 |* Ersterstellung JP 23.04.91
1618 |* Letzte Aenderung JP 18.06.92
1620 *************************************************************************/
1622 inline int TstIdx( ULONG nSttIdx, ULONG nEndIdx, ULONG nStt, ULONG nEnd )
1624 return nStt < nSttIdx && nEnd >= nSttIdx &&
1625 nStt < nEndIdx && nEnd >= nEndIdx;
1628 BOOL SwNodes::CheckNodesRange( const SwNodeIndex& rStt, const SwNodeIndex& rEnd ) const
1630 ULONG nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
1631 if( TstIdx( nStt, nEnd, pEndOfContent->StartOfSectionIndex(),
1632 pEndOfContent->GetIndex() )) return TRUE;
1633 if( TstIdx( nStt, nEnd, pEndOfAutotext->StartOfSectionIndex(),
1634 pEndOfAutotext->GetIndex() )) return TRUE;
1635 if( TstIdx( nStt, nEnd, pEndOfPostIts->StartOfSectionIndex(),
1636 pEndOfPostIts->GetIndex() )) return TRUE;
1637 if( TstIdx( nStt, nEnd, pEndOfInserts->StartOfSectionIndex(),
1638 pEndOfInserts->GetIndex() )) return TRUE;
1639 if( TstIdx( nStt, nEnd, pEndOfRedlines->StartOfSectionIndex(),
1640 pEndOfRedlines->GetIndex() )) return TRUE;
1642 return FALSE; // liegt irgendwo dazwischen, FEHLER
1646 /*************************************************************************
1648 |* void SwNodes::DelNodes()
1650 |* Beschreibung
1651 |* Loesche aus den NodesArray ab einer Position entsprechend Node's.
1653 |* Parameter SwIndex & Der Startpunkt im Nodes-Array
1654 |* USHORT die Anzahl
1656 |* Ersterstellung JP 23.04.91
1657 |* Letzte Aenderung JP 23.04.91
1659 *************************************************************************/
1660 void SwNodes::DelNodes( const SwNodeIndex & rStart, ULONG nCnt )
1662 int bUpdateNum = 0;
1663 ULONG nSttIdx = rStart.GetIndex();
1665 if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 )
1667 // es wird das gesamte Nodes-Array zerstoert, man ist im Doc DTOR!
1668 // Die initialen Start-/End-Nodes duerfen nur im SwNodes-DTOR
1669 // zerstoert werden!
1670 SwNode* aEndNdArr[] = { pEndOfContent,
1671 pEndOfPostIts, pEndOfInserts,
1672 pEndOfAutotext, pEndOfRedlines,
1676 SwNode** ppEndNdArr = aEndNdArr;
1677 while( *ppEndNdArr )
1679 nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1;
1680 ULONG nEndIdx = (*ppEndNdArr)->GetIndex();
1682 if( nSttIdx != nEndIdx )
1683 RemoveNode( nSttIdx, nEndIdx - nSttIdx, TRUE );
1685 ++ppEndNdArr;
1688 else
1690 for( ULONG n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n )
1692 SwNode* pNd = (*this)[ n ];
1694 if( pNd->IsTxtNode() &&
1695 //NO_NUMBERING != ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
1696 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() ) //<-end,zhaojianwei
1697 { // loesche die Gliederungs-Indizies.
1698 USHORT nIdxPos;
1699 if( pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
1701 pOutlineNds->Remove( nIdxPos );
1702 bUpdateNum = 1;
1705 if( pNd->IsCntntNode() )
1707 ((SwCntntNode*)pNd)->InvalidateNumRule();
1708 ((SwCntntNode*)pNd)->DelFrms();
1711 RemoveNode( nSttIdx, nCnt, TRUE );
1713 // rufe noch das Update fuer die Gliederungsnumerierung auf
1714 if( bUpdateNum )
1715 UpdtOutlineIdx( rStart.GetNode() );
1720 /*************************************************************************
1722 |* USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1724 |* Beschreibung
1725 |* Berechne den hoehsten Level innerhalb des Bereiches
1727 |* Parameter SwNodes & das Node-Array
1728 |* SwNodeRange & der zu ueberpruefende Bereich
1729 |* Return USHORT der hoechste Level
1731 |* Ersterstellung JP 24.04.91
1732 |* Letzte Aenderung JP 24.04.91
1734 *************************************************************************/
1736 struct HighLevel
1738 USHORT nLevel, nTop;
1739 HighLevel( USHORT nLv ) : nLevel( nLv ), nTop( nLv ) {}
1743 BOOL _HighestLevel( const SwNodePtr& rpNode, void * pPara )
1745 HighLevel * pHL = (HighLevel*)pPara;
1746 if( rpNode->GetStartNode() )
1747 pHL->nLevel++;
1748 else if( rpNode->GetEndNode() )
1749 pHL->nLevel--;
1750 if( pHL->nTop > pHL->nLevel )
1751 pHL->nTop = pHL->nLevel;
1752 return TRUE;
1756 USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1758 HighLevel aPara( rNodes.GetSectionLevel( rRange.aStart ));
1759 rNodes.ForEach( rRange.aStart, rRange.aEnd, _HighestLevel, &aPara );
1760 return aPara.nTop;
1764 /*************************************************************************
1766 |* SwNodes::Move()
1768 |* Beschreibung
1769 |* Parameter SwPaM& zu kopierender Bereich
1770 |* SwNodes& in dieses Nodes-Array
1771 |* SwPosition& auf diese Position im Nodes-Array
1772 |* Ersterstellung JP 09.07.92
1773 |* Letzte Aenderung JP 09.07.92
1775 *************************************************************************/
1776 void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
1778 SwPosition * const pStt = rPam.Start();
1779 SwPosition * const pEnd = rPam.End();
1781 if( !rPam.HasMark() || *pStt >= *pEnd )
1782 return;
1784 if( this == &rNodes && *pStt <= rPos && rPos < *pEnd )
1785 return;
1787 SwNodeIndex aEndIdx( pEnd->nNode );
1788 SwNodeIndex aSttIdx( pStt->nNode );
1789 SwTxtNode* const pSrcNd = (*this)[ aSttIdx ]->GetTxtNode();
1790 SwTxtNode* pDestNd = rNodes[ rPos.nNode ]->GetTxtNode();
1791 BOOL bSplitDestNd = TRUE;
1792 BOOL bCopyCollFmt = pDestNd && !pDestNd->GetTxt().Len();
1794 if( pSrcNd )
1796 // ist der 1.Node ein TextNode, dann muss im NodesArray auch
1797 // ein TextNode vorhanden sein, in den der Inhalt geschoben wird
1798 if( !pDestNd )
1800 pDestNd = rNodes.MakeTxtNode( rPos.nNode, pSrcNd->GetTxtColl() );
1801 rPos.nNode--;
1802 rPos.nContent.Assign( pDestNd, 0 );
1803 bCopyCollFmt = TRUE;
1805 bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() ||
1806 pEnd->nNode.GetNode().IsTxtNode();
1808 // verschiebe jetzt noch den Inhalt in den neuen Node
1809 BOOL bOneNd = pStt->nNode == pEnd->nNode;
1810 const xub_StrLen nLen =
1811 ( (bOneNd) ? pEnd->nContent.GetIndex() : pSrcNd->Len() )
1812 - pStt->nContent.GetIndex();
1814 if( !pEnd->nNode.GetNode().IsCntntNode() )
1816 bOneNd = TRUE;
1817 ULONG nSttNdIdx = pStt->nNode.GetIndex() + 1;
1818 const ULONG nEndNdIdx = pEnd->nNode.GetIndex();
1819 for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx )
1821 if( (*this)[ nSttNdIdx ]->IsCntntNode() )
1823 bOneNd = FALSE;
1824 break;
1829 // das kopieren / setzen der Vorlagen darf erst nach
1830 // dem Splitten erfolgen
1831 if( !bOneNd && bSplitDestNd )
1833 if( !rPos.nContent.GetIndex() )
1835 bCopyCollFmt = TRUE;
1837 if( rNodes.IsDocNodes() )
1839 SwDoc* const pInsDoc = pDestNd->GetDoc();
1840 const bool bIsUndo = pInsDoc->DoesUndo();
1841 pInsDoc->DoUndo( false );
1842 pInsDoc->SplitNode( rPos, false );
1843 pInsDoc->DoUndo( bIsUndo );
1845 else
1847 pDestNd->SplitCntntNode( rPos );
1850 if( rPos.nNode == aEndIdx )
1852 aEndIdx--;
1854 bSplitDestNd = TRUE;
1856 pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTxtNode();
1857 if( nLen )
1859 pSrcNd->CutText( pDestNd, SwIndex( pDestNd, pDestNd->Len()),
1860 pStt->nContent, nLen );
1863 else if ( nLen )
1865 pSrcNd->CutText( pDestNd, rPos.nContent, pStt->nContent, nLen );
1868 if( bCopyCollFmt )
1870 SwDoc* const pInsDoc = pDestNd->GetDoc();
1871 const bool bIsUndo = pInsDoc->DoesUndo();
1872 pInsDoc->DoUndo( false );
1873 pSrcNd->CopyCollFmt( *pDestNd );
1874 pInsDoc->DoUndo( bIsUndo );
1875 bCopyCollFmt = FALSE;
1878 if( bOneNd ) // das wars schon
1880 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
1881 // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
1882 // wird aufgehoben !
1883 pEnd->nContent = pStt->nContent;
1884 rPam.DeleteMark();
1885 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
1886 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
1887 return;
1890 aSttIdx++;
1892 else if( pDestNd )
1894 if( rPos.nContent.GetIndex() )
1896 if( rPos.nContent.GetIndex() == pDestNd->Len() )
1898 rPos.nNode++;
1900 else if( rPos.nContent.GetIndex() )
1902 // falls im EndNode gesplittet wird, dann muss der EndIdx
1903 // korrigiert werden !!
1904 const bool bCorrEnd = aEndIdx == rPos.nNode;
1905 // es wird kein Text an den TextNode angehaengt, also splitte ihn
1907 if( rNodes.IsDocNodes() )
1909 SwDoc* const pInsDoc = pDestNd->GetDoc();
1910 const bool bIsUndo = pInsDoc->DoesUndo();
1911 pInsDoc->DoUndo( false );
1912 pInsDoc->SplitNode( rPos, false );
1913 pInsDoc->DoUndo( bIsUndo );
1915 else
1917 pDestNd->SplitCntntNode( rPos );
1920 pDestNd = rPos.nNode.GetNode().GetTxtNode();
1922 if ( bCorrEnd )
1924 aEndIdx--;
1928 // am Ende steht noch ein leerer Text Node herum.
1929 bSplitDestNd = TRUE;
1932 SwTxtNode* const pEndSrcNd = (*this)[ aEndIdx ]->GetTxtNode();
1933 if ( pEndSrcNd )
1936 // am Bereichsende entsteht ein neuer TextNode
1937 if( !bSplitDestNd )
1939 if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() )
1941 rPos.nNode++;
1944 pDestNd =
1945 rNodes.MakeTxtNode( rPos.nNode, pEndSrcNd->GetTxtColl() );
1946 rPos.nNode--;
1947 rPos.nContent.Assign( pDestNd, 0 );
1949 else
1951 pDestNd = rNodes[ rPos.nNode ]->GetTxtNode();
1954 if( pDestNd && pEnd->nContent.GetIndex() )
1956 // verschiebe jetzt noch den Inhalt in den neuen Node
1957 SwIndex aIdx( pEndSrcNd, 0 );
1958 pEndSrcNd->CutText( pDestNd, rPos.nContent, aIdx,
1959 pEnd->nContent.GetIndex());
1962 if( bCopyCollFmt )
1964 SwDoc* const pInsDoc = pDestNd->GetDoc();
1965 const bool bIsUndo = pInsDoc->DoesUndo();
1966 pInsDoc->DoUndo( false );
1967 pEndSrcNd->CopyCollFmt( *pDestNd );
1968 pInsDoc->DoUndo( bIsUndo );
1972 else
1974 if ( pSrcNd && aEndIdx.GetNode().IsCntntNode() )
1976 aEndIdx++;
1978 if( !bSplitDestNd )
1980 rPos.nNode++;
1981 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 );
1985 if( aEndIdx != aSttIdx )
1987 // verschiebe jetzt die Nodes in das NodesArary
1988 const ULONG nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex();
1989 SwNodeRange aRg( aSttIdx, aEndIdx );
1990 _MoveNodes( aRg, rNodes, rPos.nNode );
1991 // falls ins gleiche Nodes-Array verschoben wurde, stehen die
1992 // Indizies jetzt auch an der neuen Position !!!!
1993 // (also alles wieder umsetzen)
1994 if( &rNodes == this )
1996 pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff;
2000 // falls der Start-Node verschoben wurde, in dem der Cursor stand, so
2001 // muss der Content im akt. Content angemeldet werden !!!
2002 if ( &pStt->nNode.GetNode() == &GetEndOfContent() )
2004 const bool bSuccess = GoPrevious( &pStt->nNode );
2005 ASSERT( bSuccess, "Move() - no ContentNode here" );
2006 (void) bSuccess;
2008 pStt->nContent.Assign( (*this)[ pStt->nNode ]->GetCntntNode(),
2009 pStt->nContent.GetIndex() );
2010 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
2011 // wurde, so stehen sie in unterschielichen Nodes. Auch die Selektion
2012 // wird aufgehoben !
2013 *pEnd = *pStt;
2014 rPam.DeleteMark();
2015 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
2016 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
2021 /*************************************************************************
2023 |* SwNodes::_Copy()
2025 |* Beschreibung
2026 |* Parameter SwNodeRange& zu kopierender Bereich
2027 |* SwDoc& in dieses Dokument
2028 |* SwIndex& auf diese Position im Nodes-Array
2029 |* Ersterstellung JP 11.11.92
2030 |* Letzte Aenderung JP 11.11.92
2032 *************************************************************************/
2034 inline BYTE MaxLvl( BYTE nMin, BYTE nMax, short nNew )
2036 return (BYTE)(nNew < nMin ? nMin : nNew > nMax ? nMax : nNew);
2039 void SwNodes::_CopyNodes( const SwNodeRange& rRange,
2040 const SwNodeIndex& rIndex, BOOL bNewFrms, BOOL bTblInsDummyNode ) const
2042 SwDoc* pDoc = rIndex.GetNode().GetDoc();
2044 SwNode * pAktNode;
2045 if( rIndex == 0 ||
2046 ( (pAktNode = &rIndex.GetNode())->GetStartNode() &&
2047 !pAktNode->StartOfSectionIndex() ))
2048 return;
2050 SwNodeRange aRg( rRange );
2052 // "einfache" StartNodes oder EndNodes ueberspringen
2053 while( ND_STARTNODE == (pAktNode = (*this)[ aRg.aStart ])->GetNodeType()
2054 || ( pAktNode->IsEndNode() &&
2055 !pAktNode->pStartOfSection->IsSectionNode() ) )
2056 aRg.aStart++;
2058 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
2059 aRg.aEnd--;
2060 while( (( pAktNode = (*this)[ aRg.aEnd ])->GetStartNode() &&
2061 !pAktNode->IsSectionNode() ) ||
2062 ( pAktNode->IsEndNode() &&
2063 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) )
2064 aRg.aEnd--;
2065 aRg.aEnd++;
2067 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
2068 if( aRg.aStart >= aRg.aEnd )
2069 return;
2071 // when inserting into the source range, nothing need to be done
2072 DBG_ASSERT( &aRg.aStart.GetNodes() == this,
2073 "aRg should use thisnodes array" );
2074 DBG_ASSERT( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(),
2075 "Range across different nodes arrays? You deserve punishment!");
2076 if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() &&
2077 rIndex.GetIndex() >= aRg.aStart.GetIndex() &&
2078 rIndex.GetIndex() < aRg.aEnd.GetIndex() )
2079 return;
2081 SwNodeIndex aInsPos( rIndex );
2082 SwNodeIndex aOrigInsPos( rIndex, -1 ); // Originale Insert Pos
2083 USHORT nLevel = 0; // Level-Counter
2085 for( ULONG nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
2086 nNodeCnt > 0; --nNodeCnt )
2088 pAktNode = &aRg.aStart.GetNode();
2089 switch( pAktNode->GetNodeType() )
2091 case ND_TABLENODE:
2092 // dann kopiere mal den TableNode
2093 // Tabell in Fussnote kopieren ?
2094 if( aInsPos < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
2095 pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex()
2096 < aInsPos.GetIndex() )
2098 nNodeCnt -=
2099 ( pAktNode->EndOfSectionIndex() -
2100 aRg.aStart.GetIndex() );
2102 // dann alle Nodes der Tabelle in die akt. Zelle kopieren
2103 // fuer den TabellenNode einen DummyNode einfuegen?
2104 if( bTblInsDummyNode )
2105 new SwNode( aInsPos, ND_SECTIONDUMMY );
2107 for( aRg.aStart++; aRg.aStart.GetIndex() <
2108 pAktNode->EndOfSectionIndex();
2109 aRg.aStart++ )
2111 // fuer den Box-StartNode einen DummyNode einfuegen?
2112 if( bTblInsDummyNode )
2113 new SwNode( aInsPos, ND_SECTIONDUMMY );
2115 SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode();
2116 _CopyNodes( SwNodeRange( *pSttNd, + 1,
2117 *pSttNd->EndOfSectionNode() ),
2118 aInsPos, bNewFrms, FALSE );
2120 // fuer den Box-EndNode einen DummyNode einfuegen?
2121 if( bTblInsDummyNode )
2122 new SwNode( aInsPos, ND_SECTIONDUMMY );
2123 aRg.aStart = *pSttNd->EndOfSectionNode();
2125 // fuer den TabellenEndNode einen DummyNode einfuegen?
2126 if( bTblInsDummyNode )
2127 new SwNode( aInsPos, ND_SECTIONDUMMY );
2128 aRg.aStart = *pAktNode->EndOfSectionNode();
2130 else
2132 SwNodeIndex nStt( aInsPos, -1 );
2133 SwTableNode* pTblNd = ((SwTableNode*)pAktNode)->
2134 MakeCopy( pDoc, aInsPos );
2135 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2;
2137 aRg.aStart = pAktNode->EndOfSectionIndex();
2139 if( bNewFrms && pTblNd )
2141 nStt = aInsPos;
2142 pTblNd->MakeFrms( &nStt );
2145 break;
2147 case ND_SECTIONNODE: // SectionNode
2148 // If the end of the section is outside the copy range,
2149 // the section node will skipped, not copied!
2150 // If someone want to change this behaviour, he has to adjust the function
2151 // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
2152 if( pAktNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
2154 // also der gesamte, lege einen neuen SectionNode an
2155 SwNodeIndex nStt( aInsPos, -1 );
2156 SwSectionNode* pSectNd = ((SwSectionNode*)pAktNode)->
2157 MakeCopy( pDoc, aInsPos );
2159 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2;
2160 aRg.aStart = pAktNode->EndOfSectionIndex();
2162 if( bNewFrms && pSectNd &&
2163 !pSectNd->GetSection().IsHidden() )
2164 pSectNd->MakeFrms( &nStt );
2166 break;
2168 case ND_STARTNODE: // StartNode gefunden
2170 SwStartNode* pTmp = new SwStartNode( aInsPos, ND_STARTNODE,
2171 ((SwStartNode*)pAktNode)->GetStartNodeType() );
2172 new SwEndNode( aInsPos, *pTmp );
2173 aInsPos--;
2174 nLevel++;
2176 break;
2178 case ND_ENDNODE:
2179 if( nLevel ) // vollstaendige Section
2181 --nLevel;
2182 aInsPos++; // EndNode schon vorhanden
2184 else if( !pAktNode->pStartOfSection->IsSectionNode() )
2186 // erzeuge eine Section an der originalen InsertPosition
2187 SwNodeRange aTmpRg( aOrigInsPos, 1, aInsPos );
2188 pDoc->GetNodes().SectionDown( &aTmpRg,
2189 pAktNode->pStartOfSection->GetStartNodeType() );
2191 break;
2193 case ND_TEXTNODE:
2194 case ND_GRFNODE:
2195 case ND_OLENODE:
2197 SwCntntNode* pNew = ((SwCntntNode*)pAktNode)->MakeCopy(
2198 pDoc, aInsPos );
2199 if( !bNewFrms ) // dflt. werden die Frames immer angelegt
2200 pNew->DelFrms();
2202 break;
2204 case ND_SECTIONDUMMY:
2205 if( (const SwNodes*)this == GetDoc()->GetUndoNds() )
2207 // dann muss an der akt. InsPos auch ein SectionNode
2208 // (Start/Ende) stehen; dann diesen ueberspringen.
2209 // Andernfalls nicht weiter beachten.
2210 SwNode* pTmpNd = pDoc->GetNodes()[ aInsPos ];
2211 if( pTmpNd->IsSectionNode() ||
2212 pTmpNd->StartOfSectionNode()->IsSectionNode() )
2213 aInsPos++; // ueberspringen
2215 else {
2216 ASSERT( FALSE, "wie kommt diser Node ins Nodes-Array??" );
2218 break;
2220 default:
2221 ASSERT( FALSE, "weder Start-/End-/Content-Node, unbekannter Typ" );
2223 aRg.aStart++;
2227 #ifdef JP_DEBUG
2229 extern Writer* GetDebugWriter(const String&);
2231 Writer* pWriter = GetDebugWriter(aEmptyStr);
2232 if( pWriter )
2234 int nError;
2235 SvFileStream aStrm( "c:\\$$copy.db", STREAM_WRITE );
2236 SwWriter aWriter( aStrm, *pMyDoc );
2237 aWriter.Write( &nError, pWriter );
2240 #endif
2243 void SwNodes::_DelDummyNodes( const SwNodeRange& rRg )
2245 SwNodeIndex aIdx( rRg.aStart );
2246 while( aIdx.GetIndex() < rRg.aEnd.GetIndex() )
2248 if( ND_SECTIONDUMMY == aIdx.GetNode().GetNodeType() )
2249 RemoveNode( aIdx.GetIndex(), 1, TRUE );
2250 else
2251 aIdx++;
2255 SwStartNode* SwNodes::MakeEmptySection( const SwNodeIndex& rIdx,
2256 SwStartNodeType eSttNdTyp )
2258 SwStartNode* pSttNd = new SwStartNode( rIdx, ND_STARTNODE, eSttNdTyp );
2259 new SwEndNode( rIdx, *pSttNd );
2260 return pSttNd;
2264 SwStartNode* SwNodes::MakeTextSection( const SwNodeIndex & rWhere,
2265 SwStartNodeType eSttNdTyp,
2266 SwTxtFmtColl *pColl,
2267 SwAttrSet* pAutoAttr )
2269 SwStartNode* pSttNd = new SwStartNode( rWhere, ND_STARTNODE, eSttNdTyp );
2270 new SwEndNode( rWhere, *pSttNd );
2271 MakeTxtNode( SwNodeIndex( rWhere, - 1 ), pColl, pAutoAttr );
2272 return pSttNd;
2275 // zum naechsten Content-Node, der nicht geschuetzt oder versteckt ist
2276 // (beides auf FALSE ==> GoNext/GoPrevious!!!)
2277 SwCntntNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
2278 int bSkipHidden, int bSkipProtect ) const
2280 int bFirst = TRUE;
2281 SwNodeIndex aTmp( *pIdx );
2282 const SwNode* pNd;
2283 while( aTmp < Count() - 1 )
2285 if( ND_SECTIONNODE == ( pNd = (*this)[aTmp])->GetNodeType() )
2287 const SwSection& rSect = ((SwSectionNode*)pNd)->GetSection();
2288 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2289 (bSkipProtect && rSect.IsProtectFlag()) )
2290 // dann diese Section ueberspringen
2291 aTmp = *pNd->EndOfSectionNode();
2292 bFirst = FALSE;
2294 else if( bFirst )
2296 bFirst = FALSE;
2297 if( pNd->pStartOfSection->IsSectionNode() )
2299 const SwSection& rSect = ((SwSectionNode*)pNd->
2300 pStartOfSection)->GetSection();
2301 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2302 (bSkipProtect && rSect.IsProtectFlag()) )
2303 // dann diese Section ueberspringen
2304 aTmp = *pNd->EndOfSectionNode();
2307 else if( ND_CONTENTNODE & pNd->GetNodeType() )
2309 const SwSectionNode* pSectNd;
2310 if( ( bSkipHidden || bSkipProtect ) &&
2311 0 != (pSectNd = pNd->FindSectionNode() ) &&
2312 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
2313 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2315 aTmp = *pSectNd->EndOfSectionNode();
2317 else
2319 (*pIdx) = aTmp;
2320 return (SwCntntNode*)pNd;
2323 aTmp++;
2324 bFirst = FALSE;
2326 return 0;
2329 SwCntntNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
2330 int bSkipHidden, int bSkipProtect ) const
2332 int bFirst = TRUE;
2333 SwNodeIndex aTmp( *pIdx );
2334 const SwNode* pNd;
2335 while( aTmp > 0 )
2337 if( ND_ENDNODE == ( pNd = (*this)[aTmp])->GetNodeType() )
2339 if( pNd->pStartOfSection->IsSectionNode() )
2341 const SwSection& rSect = ((SwSectionNode*)pNd->
2342 pStartOfSection)->GetSection();
2343 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2344 (bSkipProtect && rSect.IsProtectFlag()) )
2345 // dann diese Section ueberspringen
2346 aTmp = *pNd->StartOfSectionNode();
2348 bFirst = FALSE;
2350 else if( bFirst )
2352 bFirst = FALSE;
2353 if( pNd->pStartOfSection->IsSectionNode() )
2355 const SwSection& rSect = ((SwSectionNode*)pNd->
2356 pStartOfSection)->GetSection();
2357 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2358 (bSkipProtect && rSect.IsProtectFlag()) )
2359 // dann diese Section ueberspringen
2360 aTmp = *pNd->StartOfSectionNode();
2363 else if( ND_CONTENTNODE & pNd->GetNodeType() )
2365 const SwSectionNode* pSectNd;
2366 if( ( bSkipHidden || bSkipProtect ) &&
2367 0 != (pSectNd = pNd->FindSectionNode() ) &&
2368 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
2369 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2371 aTmp = *pSectNd;
2373 else
2375 (*pIdx) = aTmp;
2376 return (SwCntntNode*)pNd;
2379 aTmp--;
2381 return 0;
2385 // suche den vorhergehenden [/nachfolgenden ] ContentNode oder
2386 // TabellenNode mit Frames. Wird kein Ende angeben, dann wird mit
2387 // dem FrameIndex begonnen; ansonsten, wird mit dem vor rFrmIdx und
2388 // dem hintern pEnd die Suche gestartet. Sollte kein gueltiger Node
2389 // gefunden werden, wird 0 returnt. rFrmIdx zeigt auf dem Node mit
2390 // Frames
2391 SwNode* SwNodes::FindPrvNxtFrmNode( SwNodeIndex& rFrmIdx,
2392 const SwNode* pEnd ) const
2394 SwNode* pFrmNd = 0;
2396 // habe wir gar kein Layout, vergiss es
2397 if( GetDoc()->GetRootFrm() )
2399 SwNode* pSttNd = &rFrmIdx.GetNode();
2401 // wird in eine versteckte Section verschoben ??
2402 SwSectionNode* pSectNd = pSttNd->IsSectionNode()
2403 ? pSttNd->StartOfSectionNode()->FindSectionNode()
2404 : pSttNd->FindSectionNode();
2405 if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag()/*IsHiddenFlag()*/ ) )
2407 // #130650# in a table in table situation we have to assure that we don't leave the
2408 // outer table cell when the inner table is looking for a PrvNxt...
2409 SwTableNode* pTableNd = pSttNd->IsTableNode()
2410 ? pSttNd->StartOfSectionNode()->FindTableNode()
2411 : pSttNd->FindTableNode();
2412 SwNodeIndex aIdx( rFrmIdx );
2413 SwNode* pNd;
2414 if( pEnd )
2416 aIdx--;
2417 pNd = &aIdx.GetNode();
2419 else
2420 pNd = pSttNd;
2422 if( ( pFrmNd = pNd )->IsCntntNode() )
2423 rFrmIdx = aIdx;
2425 // suche nach vorne/hinten nach einem Content Node
2426 else if( 0 != ( pFrmNd = GoPrevSection( &aIdx, TRUE, FALSE )) &&
2427 ::CheckNodesRange( aIdx, rFrmIdx, TRUE ) &&
2428 // nach vorne nie aus der Tabelle hinaus!
2429 pFrmNd->FindTableNode() == pTableNd &&
2430 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
2431 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
2432 == pSttNd->FindTableBoxStartNode() ) &&
2433 (!pSectNd || pSttNd->IsSectionNode() ||
2434 pSectNd->GetIndex() < pFrmNd->GetIndex())
2437 rFrmIdx = aIdx;
2439 else
2441 if( pEnd )
2442 aIdx = pEnd->GetIndex() + 1;
2443 else
2444 aIdx = rFrmIdx;
2446 // JP 19.09.93: aber nie die Section dafuer verlassen !!
2447 if( ( pEnd && ( pFrmNd = &aIdx.GetNode())->IsCntntNode() ) ||
2448 ( 0 != ( pFrmNd = GoNextSection( &aIdx, TRUE, FALSE )) &&
2449 ::CheckNodesRange( aIdx, rFrmIdx, TRUE ) &&
2450 ( pFrmNd->FindTableNode() == pTableNd &&
2451 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
2452 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
2453 == pSttNd->FindTableBoxStartNode() ) ) &&
2454 (!pSectNd || pSttNd->IsSectionNode() ||
2455 pSectNd->EndOfSectionIndex() > pFrmNd->GetIndex())
2458 //JP 18.02.99: Undo von Merge einer Tabelle mit der
2459 // der vorherigen, wenn dahinter auch noch eine steht
2460 // falls aber der Node in einer Tabelle steht, muss
2461 // natuerlich dieser returnt werden, wenn der SttNode eine
2462 // Section oder Tabelle ist!
2463 SwTableNode* pTblNd;
2464 if( pSttNd->IsTableNode() &&
2465 0 != ( pTblNd = pFrmNd->FindTableNode() ) &&
2466 // TABLE IN TABLE:
2467 pTblNd != pSttNd->StartOfSectionNode()->FindTableNode() )
2469 pFrmNd = pTblNd;
2470 rFrmIdx = *pFrmNd;
2472 else
2473 rFrmIdx = aIdx;
2475 else if( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
2477 pFrmNd = pNd->StartOfSectionNode();
2478 rFrmIdx = *pFrmNd;
2480 else
2482 if( pEnd )
2483 aIdx = pEnd->GetIndex() + 1;
2484 else
2485 aIdx = rFrmIdx.GetIndex() + 1;
2487 if( (pFrmNd = &aIdx.GetNode())->IsTableNode() )
2488 rFrmIdx = aIdx;
2489 else
2491 pFrmNd = 0;
2493 // is there some sectionnodes before a tablenode?
2494 while( aIdx.GetNode().IsSectionNode() )
2496 const SwSection& rSect = aIdx.GetNode().
2497 GetSectionNode()->GetSection();
2498 if( rSect.IsHiddenFlag() )
2499 aIdx = aIdx.GetNode().EndOfSectionIndex()+1;
2500 else
2501 aIdx++;
2503 if( aIdx.GetNode().IsTableNode() )
2505 rFrmIdx = aIdx;
2506 pFrmNd = &aIdx.GetNode();
2513 return pFrmNd;
2516 void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
2517 FnForEach_SwNodes fnForEach, void* pArgs )
2519 BigPtrArray::ForEach( rStart.GetIndex(), rEnd.GetIndex(),
2520 (FnForEach) fnForEach, pArgs );
2523 struct _TempBigPtrEntry : public BigPtrEntry
2525 _TempBigPtrEntry() {}
2529 void SwNodes::RemoveNode( ULONG nDelPos, ULONG nSz, BOOL bDel )
2531 ULONG nEnd = nDelPos + nSz;
2532 SwNode* pNew = (*this)[ nEnd ];
2534 if( pRoot )
2536 SwNodeIndex *p = pRoot;
2537 while( p )
2539 ULONG nIdx = p->GetIndex();
2540 SwNodeIndex* pNext = p->pNext;
2541 if( nDelPos <= nIdx && nIdx < nEnd )
2542 (*p) = *pNew;
2544 p = pNext;
2547 p = pRoot->pPrev;
2548 while( p )
2550 ULONG nIdx = p->GetIndex();
2551 SwNodeIndex* pPrev = p->pPrev;
2552 if( nDelPos <= nIdx && nIdx < nEnd )
2553 (*p) = *pNew;
2555 p = pPrev;
2560 for (ULONG nCnt = 0; nCnt < nSz; nCnt++)
2562 SwTxtNode * pTxtNd = ((*this)[ nDelPos + nCnt ])->GetTxtNode();
2564 if (pTxtNd)
2566 // --> OD 2008-03-13 #refactorlists#
2567 // pTxtNd->UnregisterNumber();
2568 pTxtNd->RemoveFromList();
2569 // <--
2574 if( bDel )
2576 ULONG nCnt = nSz;
2577 SwNode *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ];
2579 // temp. Object setzen
2580 //JP 24.08.98: muessten eigentlich einzeln removed werden, weil
2581 // das Remove auch rekursiv gerufen werden kann, z.B. bei
2582 // zeichengebundenen Rahmen. Da aber dabei viel zu viel
2583 // ablaueft, wird hier ein temp. Objekt eingefuegt, das
2584 // dann mit dem Remove wieder entfernt wird.
2585 // siehe Bug 55406
2586 _TempBigPtrEntry aTempEntry;
2587 BigPtrEntry* pTempEntry = &aTempEntry;
2589 while( nCnt-- )
2591 delete pDel;
2592 pDel = pPrev;
2593 ULONG nPrevNdIdx = pPrev->GetIndex();
2594 BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
2595 if( nCnt )
2596 pPrev = (*this)[ nPrevNdIdx - 1 ];
2598 nDelPos = pDel->GetIndex() + 1;
2601 BigPtrArray::Remove( nDelPos, nSz );
2604 void SwNodes::RegisterIndex( SwNodeIndex& rIdx )
2606 if( !pRoot ) // noch keine Root gesetzt?
2608 pRoot = &rIdx;
2609 pRoot->pPrev = 0;
2610 pRoot->pNext = 0;
2612 else
2614 // immer hinter die Root haengen
2615 rIdx.pNext = pRoot->pNext;
2616 pRoot->pNext = &rIdx;
2617 rIdx.pPrev = pRoot;
2618 if( rIdx.pNext )
2619 rIdx.pNext->pPrev = &rIdx;
2623 void SwNodes::DeRegisterIndex( SwNodeIndex& rIdx )
2625 SwNodeIndex* pN = rIdx.pNext;
2626 SwNodeIndex* pP = rIdx.pPrev;
2628 if( pRoot == &rIdx )
2629 pRoot = pP ? pP : pN;
2631 if( pP )
2632 pP->pNext = pN;
2633 if( pN )
2634 pN->pPrev = pP;
2636 rIdx.pNext = 0;
2637 rIdx.pPrev = 0;
2640 void SwNodes::InsertNode( const SwNodePtr pNode,
2641 const SwNodeIndex& rPos )
2643 const ElementPtr pIns = pNode;
2644 BigPtrArray::Insert( pIns, rPos.GetIndex() );
2647 void SwNodes::InsertNode( const SwNodePtr pNode,
2648 ULONG nPos )
2650 const ElementPtr pIns = pNode;
2651 BigPtrArray::Insert( pIns, nPos );
2654 // ->#112139#
2655 SwNode * SwNodes::DocumentSectionStartNode(SwNode * pNode) const
2657 if (NULL != pNode)
2659 SwNodeIndex aIdx(*pNode);
2661 if (aIdx <= (*this)[0]->EndOfSectionIndex())
2662 pNode = (*this)[0];
2663 else
2665 while ((*this)[0] != pNode->StartOfSectionNode())
2666 pNode = pNode->StartOfSectionNode();
2670 return pNode;
2673 SwNode * SwNodes::DocumentSectionEndNode(SwNode * pNode) const
2675 return DocumentSectionStartNode(pNode)->EndOfSectionNode();
2678 //SwNode * SwNodes::operator[](int n) const
2680 // return operator[]((ULONG) n);
2682 // <-#112139#
2684 sal_Bool SwNodes::IsDocNodes() const
2686 return this == &pMyDoc->GetNodes();