update dev300-m58
[ooovba.git] / sw / source / core / docnode / nodes.cxx
blob4cefc2dd5a82740f8dea59cce017b2a57714ee40
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>
51 #include <docsh.hxx>
52 #include <svtools/smplhint.hxx>
54 extern BOOL CheckNodesRange( const SwNodeIndex& rStt,
55 const SwNodeIndex& rEnd, BOOL bChkSection );
57 SV_DECL_PTRARR(SwSttNdPtrs,SwStartNode*,2,2)
60 //#define JP_DEBUG
61 #ifdef JP_DEBUG
62 #include "shellio.hxx"
63 #endif
66 // Funktion zum bestimmen des hoechsten Levels innerhalb des Bereiches
68 USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange );
70 //-----------------------------------------------------------------------
72 /*******************************************************************
73 |* SwNodes::SwNodes
75 |* Beschreibung
76 |* Konstruktor; legt die vier Grundsektions (PostIts,
77 |* Inserts, Icons, Inhalt) an
78 *******************************************************************/
79 SwNodes::SwNodes( SwDoc* pDocument )
80 : pRoot( 0 ), pMyDoc( pDocument )
82 bInNodesDel = bInDelUpdOutl = bInDelUpdNum = FALSE;
84 ASSERT( pMyDoc, "in welchem Doc stehe ich denn?" );
86 ULONG nPos = 0;
87 SwStartNode* pSttNd = new SwStartNode( *this, nPos++ );
88 pEndOfPostIts = new SwEndNode( *this, nPos++, *pSttNd );
90 SwStartNode* pTmp = new SwStartNode( *this, nPos++ );
91 pEndOfInserts = new SwEndNode( *this, nPos++, *pTmp );
93 pTmp = new SwStartNode( *this, nPos++ );
94 pTmp->pStartOfSection = pSttNd;
95 pEndOfAutotext = new SwEndNode( *this, nPos++, *pTmp );
97 pTmp = new SwStartNode( *this, nPos++ );
98 pTmp->pStartOfSection = pSttNd;
99 pEndOfRedlines = new SwEndNode( *this, nPos++, *pTmp );
101 pTmp = new SwStartNode( *this, nPos++ );
102 pTmp->pStartOfSection = pSttNd;
103 pEndOfContent = new SwEndNode( *this, nPos++, *pTmp );
105 pOutlineNds = new SwOutlineNodes;
108 /*******************************************************************
110 |* SwNodes::~SwNodes
112 |* Beschreibung
113 |* dtor, loescht alle Nodes, deren Pointer in diesem dynamischen
114 |* Array sind. Ist kein Problem, da Nodes ausserhalb dieses
115 |* Arrays nicht erzeugt werden koennen und somit auch nicht
116 |* in mehreren drin sein koennen
118 |* Ersterstellung
119 |* VER0100 vb 901214
121 |* Stand
122 |* VER0100 vb 901214
124 *******************************************************************/
126 SwNodes::~SwNodes()
128 delete pOutlineNds;
131 SwNode *pNode;
132 SwNodeIndex aNdIdx( *this );
133 while( TRUE )
135 pNode = &aNdIdx.GetNode();
136 if( pNode == pEndOfContent )
137 break;
139 aNdIdx++;
140 delete pNode;
144 // jetzt muessen alle SwNodeIndizies abgemeldet sein!!!
145 delete pEndOfContent;
148 void SwNodes::ChgNode( SwNodeIndex& rDelPos, ULONG nSz,
149 SwNodeIndex& rInsPos, BOOL bNewFrms )
151 // im UndoBereich brauchen wir keine Frames
152 SwNodes& rNds = rInsPos.GetNodes();
153 const SwNode* pPrevInsNd = rNds[ rInsPos.GetIndex() -1 ];
155 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
156 // Idle-Handler des Docs
157 if( GetDoc()->SetFieldsDirty( TRUE, &rDelPos.GetNode(), nSz ) &&
158 rNds.GetDoc() != GetDoc() )
159 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
161 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
162 ULONG nNd = rInsPos.GetIndex();
163 BOOL bInsOutlineIdx = !(
164 rNds.GetEndOfRedlines().StartOfSectionNode()->GetIndex() < nNd &&
165 nNd < rNds.GetEndOfRedlines().GetIndex() );
167 if( &rNds == this ) // im gleichen Nodes-Array -> moven !!
169 // wird von vorne nach hinten gemovt, so wird nach vorne immer
170 // nachgeschoben, d.H. die Loeschposition ist immer gleich
171 USHORT nDiff = rDelPos.GetIndex() < rInsPos.GetIndex() ? 0 : 1;
173 for( ULONG n = rDelPos.GetIndex(); nSz; n += nDiff, --nSz )
175 SwNodeIndex aDelIdx( *this, n );
176 SwNode& rNd = aDelIdx.GetNode();
178 // --> OD 2005-11-16 #i57920#
179 // correction of refactoring done by cws swnumtree:
180 // - <SwTxtNode::SetLevel( NO_NUMBERING ) is deprecated and
181 // set <IsCounted> state of the text node to <false>, which
182 // isn't correct here.
183 if ( rNd.IsTxtNode() )
185 SwTxtNode* pTxtNode = rNd.GetTxtNode();
186 // --> OD 2008-03-13 #refactorlists#
187 // pTxtNode->UnregisterNumber();
188 pTxtNode->RemoveFromList();
189 // <--
191 //if ( pTxtNode->GetTxtColl()->GetOutlineLevel() != NO_NUMBERING )//#outline level,zhaojianwei
192 if ( pTxtNode->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
194 const SwNodePtr pSrch = (SwNodePtr)&rNd;
195 pOutlineNds->Remove( pSrch );
198 // <--
200 BigPtrArray::Move( aDelIdx.GetIndex(), rInsPos.GetIndex() );
202 if( rNd.IsTxtNode() )
204 SwTxtNode& rTxtNd = (SwTxtNode&)rNd;
205 // --> OD 2008-03-13 #refactorlists#
206 // rTxtNd.SyncNumberAndNumRule();
207 rTxtNd.AddToList();
208 // <--
210 if( bInsOutlineIdx &&
211 //NO_NUMBERING != rTxtNd.GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
212 0 != rTxtNd.GetAttrOutlineLevel() )//<-end,zhaojianwei
214 const SwNodePtr pSrch = (SwNodePtr)&rNd;
215 pOutlineNds->Insert( pSrch );
217 rTxtNd.InvalidateNumRule();
219 //FEATURE::CONDCOLL
220 if( RES_CONDTXTFMTCOLL == rTxtNd.GetTxtColl()->Which() )
221 rTxtNd.ChkCondColl();
222 //FEATURE::CONDCOLL
224 else if( rNd.IsCntntNode() )
225 ((SwCntntNode&)rNd).InvalidateNumRule();
228 else
230 int bSavePersData = GetDoc()->GetUndoNds() == &rNds;
231 int bRestPersData = GetDoc()->GetUndoNds() == this;
232 SwDoc* pDestDoc = rNds.GetDoc() != GetDoc() ? rNds.GetDoc() : 0;
233 if( !bRestPersData && !bSavePersData && pDestDoc )
234 bSavePersData = bRestPersData = TRUE;
236 String sNumRule;
237 SwNodeIndex aInsPos( rInsPos );
238 for( ULONG n = 0; n < nSz; n++ )
240 SwNode* pNd = &rDelPos.GetNode();
242 // NoTextNode muessen ihre Persitenten Daten mitnehmen
243 if( pNd->IsNoTxtNode() )
245 if( bSavePersData )
246 ((SwNoTxtNode*)pNd)->SavePersistentData();
248 else if( pNd->IsTxtNode() )
250 SwTxtNode* pTxtNd = (SwTxtNode*)pNd;
252 // loesche die Gliederungs-Indizies aus dem alten Nodes-Array
253 //if( NO_NUMBERING != pTxtNd->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
254 if( 0 != pTxtNd->GetAttrOutlineLevel() )//<-end,zhaojianwei
255 pOutlineNds->Remove( pNd );
257 // muss die Rule kopiere werden?
258 if( pDestDoc )
260 const SwNumRule* pNumRule = pTxtNd->GetNumRule();
261 if( pNumRule && sNumRule != pNumRule->GetName() )
263 sNumRule = pNumRule->GetName();
264 SwNumRule* pDestRule = pDestDoc->FindNumRulePtr( sNumRule );
265 if( pDestRule )
266 pDestRule->SetInvalidRule( TRUE );
267 else
268 pDestDoc->MakeNumRule( sNumRule, pNumRule );
271 else
272 // wenns ins UndoNodes-Array gemoved wird, sollten die
273 // Numerierungen auch aktualisiert werden.
274 pTxtNd->InvalidateNumRule();
276 // --> OD 2008-03-13 #refactorlists#
277 // pTxtNd->UnregisterNumber();
278 pTxtNd->RemoveFromList();
279 // <--
282 RemoveNode( rDelPos.GetIndex(), 1, FALSE ); // Indizies verschieben !!
283 SwCntntNode * pCNd = pNd->GetCntntNode();
284 rNds.InsertNode( pNd, aInsPos );
286 if( pCNd )
288 SwTxtNode* pTxtNd = pCNd->GetTxtNode();
289 if( pTxtNd )
291 const SwpHints* pHts = pTxtNd->GetpSwpHints();
292 // setze die OultineNodes im neuen Nodes-Array
293 //if( bInsOutlineIdx && NO_NUMBERING != //#outline level,removed by zhaojianwei
294 // pTxtNd->GetTxtColl()->GetOutlineLevel() )
295 if( bInsOutlineIdx &&
296 0 != pTxtNd->GetAttrOutlineLevel() ) //#outline level,added by zhaojianwei
298 rNds.pOutlineNds->Insert( pTxtNd );
301 // --> OD 2008-03-13 #refactorlists#
302 // pTxtNd->SyncNumberAndNumRule();
303 pTxtNd->AddToList();
304 // <--
306 // Sonderbehandlung fuer die Felder!
307 if( pHts && pHts->Count() )
309 const SwTxtAttr* pAttr;
310 int bToUndo = &pDestDoc->GetNodes() != &rNds;
311 for( USHORT i = pHts->Count(); i; )
313 USHORT nDelMsg = 0;
314 switch( (pAttr = (*pHts)[ --i ])->Which() )
316 case RES_TXTATR_FIELD:
318 SwTxtFld* pTxtFld = (SwTxtFld*)pAttr;
319 rNds.GetDoc()->InsDelFldInFldLst( !bToUndo, *pTxtFld );
321 const SwFieldType* pTyp = pTxtFld->GetFld().GetFld()->GetTyp();
322 if ( RES_POSTITFLD == pTyp->Which() )
324 rNds.GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( &pTxtFld->GetFld(), pTxtFld->GetFld().IsFldInDoc() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
326 else
327 if( RES_DDEFLD == pTyp->Which() )
329 if( bToUndo )
330 ((SwDDEFieldType*)pTyp)->DecRefCnt();
331 else
332 ((SwDDEFieldType*)pTyp)->IncRefCnt();
334 nDelMsg = RES_FIELD_DELETED;
336 break;
337 case RES_TXTATR_FTN:
338 nDelMsg = RES_FOOTNOTE_DELETED;
339 break;
341 case RES_TXTATR_TOXMARK:
342 nDelMsg = RES_TOXMARK_DELETED;
343 break;
345 case RES_TXTATR_REFMARK:
346 nDelMsg = RES_REFMARK_DELETED;
347 break;
349 if( nDelMsg && bToUndo )
351 SwPtrMsgPoolItem aMsgHint( nDelMsg,
352 (void*)&pAttr->GetAttr() );
353 rNds.GetDoc()->GetUnoCallBack()->
354 Modify( &aMsgHint, &aMsgHint );
358 //FEATURE::CONDCOLL
359 if( RES_CONDTXTFMTCOLL == pTxtNd->GetTxtColl()->Which() )
360 pTxtNd->ChkCondColl();
361 //FEATURE::CONDCOLL
363 else
365 // in unterschiedliche Docs gemoved ?
366 // dann die Daten wieder persistent machen
367 if( pCNd->IsNoTxtNode() && bRestPersData )
368 ((SwNoTxtNode*)pCNd)->RestorePersistentData();
374 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
375 // Idle-Handler des Docs
376 GetDoc()->SetFieldsDirty( true, NULL, 0 );
377 if( rNds.GetDoc() != GetDoc() )
378 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
381 if( bNewFrms )
382 bNewFrms = &GetDoc()->GetNodes() == (const SwNodes*)&rNds &&
383 GetDoc()->GetRootFrm();
384 if( bNewFrms )
386 // Frames besorgen:
387 SwNodeIndex aIdx( *pPrevInsNd, 1 );
388 SwNodeIndex aFrmNdIdx( aIdx );
389 SwNode* pFrmNd = rNds.FindPrvNxtFrmNode( aFrmNdIdx,
390 rNds[ rInsPos.GetIndex() - 1 ] );
392 if( !pFrmNd && aFrmNdIdx > rNds.GetEndOfExtras().GetIndex() )
394 ASSERT( !this, "ob das so richtig ist ??" );
395 aFrmNdIdx = rNds.GetEndOfContent();
396 pFrmNd = rNds.GoPrevSection( &aFrmNdIdx, TRUE, FALSE );
397 if( pFrmNd && !((SwCntntNode*)pFrmNd)->GetDepends() )
398 pFrmNd = 0;
400 #ifndef PRODUCT
401 if( !pFrmNd )
402 ASSERT( !this, "ChgNode() - kein FrameNode gefunden" );
403 #endif
405 if( pFrmNd )
406 while( aIdx != rInsPos )
408 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
409 if( pCNd )
411 if( pFrmNd->IsTableNode() )
412 ((SwTableNode*)pFrmNd)->MakeFrms( aIdx );
413 else if( pFrmNd->IsSectionNode() )
414 ((SwSectionNode*)pFrmNd)->MakeFrms( aIdx );
415 else
416 ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd );
417 pFrmNd = pCNd;
419 aIdx++;
425 /***********************************************************************
427 |* SwNodes::Move
429 |* Beschreibung
430 |* Move loescht die Node-Pointer ab und einschliesslich der Startposition
431 |* bis zu und ausschliesslich der Endposition und fuegt sie an
432 |* der vor der Zielposition ein.
433 |* Wenn das Ziel vor dem ersten oder dem letzten zu bewegenden Element oder
434 |* dazwischen liegt, geschieht nichts.
435 |* Wenn der zu bewegende Bereich leer ist oder das Ende vor
436 |* dem Anfang liegt, geschieht nichts.
438 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
439 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
443 ***********************************************************************/
445 BOOL SwNodes::_MoveNodes( const SwNodeRange& aRange, SwNodes & rNodes,
446 const SwNodeIndex& aIndex, BOOL bNewFrms )
448 SwNode * pAktNode;
449 if( aIndex == 0 ||
450 ( (pAktNode = &aIndex.GetNode())->GetStartNode() &&
451 !pAktNode->StartOfSectionIndex() ))
452 return FALSE;
454 SwNodeRange aRg( aRange );
456 // "einfache" StartNodes oder EndNodes ueberspringen
457 while( ND_STARTNODE == (pAktNode = &aRg.aStart.GetNode())->GetNodeType()
458 || ( pAktNode->IsEndNode() &&
459 !pAktNode->pStartOfSection->IsSectionNode() ) )
460 aRg.aStart++;
461 aRg.aStart--;
463 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
464 aRg.aEnd--;
465 while( ( (( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
466 !pAktNode->IsSectionNode() ) ||
467 ( pAktNode->IsEndNode() &&
468 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) ) &&
469 aRg.aEnd > aRg.aStart )
470 aRg.aEnd--;
473 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
474 if( aRg.aStart >= aRg.aEnd )
475 return FALSE;
477 if( this == &rNodes )
479 if( ( aIndex.GetIndex()-1 >= aRg.aStart.GetIndex() &&
480 aIndex.GetIndex()-1 < aRg.aEnd.GetIndex()) ||
481 ( aIndex.GetIndex()-1 == aRg.aEnd.GetIndex() ) )
482 return FALSE;
485 USHORT nLevel = 0; // Level-Counter
486 ULONG nInsPos = 0; // Cnt fuer das TmpArray
488 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
489 SwSttNdPtrs aSttNdStack( 1, 5 );
491 // setze den Start-Index
492 SwNodeIndex aIdx( aIndex );
494 --- JP 17.11.94: sollte ueberholt sein, wird im ChgNode schon erledigt!
495 BOOL bCorrNum = pSect && pSect->aStart.GetIndex() == aIdx.GetIndex();
498 SwStartNode* pStartNode = aIdx.GetNode().pStartOfSection;
499 aSttNdStack.C40_INSERT( SwStartNode, pStartNode, 0 );
500 // aSttNdStack.Insert( rNodes[ aIdx ]->pStartOfSection, 0 );
501 SwNodeRange aOrigInsPos( aIdx, -1, aIdx ); // Originale Insert Pos
503 //JP 16.01.98: SectionNodes: DelFrms/MakeFrms beim obersten SectionNode!
504 USHORT nSectNdCnt = 0;
505 BOOL bSaveNewFrms = bNewFrms;
507 // bis alles verschoben ist
508 while( aRg.aStart < aRg.aEnd )
509 switch( (pAktNode = &aRg.aEnd.GetNode())->GetNodeType() )
511 case ND_ENDNODE:
513 if( nInsPos ) // verschieb schon mal alle bis hier her
515 // loeschen und kopieren. ACHTUNG: die Indizies ab
516 // "aRg.aEnd+1" werden mit verschoben !!
517 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
518 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
519 aIdx -= nInsPos;
520 nInsPos = 0;
523 SwStartNode* pSttNd = pAktNode->pStartOfSection;
524 if( pSttNd->IsTableNode() )
526 SwTableNode* pTblNd = (SwTableNode*)pSttNd;
528 // dann bewege die gesamte Tabelle/den Bereich !!
529 nInsPos = (aRg.aEnd.GetIndex() -
530 pSttNd->GetIndex() )+1;
531 aRg.aEnd -= nInsPos;
533 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
534 ULONG nNd = aIdx.GetIndex();
535 BOOL bInsOutlineIdx = !( rNodes.GetEndOfRedlines().
536 StartOfSectionNode()->GetIndex() < nNd &&
537 nNd < rNodes.GetEndOfRedlines().GetIndex() );
539 if( bNewFrms )
540 // loesche erstmal die Frames
541 pTblNd->DelFrms();
542 if( &rNodes == this ) // in sich selbst moven ??
544 // dann bewege alle Start/End/ContentNodes. Loesche
545 // bei den ContentNodes auch die Frames !!
546 pTblNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
547 for( ULONG n = 0; n < nInsPos; ++n )
549 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
550 SwCntntNode* pCNd = 0;
551 SwNode* pTmpNd = &aMvIdx.GetNode();
552 if( pTmpNd->IsCntntNode() )
554 pCNd = (SwCntntNode*)pTmpNd;
555 if( pTmpNd->IsTxtNode() )
556 ((SwTxtNode*)pTmpNd)->RemoveFromList();
558 // if( bNewFrms )
559 // pCNd->DelFrms();
561 // setze bei Start/EndNodes die richtigen Indizies
562 // loesche die Gliederungs-Indizies aus
563 // dem alten Nodes-Array
564 //if( pCNd->IsTxtNode() && NO_NUMBERING != //#outline level,zhaojianwei
565 // ((SwTxtNode*)pCNd)->GetTxtColl()->GetOutlineLevel() )
566 if( pCNd->IsTxtNode() && 0 !=
567 ((SwTxtNode*)pCNd)->GetAttrOutlineLevel() )//<-end,by zhaojianwei
568 pOutlineNds->Remove( pCNd );
569 else
570 pCNd = 0;
572 // else if( bNewFrms && pTmpNd->IsSectionNode() )
573 // ((SwSectionNode*)pTmpNd)->DelFrms();
574 BigPtrArray::Move( aMvIdx.GetIndex(), aIdx.GetIndex() );
576 if( bInsOutlineIdx && pCNd )
577 pOutlineNds->Insert( pCNd );
578 if( pTmpNd->IsTxtNode() )
579 ((SwTxtNode*)pTmpNd)->AddToList();
582 else
584 // StartNode holen
585 // Even aIdx points to a startnode, we need the startnode
586 // of the environment of aIdx (#i80941)
587 SwStartNode* pSttNode = aIdx.GetNode().pStartOfSection;
589 // Hole alle Boxen mit Inhalt. Deren Indizies auf die
590 // StartNodes muessen umgemeldet werden !!
591 // (Array kopieren und alle gefunden wieder loeschen;
592 // erleichtert das suchen!!)
593 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
594 for( ULONG n = 0; n < nInsPos; ++n )
596 SwNode* pNd = &aMvIdx.GetNode();
597 /* if( bNewFrms )
599 if( pNd->IsCntntNode() )
600 ((SwCntntNode*)pNd)->DelFrms();
601 else if( pNd->IsSectionNode() )
602 ((SwSectionNode*)pNd)->DelFrms();
605 //BOOL bOutlNd = pNd->IsTxtNode() && NO_NUMBERING !=//#outline level,zhaojianwei
606 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel();
607 const bool bOutlNd = pNd->IsTxtNode() &&
608 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel();//<-end,zhaojianwei
609 // loesche die Gliederungs-Indizies aus
610 // dem alten Nodes-Array
611 if( bOutlNd )
612 pOutlineNds->Remove( pNd );
614 RemoveNode( aMvIdx.GetIndex(), 1, FALSE );
615 pNd->pStartOfSection = pSttNode;
616 rNodes.InsertNode( pNd, aIdx );
618 // setze bei Start/EndNodes die richtigen Indizies
619 if( bInsOutlineIdx && bOutlNd )
620 // und setze sie im neuen Nodes-Array
621 rNodes.pOutlineNds->Insert( pNd );
622 else if( pNd->IsStartNode() )
623 pSttNode = (SwStartNode*)pNd;
624 else if( pNd->IsEndNode() )
626 pSttNode->pEndOfSection = (SwEndNode*)pNd;
627 if( pSttNode->IsSectionNode() )
628 ((SwSectionNode*)pSttNode)->NodesArrChgd();
629 pSttNode = pSttNode->pStartOfSection;
633 if( pTblNd->GetTable().IsA( TYPE( SwDDETable ) ))
635 SwDDEFieldType* pTyp = ((SwDDETable&)pTblNd->
636 GetTable()).GetDDEFldType();
637 if( pTyp )
639 if( rNodes.IsDocNodes() )
640 pTyp->IncRefCnt();
641 else
642 pTyp->DecRefCnt();
646 if( GetDoc()->GetUndoNds() == &rNodes )
648 SwFrmFmt* pTblFmt = pTblNd->GetTable().GetFrmFmt();
649 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
650 pTblFmt );
651 pTblFmt->Modify( &aMsgHint, &aMsgHint );
654 if( bNewFrms )
656 SwNodeIndex aTmp( aIdx );
657 pTblNd->MakeFrms( &aTmp );
659 aIdx -= nInsPos;
660 nInsPos = 0;
662 else if( pSttNd->GetIndex() < aRg.aStart.GetIndex() )
664 // SectionNode: es wird nicht die gesamte Section
665 // verschoben, also bewege nur die
666 // ContentNodes
667 // StartNode: erzeuge an der Postion eine neue Section
668 do { // middle check loop
669 if( !pSttNd->IsSectionNode() )
671 // Start und EndNode an der InsertPos erzeugen
672 SwStartNode* pTmp = new SwStartNode( aIdx,
673 ND_STARTNODE,
674 /*?? welcher NodeTyp ??*/
675 SwNormalStartNode );
677 nLevel++; // den Index auf StartNode auf den Stack
678 aSttNdStack.C40_INSERT( SwStartNode, pTmp, nLevel );
680 // noch den EndNode erzeugen
681 new SwEndNode( aIdx, *pTmp );
683 else if( (const SwNodes*)&rNodes ==
684 GetDoc()->GetUndoNds() )
686 // im UndoNodes-Array spendieren wir einen
687 // Platzhalter
688 new SwNode( aIdx, ND_SECTIONDUMMY );
690 else
692 // JP 18.5.2001: neue Section anlegen?? Bug 70454
693 aRg.aEnd--;
694 break;
698 aRg.aEnd--;
699 aIdx--;
700 } while( FALSE );
702 else
704 // Start und EndNode komplett verschieben
705 // s. u. SwIndex aOldStt( pSttNd->theIndex );
706 //JP 21.05.97: sollte der Start genau der Start des Bereiches sein, so muss
707 // der Node auf jedenfall noch besucht werden!
708 if( &aRg.aStart.GetNode() == pSttNd )
709 --aRg.aStart;
711 SwSectionNode* pSctNd = pSttNd->GetSectionNode();
712 if( bNewFrms && pSctNd )
713 pSctNd->DelFrms();
715 RemoveNode( aRg.aEnd.GetIndex(), 1, FALSE ); // EndNode loeschen
716 ULONG nSttPos = pSttNd->GetIndex();
718 // dieser StartNode wird spaeter wieder entfernt!
719 SwStartNode* pTmpSttNd = new SwStartNode( *this, nSttPos+1 );
720 pTmpSttNd->pStartOfSection = pSttNd->pStartOfSection;
722 RemoveNode( nSttPos, 1, FALSE ); // SttNode loeschen
724 pSttNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
725 rNodes.InsertNode( pSttNd, aIdx );
726 rNodes.InsertNode( pAktNode, aIdx );
727 aIdx--;
728 pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
730 aRg.aEnd--;
732 nLevel++; // den Index auf StartNode auf den Stack
733 aSttNdStack.C40_INSERT( SwStartNode, pSttNd, nLevel );
735 // SectionNode muss noch ein paar Indizies ummelden
736 if( pSctNd )
738 pSctNd->NodesArrChgd();
739 ++nSectNdCnt;
740 bNewFrms = FALSE;
744 break;
748 case ND_SECTIONNODE:
749 if( !nLevel &&
750 ( (const SwNodes*)&rNodes == GetDoc()->GetUndoNds() ) )
752 // dann muss an der akt. InsPos ein SectionDummyNode
753 // eingefuegt werden
754 if( nInsPos ) // verschieb schon mal alle bis hier her
756 // loeschen und kopieren. ACHTUNG: die Indizies ab
757 // "aRg.aEnd+1" werden mit verschoben !!
758 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
759 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
760 aIdx -= nInsPos;
761 nInsPos = 0;
763 new SwNode( aIdx, ND_SECTIONDUMMY );
764 aRg.aEnd--;
765 aIdx--;
766 break;
768 // kein break !!
769 case ND_TABLENODE:
770 case ND_STARTNODE:
772 // Bug #78589# - empty section -> nothing to do
773 // and only if it's a top level section
774 if( !nInsPos && !nLevel )
776 aRg.aEnd--;
777 break;
780 if( !nLevel ) // es wird eine Stufe runter gestuft
782 // erzeuge die Runterstufung
783 SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 );
784 SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx,
785 ND_STARTNODE,
786 ((SwStartNode*)pAktNode)->GetStartNodeType() );
788 aTmpSIdx--;
790 SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd );
791 new SwEndNode( aTmpEIdx, *pTmpStt );
792 aTmpEIdx--;
793 aTmpSIdx++;
795 // setze die StartOfSection richtig
796 aRg.aEnd++;
798 SwNodeIndex aCntIdx( aRg.aEnd );
799 for( ULONG n = 0; n < nInsPos; n++, aCntIdx++)
800 aCntIdx.GetNode().pStartOfSection = pTmpStt;
803 // Setze auch bei allen runtergestuften den richtigen StartNode
804 while( aTmpSIdx < aTmpEIdx )
805 if( 0 != (( pAktNode = &aTmpEIdx.GetNode())->GetEndNode()) )
806 aTmpEIdx = pAktNode->StartOfSectionIndex();
807 else
809 pAktNode->pStartOfSection = pTmpStt;
810 aTmpEIdx--;
813 aIdx--; // hinter den eingefuegten StartNode
814 aRg.aEnd--; // vor den StartNode
815 // kopiere jetzt das Array. ACHTUNG: die Indizies ab
816 // "aRg.aEnd+1" werden mit verschoben !!
817 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
818 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
819 aIdx -= nInsPos+1;
820 nInsPos = 0;
822 else // es wurden alle Nodes innerhalb eines
823 { // Start- und End-Nodes verschoben
824 ASSERT( pAktNode == aSttNdStack[nLevel] ||
825 ( pAktNode->IsStartNode() &&
826 aSttNdStack[nLevel]->IsSectionNode()),
827 "falscher StartNode" );
829 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
830 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
831 aIdx -= nInsPos+1; // vor den eingefuegten StartNode
832 nInsPos = 0;
834 // loesche nur noch den Pointer aus dem Nodes-Array.
835 // RemoveNode( aRg.aEnd.GetIndex(), 1, FALSE );
836 RemoveNode( aRg.aEnd.GetIndex(), 1, TRUE );
837 aRg.aEnd--;
839 SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode();
840 if( pSectNd && !--nSectNdCnt )
842 SwNodeIndex aTmp( *pSectNd );
843 pSectNd->MakeFrms( &aTmp );
844 bNewFrms = bSaveNewFrms;
846 aSttNdStack.Remove( nLevel ); // vom Stack loeschen
847 nLevel--;
850 // loesche alle entstehenden leeren Start-/End-Node-Paare
851 SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode();
852 if( pTmpNode && ND_STARTNODE == (pAktNode = &aRg.aEnd.GetNode())
853 ->GetNodeType() && pAktNode->StartOfSectionIndex() &&
854 pTmpNode->StartOfSectionNode() == pAktNode )
856 DelNodes( aRg.aEnd, 2 );
857 aRg.aEnd--;
859 // aRg.aEnd--;
861 break;
863 case ND_TEXTNODE:
864 case ND_GRFNODE:
865 case ND_OLENODE:
867 if( bNewFrms && pAktNode->GetCntntNode() )
868 ((SwCntntNode*)pAktNode)->DelFrms();
870 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
871 nInsPos++;
872 aRg.aEnd--;
874 break;
876 case ND_SECTIONDUMMY:
877 if( (const SwNodes*)this == GetDoc()->GetUndoNds() )
879 if( &rNodes == this ) // innerhalb vom UndoNodesArray
881 // mit verschieben
882 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
883 nInsPos++;
885 else // in ein "normales" Nodes-Array verschieben
887 // dann muss an der akt. InsPos auch ein SectionNode
888 // (Start/Ende) stehen; dann diesen ueberspringen.
889 // Andernfalls nicht weiter beachten.
890 if( nInsPos ) // verschieb schon mal alle bis hier her
892 // loeschen und kopieren. ACHTUNG: die Indizies ab
893 // "aRg.aEnd+1" werden mit verschoben !!
894 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
895 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
896 aIdx -= nInsPos;
897 nInsPos = 0;
899 SwNode* pTmpNd = &aIdx.GetNode();
900 if( pTmpNd->IsSectionNode() ||
901 pTmpNd->StartOfSectionNode()->IsSectionNode() )
902 aIdx--; // ueberspringen
905 else {
906 ASSERT( FALSE, "wie kommt diser Node ins Nodes-Array??" );
908 aRg.aEnd--;
909 break;
911 default:
912 ASSERT( FALSE, "was ist das fuer ein Node??" );
913 break;
916 if( nInsPos ) // kopiere den Rest
918 // der Rest muesste so stimmen
919 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
920 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
922 aRg.aEnd++; // wieder exklusive Ende
924 // loesche alle leeren Start-/End-Node-Paare
925 if( ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
926 pAktNode->StartOfSectionIndex() &&
927 aRg.aEnd.GetNode().GetEndNode() )
928 DelNodes( aRg.aStart, 2 );
930 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
931 aOrigInsPos.aStart++;
932 // im gleichen Nodes-Array verschoben ??,
933 // dann von oben nach unten das Update aufrufen !!
934 if( this == &rNodes &&
935 aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() )
937 UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
938 UpdtOutlineIdx( aRg.aEnd.GetNode() );
940 else
942 UpdtOutlineIdx( aRg.aEnd.GetNode() );
943 rNodes.UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
946 #ifdef JP_DEBUG
948 extern Writer* GetDebugWriter(const String&);
950 Writer* pWriter = GetDebugWriter(aEmptyStr);
951 if( pWriter )
953 int nError;
954 SvFileStream aStrm( "c:\\$$move.db", STREAM_WRITE );
955 SwWriter aWriter( aStrm, *pMyDoc );
956 aWriter.Write( &nError, pWriter );
959 #endif
961 return TRUE;
965 /*******************************************************************
967 |* SwNodes::SectionDown
969 |* Beschreibung
970 |* SectionDown() legt ein Paar von Start- und EndSection-Node
971 |* (andere Nodes koennen dazwischen liegen) an.
973 |* Zustand des SRange beim Verlassen der Funktion: nStart ist der
974 |* Index des ersten Node hinter dem Start Section Node, nEnd ist
975 |* der Index des End Section Nodes. Beispiel: Wird Insert Section
976 |* mehrmals hintereinander aufgerufen, so werden mehrere
977 |* unmittelbar geschachtelte Sections (keine Content Nodes
978 |* zwischen Start- bzw. End Nodes) angelegt.
980 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
981 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
983 |* Parameter
984 |* SwRange &rRange
985 |* IO:
986 |* IN
987 |* rRange.aStart: Einfuegeposition des StartNodes
988 |* rRange.aEnd: Einfuegeposition des EndNodes
989 |* OUT
990 |* rRange.aStart: steht hinter dem eingefuegten Startnode
991 |* rRange.aEnd: steht auf dem eingefuegen Endnode
993 |* Ausnahmen
994 |* 1. SRange-Anfang und SRange-Ende muessen auf dem gleichen Level sein
995 |* 2. duerfen nicht auf dem obersten Level sein
996 |* Ist dies nicht der Fall, wird die
997 |* Funktion durch Aufruf von ERR_RAISE verlassen.
999 |* Debug-Funktionen
1000 |* die Debugging Tools geben rRange beim Eintritt und beim
1001 |* Verlassen der Funktion aus
1003 |* Ersterstellung
1004 |* VER0100 vb 901214
1006 |* Stand
1007 |* VER0100 vb 901214
1009 *******************************************************************/
1010 void SwNodes::SectionDown(SwNodeRange *pRange, SwStartNodeType eSttNdTyp )
1012 if( pRange->aStart >= pRange->aEnd ||
1013 pRange->aEnd >= Count() ||
1014 !CheckNodesRange( pRange->aStart, pRange->aEnd ))
1015 return;
1017 // Ist der Anfang vom Bereich vor oder auf einem EndNode, so loesche
1018 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
1019 // Bei anderen Nodes wird eine neuer StartNode eingefuegt
1020 SwNode * pAktNode = &pRange->aStart.GetNode();
1021 SwNodeIndex aTmpIdx( *pAktNode->StartOfSectionNode() );
1023 if( pAktNode->GetEndNode() )
1024 DelNodes( pRange->aStart, 1 ); // verhinder leere Section
1025 else
1027 // fuege einen neuen StartNode ein
1028 SwNode* pSttNd = new SwStartNode( pRange->aStart, ND_STARTNODE, eSttNdTyp );
1029 pRange->aStart = *pSttNd;
1030 aTmpIdx = pRange->aStart;
1033 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
1034 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen
1035 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1036 pRange->aEnd--;
1037 if( pRange->aEnd.GetNode().GetStartNode() )
1038 DelNodes( pRange->aEnd, 1 );
1039 else
1041 pRange->aEnd++;
1042 // fuege einen neuen EndNode ein
1043 new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() );
1045 pRange->aEnd--;
1047 SectionUpDown( aTmpIdx, pRange->aEnd );
1050 /*******************************************************************
1052 |* SwNodes::SectionUp
1054 |* Beschreibung
1055 |* Der von rRange umspannte Bereich wird auf die naechst hoehere
1056 |* Ebene gehoben. Das geschieht dadurch, dass bei
1057 |* rRange.aStart ein Endnode und bei rRange.aEnd ein
1058 |* Startnode eingefuegt wird. Die Indices fuer den Bereich
1059 |* innerhalb von rRange werden geupdated.
1061 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
1062 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
1064 |* Parameter
1065 |* SwRange &rRange
1066 |* IO:
1067 |* IN
1068 |* rRange.aStart: Anfang des hoeher zubewegenden Bereiches
1069 |* rRange.aEnd: der 1.Node hinter dem Bereich
1070 |* OUT
1071 |* rRange.aStart: an der ersten Position innerhalb des
1072 |* hochbewegten Bereiches
1073 |* rRange.aEnd: an der letzten Position innerhalb des
1074 |* hochbewegten Bereiches
1076 |* Debug-Funktionen
1077 |* die Debugging Tools geben rRange beim Eintritt und beim
1078 |* Verlassen der Funktion aus
1080 |* Ersterstellung
1081 |* VER0100 vb 901214
1083 |* Stand
1084 |* VER0100 vb 901214
1086 *******************************************************************/
1087 void SwNodes::SectionUp(SwNodeRange *pRange)
1089 if( pRange->aStart >= pRange->aEnd ||
1090 pRange->aEnd >= Count() ||
1091 !CheckNodesRange( pRange->aStart, pRange->aEnd ) ||
1092 !( HighestLevel( *this, *pRange ) > 1 ))
1093 return;
1095 // Ist der Anfang vom Bereich vor oder auf einem StartNode, so loesche
1096 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
1097 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1098 SwNode * pAktNode = &pRange->aStart.GetNode();
1099 SwNodeIndex aIdx( *pAktNode->StartOfSectionNode() );
1100 if( pAktNode->IsStartNode() ) // selbst StartNode
1102 SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode();
1103 if( pAktNode == pEndNd->pStartOfSection )
1105 // dann wurde paarig aufgehoben, also nur die im Berich neu anpassen
1106 SwStartNode* pTmpSttNd = pAktNode->pStartOfSection;
1107 RemoveNode( pRange->aStart.GetIndex(), 1, TRUE );
1108 RemoveNode( pRange->aEnd.GetIndex(), 1, TRUE );
1110 SwNodeIndex aTmpIdx( pRange->aStart );
1111 while( aTmpIdx < pRange->aEnd )
1113 pAktNode = &aTmpIdx.GetNode();
1114 pAktNode->pStartOfSection = pTmpSttNd;
1115 if( pAktNode->IsStartNode() )
1116 aTmpIdx = pAktNode->EndOfSectionIndex() + 1;
1117 else
1118 aTmpIdx++;
1120 return ;
1122 DelNodes( pRange->aStart, 1 );
1124 else if( aIdx == pRange->aStart.GetIndex()-1 ) // vor StartNode
1125 DelNodes( aIdx, 1 );
1126 else
1127 new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() );
1129 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
1130 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes entstehen
1131 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1132 SwNodeIndex aTmpIdx( pRange->aEnd );
1133 if( pRange->aEnd.GetNode().IsEndNode() )
1134 DelNodes( pRange->aEnd, 1 );
1135 else
1137 pAktNode = new SwStartNode( pRange->aEnd );
1138 /*?? welcher NodeTyp ??*/
1139 aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode();
1140 pRange->aEnd--;
1143 SectionUpDown( aIdx, aTmpIdx );
1147 /*************************************************************************
1149 |* SwNodes::SectionUpDown()
1151 |* Beschreibung
1152 |* Methode setzt die Indizies die bei SectionUp oder SectionDwon
1153 |* veraendert wurden wieder richtig, sodass die Ebenen wieder
1154 |* Konsistent sind.
1156 |* Parameter
1157 |* SwIndex & aStart StartNode !!!
1158 |* SwIndex & aEnd EndPunkt
1160 |* Ersterstellung JP 23.04.91
1161 |* Letzte Aenderung JP 23.04.91
1163 *************************************************************************/
1164 void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd )
1166 SwNode * pAktNode;
1167 SwNodeIndex aTmpIdx( aStart, +1 );
1168 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
1169 SwSttNdPtrs aSttNdStack( 1, 5 );
1170 SwStartNode* pTmp = aStart.GetNode().GetStartNode();
1171 aSttNdStack.C40_INSERT( SwStartNode, pTmp, 0 );
1173 // durchlaufe bis der erste zu aendernde Start-Node gefunden wurde
1174 // ( Es wird vom eingefuegten EndNode bis nach vorne die Indexe gesetzt )
1175 for( ;; aTmpIdx++ )
1177 pAktNode = &aTmpIdx.GetNode();
1178 pAktNode->pStartOfSection = aSttNdStack[ aSttNdStack.Count()-1 ];
1180 if( pAktNode->GetStartNode() )
1182 pTmp = (SwStartNode*)pAktNode;
1183 aSttNdStack.C40_INSERT( SwStartNode, pTmp, aSttNdStack.Count() );
1185 else if( pAktNode->GetEndNode() )
1187 SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.Count() - 1 ];
1188 pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
1189 aSttNdStack.Remove( aSttNdStack.Count() - 1 );
1190 if( aSttNdStack.Count() )
1191 continue; // noch genuegend EndNodes auf dem Stack
1193 else if( aTmpIdx < aEnd ) // Uebergewicht an StartNodes
1194 // ist das Ende noch nicht erreicht, so hole den Start von
1195 // der uebergeordneten Section
1197 aSttNdStack.C40_INSERT( SwStartNode, pSttNd->pStartOfSection, 0 );
1199 else // wenn ueber den Bereich hinaus, dann Ende
1200 break;
1208 /*******************************************************************
1210 |* SwNodes::Delete
1212 |* Beschreibung
1213 |* Spezielle Implementierung der Delete-Funktion des
1214 |* variablen Array. Diese spezielle Implementierung ist
1215 |* notwendig, da durch das Loeschen von Start- bzw.
1216 |* Endnodes Inkonsistenzen entstehen koennen. Diese werden
1217 |* durch diese Funktion beseitigt.
1219 |* Parameter
1220 |* IN
1221 |* SwIndex &rIndex bezeichnet die Position, an der
1222 |* geloescht wird
1223 |* rIndex ist nach Aufruf der Funktion unveraendert (Kopie?!)
1224 |* USHORT nNodes bezeichnet die Anzahl der zu loeschenden
1225 |* Nodes; ist auf 1 defaulted
1227 |* Debug-Funktionen
1228 |* geben beim Eintritt in die Funktion Position und Anzahl
1229 |* der zu loeschenden Nodes aus.
1231 |* Ersterstellung
1232 |* VER0100 vb 901214
1234 |* Stand
1235 |* VER0100 vb 901214
1237 *******************************************************************/
1238 void SwNodes::Delete(const SwNodeIndex &rIndex, ULONG nNodes)
1240 USHORT nLevel = 0; // Level-Counter
1241 SwNode * pAktNode;
1243 ULONG nCnt = Count() - rIndex.GetIndex() - 1;
1244 if( nCnt > nNodes ) nCnt = nNodes;
1246 if( nCnt == 0 ) // keine Anzahl -> return
1247 return;
1249 SwNodeRange aRg( rIndex, 0, rIndex, nCnt-1 );
1250 // ueberprufe ob rIndex..rIndex + nCnt ueber einen Bereich hinausragt !!
1251 if( ( !aRg.aStart.GetNode().StartOfSectionIndex() &&
1252 !aRg.aStart.GetIndex() ) ||
1253 ! CheckNodesRange( aRg.aStart, aRg.aEnd ) )
1254 return;
1257 // falls aEnd auf keinem ContentNode steht, dann suche den vorherigen
1258 while( ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() ||
1259 ( pAktNode->GetEndNode() &&
1260 !pAktNode->pStartOfSection->IsTableNode() ))
1261 aRg.aEnd--;
1263 nCnt = 0;
1264 // Start erhoehen, damit auf < abgefragt wird. ( bei <= kann es zu
1265 // Problemen fuehren; ist aEnd == aStart und wird aEnd geloscht,
1266 // so ist aEnd <= aStart
1267 aRg.aStart--;
1269 BOOL bSaveInNodesDel = bInNodesDel;
1270 bInNodesDel = TRUE;
1271 BOOL bUpdateOutline = FALSE;
1273 // bis alles geloescht ist
1274 while( aRg.aStart < aRg.aEnd )
1276 pAktNode = &aRg.aEnd.GetNode();
1278 if( pAktNode->GetEndNode() )
1280 // die gesamte Section loeschen ?
1281 if( pAktNode->StartOfSectionIndex() > aRg.aStart.GetIndex() )
1283 SwTableNode* pTblNd = pAktNode->pStartOfSection->GetTableNode();
1284 if( pTblNd )
1285 pTblNd->DelFrms();
1287 SwNode *pNd, *pChkNd = pAktNode->pStartOfSection;
1288 USHORT nIdxPos;
1289 do {
1290 pNd = &aRg.aEnd.GetNode();
1292 if( pNd->IsTxtNode() )
1294 //if( NO_NUMBERING != //#outline level,zhaojianwei
1295 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() &&
1296 if( 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() &&//<-end,zhaojianwei
1297 pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
1299 // loesche die Gliederungs-Indizies.
1300 pOutlineNds->Remove( nIdxPos );
1301 bUpdateOutline = TRUE;
1303 ((SwTxtNode*)pNd)->InvalidateNumRule();
1305 else if( pNd->IsEndNode() &&
1306 pNd->pStartOfSection->IsTableNode() )
1307 ((SwTableNode*)pNd->pStartOfSection)->DelFrms();
1309 aRg.aEnd--;
1310 nCnt++;
1312 } while( pNd != pChkNd );
1314 else
1316 RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, TRUE ); // loesche
1317 nCnt = 0;
1318 aRg.aEnd--; // vor den EndNode
1319 nLevel++;
1322 else if( pAktNode->GetStartNode() ) // StartNode gefunden
1324 if( nLevel == 0 ) // es wird eine Stufe runter gestuft
1326 if( nCnt )
1328 // loesche jetzt das Array
1329 aRg.aEnd++;
1330 RemoveNode( aRg.aEnd.GetIndex(), nCnt, TRUE );
1331 nCnt = 0;
1334 else // es werden alle Nodes Innerhalb eines Start- und
1335 { // End-Nodes geloescht, loesche mit Start/EndNode
1336 RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, TRUE ); // loesche Array
1337 nCnt = 0;
1338 nLevel--;
1341 // nach dem loeschen kann aEnd auf einem EndNode stehen
1342 // loesche alle leeren Start-/End-Node-Paare
1343 SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1344 aRg.aEnd--;
1345 while( pTmpNode &&
1346 ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
1347 pAktNode->StartOfSectionIndex() )
1349 // loesche den EndNode und StartNode
1350 DelNodes( aRg.aEnd, 2 );
1351 pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1352 aRg.aEnd--;
1355 else // normaler Node, also ins TmpArray einfuegen
1357 SwTxtNode* pTxtNd = pAktNode->GetTxtNode();
1358 if( pTxtNd )
1360 if( pTxtNd->IsOutline())
1361 { // loesche die Gliederungs-Indizies.
1362 pOutlineNds->Remove( pTxtNd );
1363 bUpdateOutline = TRUE;
1365 pTxtNd->InvalidateNumRule();
1367 else if( pAktNode->IsCntntNode() )
1368 ((SwCntntNode*)pAktNode)->InvalidateNumRule();
1370 aRg.aEnd--;
1371 nCnt++;
1375 aRg.aEnd++;
1376 if( nCnt != 0 )
1377 RemoveNode( aRg.aEnd.GetIndex(), nCnt, TRUE ); // loesche den Rest
1379 // loesche alle leeren Start-/End-Node-Paare
1380 while( aRg.aEnd.GetNode().GetEndNode() &&
1381 ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
1382 pAktNode->StartOfSectionIndex() )
1383 // aber ja keinen der heiligen 5.
1385 DelNodes( aRg.aStart, 2 ); // loesche den Start- und EndNode
1386 aRg.aStart--;
1389 bInNodesDel = bSaveInNodesDel;
1391 if( !bInNodesDel )
1393 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
1394 if( bUpdateOutline || bInDelUpdOutl )
1396 UpdtOutlineIdx( aRg.aEnd.GetNode() );
1397 bInDelUpdOutl = FALSE;
1401 else
1403 if( bUpdateOutline )
1404 bInDelUpdOutl = TRUE;
1408 /*******************************************************************
1410 |* SwNodes::GetSectionLevel
1412 |* Beschreibung
1413 |* Die Funktion liefert den Sectionlevel an der durch
1414 |* aIndex bezeichneten Position. Die Funktion ruft die
1415 |* GetSectionlevel-Funktion des durch aIndex bezeichneten
1416 |* Nodes. Diese ist eine virtuelle Funktion, die fuer
1417 |* Endnodes speziell implementiert werden musste.
1418 |* Die Sectionlevels werden ermittelt, indem rekursiv durch
1419 |* die Nodesstruktur (jeweils zum naechsten theEndOfSection)
1420 |* gegangen wird, bis die oberste Ebene erreicht ist
1421 |* (theEndOfSection == 0)
1423 |* Parameter
1424 |* aIndex bezeichnet die Position des Nodes, dessen
1425 |* Sectionlevel ermittelt werden soll. Hier wird eine Kopie
1426 |* uebergeben, da eine Veraenderung der Variablen in der
1427 |* rufenden Funktion nicht wuenschenswert ist.
1429 |* Ausnahmen
1430 |* Der erste Node im Array sollte immer ein Startnode sein.
1431 |* Dieser erfaehrt in der Funktion SwNodes::GetSectionLevel()
1432 |* eine Sonderbehandlung; es wird davon ausgegangen, dass der
1433 |* erste Node auch ein Startnode ist.
1435 |* Ersterstellung
1436 |* VER0100 vb 901214
1438 |* Stand
1439 |* VER0100 vb 901214
1441 *******************************************************************/
1442 USHORT SwNodes::GetSectionLevel(const SwNodeIndex &rIdx) const {
1443 // Sonderbehandlung 1. Node
1444 if(rIdx == 0) return 1;
1446 * Keine Rekursion! - hier wird das SwNode::GetSectionLevel
1447 * aufgerufen
1449 return (*this)[rIdx]->GetSectionLevel();
1453 void SwNodes::GoStartOfSection(SwNodeIndex *pIdx) const
1455 // hinter den naechsten Startnode
1456 SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 );
1458 // steht der Index auf keinem ContentNode, dann gehe dahin. Ist aber
1459 // kein weiterer vorhanden, dann lasse den Index an alter Pos stehen !!!
1460 while( !aTmp.GetNode().IsCntntNode() )
1461 { // gehe vom StartNode ( es kann nur ein StartNode sein ! ) an sein
1462 // Ende
1463 if( *pIdx <= aTmp )
1464 return; // FEHLER: Steht schon hinter der Sektion
1465 aTmp = aTmp.GetNode().EndOfSectionIndex()+1;
1466 if( *pIdx <= aTmp )
1467 return; // FEHLER: Steht schon hinter der Sektion
1469 (*pIdx) = aTmp; // steht auf einem ContentNode
1472 void SwNodes::GoEndOfSection(SwNodeIndex *pIdx) const
1474 // falls er vor einem Endnode steht --> nichts tun
1475 if( !pIdx->GetNode().IsEndNode() )
1476 (*pIdx) = *pIdx->GetNode().EndOfSectionNode();
1479 SwCntntNode* SwNodes::GoNext(SwNodeIndex *pIdx) const
1481 if( pIdx->GetIndex() >= Count() - 1 )
1482 return 0;
1484 SwNodeIndex aTmp(*pIdx, +1);
1485 SwNode* pNd = 0;
1486 while( aTmp < Count()-1 && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
1487 aTmp++;
1489 if( aTmp == Count()-1 )
1490 pNd = 0;
1491 else
1492 (*pIdx) = aTmp;
1493 return (SwCntntNode*)pNd;
1496 SwCntntNode* SwNodes::GoPrevious(SwNodeIndex *pIdx) const
1498 if( !pIdx->GetIndex() )
1499 return 0;
1501 SwNodeIndex aTmp( *pIdx, -1 );
1502 SwNode* pNd = 0;
1503 while( aTmp.GetIndex() && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
1504 aTmp--;
1506 if( !aTmp.GetIndex() )
1507 pNd = 0;
1508 else
1509 (*pIdx) = aTmp;
1510 return (SwCntntNode*)pNd;
1513 SwNode* SwNodes::GoNextWithFrm(SwNodeIndex *pIdx) const
1515 if( pIdx->GetIndex() >= Count() - 1 )
1516 return 0;
1518 SwNodeIndex aTmp(*pIdx, +1);
1519 SwNode* pNd = 0;
1520 while( aTmp < Count()-1 )
1522 pNd = &aTmp.GetNode();
1523 SwModify *pMod = 0;
1524 if ( pNd->IsCntntNode() )
1525 pMod = (SwCntntNode*)pNd;
1526 else if ( pNd->IsTableNode() )
1527 pMod = ((SwTableNode*)pNd)->GetTable().GetFrmFmt();
1528 else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() )
1530 pNd = 0;
1531 break;
1533 if ( pMod && pMod->GetDepends() )
1535 SwClientIter aIter( *pMod );
1536 if( aIter.First( TYPE(SwFrm) ) )
1537 break;
1539 aTmp++;
1541 if( aTmp == Count()-1 )
1542 pNd = 0;
1543 else if( pNd )
1544 (*pIdx) = aTmp;
1545 return pNd;
1548 SwNode* SwNodes::GoPreviousWithFrm(SwNodeIndex *pIdx) const
1550 if( !pIdx->GetIndex() )
1551 return 0;
1553 SwNodeIndex aTmp( *pIdx, -1 );
1554 SwNode* pNd(0);
1555 while( aTmp.GetIndex() )
1557 pNd = &aTmp.GetNode();
1558 SwModify *pMod = 0;
1559 if ( pNd->IsCntntNode() )
1560 pMod = (SwCntntNode*)pNd;
1561 else if ( pNd->IsTableNode() )
1562 pMod = ((SwTableNode*)pNd)->GetTable().GetFrmFmt();
1563 else if( pNd->IsStartNode() && !pNd->IsSectionNode() )
1565 pNd = 0;
1566 break;
1568 if ( pMod && pMod->GetDepends() )
1570 SwClientIter aIter( *pMod );
1571 if( aIter.First( TYPE(SwFrm) ) )
1572 break;
1574 aTmp--;
1577 if( !aTmp.GetIndex() )
1578 pNd = 0;
1579 else if( pNd )
1580 (*pIdx) = aTmp;
1581 return pNd;
1586 /*************************************************************************
1588 |* BOOL SwNodes::CheckNodesRange()
1590 |* Beschreibung
1591 |* Teste ob der uebergene SRange nicht ueber die Grenzen der
1592 |* einzelnen Bereiche (PosIts, Autotext, Content, Icons und Inserts )
1593 |* hinaus reicht.
1594 |* Nach Wahrscheinlichkeit des Ranges sortiert.
1596 |* Alg.: Da festgelegt ist, das aRange.aEnd den 1.Node hinter dem Bereich
1597 |* bezeichnet, wird hier auf aEnd <= End.. getestet !!
1599 |* Parameter SwIndex & Start-Index vom Bereich
1600 |* SwIndex & End-Index vom Bereich
1601 |* BOOL TRUE: Start+End in gleicher Section!
1602 |* FALSE: Start+End in verschiedenen Sect.
1603 |* Return-Wert BOOL TRUE: gueltiger SRange
1604 |* FALSE: ungueltiger SRange
1606 |* Ersterstellung JP 23.04.91
1607 |* Letzte Aenderung JP 18.06.92
1609 *************************************************************************/
1611 inline int TstIdx( ULONG nSttIdx, ULONG nEndIdx, ULONG nStt, ULONG nEnd )
1613 return nStt < nSttIdx && nEnd >= nSttIdx &&
1614 nStt < nEndIdx && nEnd >= nEndIdx;
1617 BOOL SwNodes::CheckNodesRange( const SwNodeIndex& rStt, const SwNodeIndex& rEnd ) const
1619 ULONG nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
1620 if( TstIdx( nStt, nEnd, pEndOfContent->StartOfSectionIndex(),
1621 pEndOfContent->GetIndex() )) return TRUE;
1622 if( TstIdx( nStt, nEnd, pEndOfAutotext->StartOfSectionIndex(),
1623 pEndOfAutotext->GetIndex() )) return TRUE;
1624 if( TstIdx( nStt, nEnd, pEndOfPostIts->StartOfSectionIndex(),
1625 pEndOfPostIts->GetIndex() )) return TRUE;
1626 if( TstIdx( nStt, nEnd, pEndOfInserts->StartOfSectionIndex(),
1627 pEndOfInserts->GetIndex() )) return TRUE;
1628 if( TstIdx( nStt, nEnd, pEndOfRedlines->StartOfSectionIndex(),
1629 pEndOfRedlines->GetIndex() )) return TRUE;
1631 return FALSE; // liegt irgendwo dazwischen, FEHLER
1635 /*************************************************************************
1637 |* void SwNodes::DelNodes()
1639 |* Beschreibung
1640 |* Loesche aus den NodesArray ab einer Position entsprechend Node's.
1642 |* Parameter SwIndex & Der Startpunkt im Nodes-Array
1643 |* USHORT die Anzahl
1645 |* Ersterstellung JP 23.04.91
1646 |* Letzte Aenderung JP 23.04.91
1648 *************************************************************************/
1649 void SwNodes::DelNodes( const SwNodeIndex & rStart, ULONG nCnt )
1651 int bUpdateNum = 0;
1652 ULONG nSttIdx = rStart.GetIndex();
1654 if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 )
1656 // es wird das gesamte Nodes-Array zerstoert, man ist im Doc DTOR!
1657 // Die initialen Start-/End-Nodes duerfen nur im SwNodes-DTOR
1658 // zerstoert werden!
1659 SwNode* aEndNdArr[] = { pEndOfContent,
1660 pEndOfPostIts, pEndOfInserts,
1661 pEndOfAutotext, pEndOfRedlines,
1665 SwNode** ppEndNdArr = aEndNdArr;
1666 while( *ppEndNdArr )
1668 nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1;
1669 ULONG nEndIdx = (*ppEndNdArr)->GetIndex();
1671 if( nSttIdx != nEndIdx )
1672 RemoveNode( nSttIdx, nEndIdx - nSttIdx, TRUE );
1674 ++ppEndNdArr;
1677 else
1679 for( ULONG n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n )
1681 SwNode* pNd = (*this)[ n ];
1683 if( pNd->IsTxtNode() &&
1684 //NO_NUMBERING != ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
1685 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() ) //<-end,zhaojianwei
1686 { // loesche die Gliederungs-Indizies.
1687 USHORT nIdxPos;
1688 if( pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
1690 pOutlineNds->Remove( nIdxPos );
1691 bUpdateNum = 1;
1694 if( pNd->IsCntntNode() )
1696 ((SwCntntNode*)pNd)->InvalidateNumRule();
1697 ((SwCntntNode*)pNd)->DelFrms();
1700 RemoveNode( nSttIdx, nCnt, TRUE );
1702 // rufe noch das Update fuer die Gliederungsnumerierung auf
1703 if( bUpdateNum )
1704 UpdtOutlineIdx( rStart.GetNode() );
1709 /*************************************************************************
1711 |* USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1713 |* Beschreibung
1714 |* Berechne den hoehsten Level innerhalb des Bereiches
1716 |* Parameter SwNodes & das Node-Array
1717 |* SwNodeRange & der zu ueberpruefende Bereich
1718 |* Return USHORT der hoechste Level
1720 |* Ersterstellung JP 24.04.91
1721 |* Letzte Aenderung JP 24.04.91
1723 *************************************************************************/
1725 struct HighLevel
1727 USHORT nLevel, nTop;
1728 HighLevel( USHORT nLv ) : nLevel( nLv ), nTop( nLv ) {}
1732 BOOL _HighestLevel( const SwNodePtr& rpNode, void * pPara )
1734 HighLevel * pHL = (HighLevel*)pPara;
1735 if( rpNode->GetStartNode() )
1736 pHL->nLevel++;
1737 else if( rpNode->GetEndNode() )
1738 pHL->nLevel--;
1739 if( pHL->nTop > pHL->nLevel )
1740 pHL->nTop = pHL->nLevel;
1741 return TRUE;
1745 USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1747 HighLevel aPara( rNodes.GetSectionLevel( rRange.aStart ));
1748 rNodes.ForEach( rRange.aStart, rRange.aEnd, _HighestLevel, &aPara );
1749 return aPara.nTop;
1753 /*************************************************************************
1755 |* SwNodes::Move()
1757 |* Beschreibung
1758 |* Parameter SwPaM& zu kopierender Bereich
1759 |* SwNodes& in dieses Nodes-Array
1760 |* SwPosition& auf diese Position im Nodes-Array
1761 |* Ersterstellung JP 09.07.92
1762 |* Letzte Aenderung JP 09.07.92
1764 *************************************************************************/
1765 void SwNodes::Move( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes,
1766 BOOL )
1768 SwPosition *pStt = (SwPosition*)rPam.Start(), *pEnd = (SwPosition*)rPam.End();
1770 if( !rPam.HasMark() || *pStt >= *pEnd )
1771 return;
1773 if( this == &rNodes && *pStt <= rPos && rPos < *pEnd )
1774 return;
1776 SwNodeIndex aEndIdx( pEnd->nNode );
1777 SwNodeIndex aSttIdx( pStt->nNode );
1778 SwTxtNode* pSrcNd = (*this)[ aSttIdx ]->GetTxtNode();
1779 SwTxtNode* pDestNd = rNodes[ rPos.nNode ]->GetTxtNode();
1780 BOOL bSplitDestNd = TRUE;
1781 BOOL bSttTxtNd = 0 != pSrcNd;
1782 BOOL bCopyCollFmt = pDestNd && !pDestNd->GetTxt().Len();
1784 if( pSrcNd )
1786 // ist der 1.Node ein TextNode, dann muss im NodesArray auch
1787 // ein TextNode vorhanden sein, in den der Inhalt geschoben wird
1788 if( !pDestNd )
1790 pDestNd = rNodes.MakeTxtNode( rPos.nNode, pSrcNd->GetTxtColl() );
1791 rPos.nNode--;
1792 rPos.nContent.Assign( pDestNd, 0 );
1793 bCopyCollFmt = TRUE;
1795 /*!NOSPLIT bSplitDestNd = !bSplitNd &&
1796 ( pDestNd->Len() > rPos.nContent.GetIndex() ||
1797 !aEndIdx.GetNode().IsTxtNode() );
1799 // ASSERT( bSplitNd, "Move mit bSplitNode = FALSE" );
1800 bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() ||
1801 pEnd->nNode.GetNode().IsTxtNode();
1803 // verschiebe jetzt noch den Inhalt in den neuen Node
1804 BOOL bOneNd = pStt->nNode == pEnd->nNode;
1805 xub_StrLen nLen = ( bOneNd ? pEnd->nContent.GetIndex() : pSrcNd->Len() )
1806 - pStt->nContent.GetIndex();
1808 if( !pEnd->nNode.GetNode().IsCntntNode() )
1810 bOneNd = TRUE;
1811 ULONG nSttNdIdx = pStt->nNode.GetIndex() + 1,
1812 nEndNdIdx = pEnd->nNode.GetIndex();
1813 for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx )
1814 if( (*this)[ nSttNdIdx ]->IsCntntNode() )
1816 bOneNd = FALSE;
1817 break;
1821 // das kopieren / setzen der Vorlagen darf erst nach
1822 // dem Splitten erfolgen
1823 //!NOSPLIT if( !bOneNd && ( bSplitNd || bSplitDestNd ))
1824 if( !bOneNd && bSplitDestNd )
1826 if( !rPos.nContent.GetIndex() )
1827 bCopyCollFmt = TRUE;
1828 if( rNodes.IsDocNodes() )
1830 SwDoc* pInsDoc = pDestNd->GetDoc();
1831 BOOL bIsUndo = pInsDoc->DoesUndo();
1832 pInsDoc->DoUndo( FALSE );
1833 pInsDoc->SplitNode( rPos, false );
1834 pInsDoc->DoUndo( bIsUndo );
1836 else
1837 pDestNd->SplitCntntNode( rPos );
1839 if( rPos.nNode == aEndIdx )
1840 aEndIdx--;
1841 bSplitDestNd = TRUE;
1843 pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTxtNode();
1844 if( nLen )
1845 pSrcNd->Cut( pDestNd, SwIndex( pDestNd, pDestNd->Len()),
1846 pStt->nContent, nLen );
1848 else if( nLen )
1849 pSrcNd->Cut( pDestNd, rPos.nContent, pStt->nContent, nLen );
1851 if( bCopyCollFmt )
1853 SwDoc* pInsDoc = pDestNd->GetDoc();
1854 BOOL bIsUndo = pInsDoc->DoesUndo();
1855 pInsDoc->DoUndo( FALSE );
1856 pSrcNd->CopyCollFmt( *pDestNd );
1857 pInsDoc->DoUndo( bIsUndo );
1858 bCopyCollFmt = FALSE;
1861 if( bOneNd ) // das wars schon
1863 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
1864 // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
1865 // wird aufgehoben !
1866 pEnd->nContent = pStt->nContent;
1867 rPam.DeleteMark();
1868 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0, rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
1869 return;
1872 aSttIdx++;
1874 else if( pDestNd )
1876 if( rPos.nContent.GetIndex() )
1878 //!NOSPLIT if( !bSplitNd && rPos.nContent.GetIndex() == pDestNd->Len() )
1879 if( rPos.nContent.GetIndex() == pDestNd->Len() )
1880 rPos.nNode++;
1881 else if( rPos.nContent.GetIndex() )
1883 // falls im EndNode gesplittet wird, dann muss der EndIdx
1884 // korrigiert werden !!
1885 BOOL bCorrEnde = aEndIdx == rPos.nNode;
1886 // es wird kein Text an den TextNode angehaengt, also splitte ihn
1888 if( rNodes.IsDocNodes() )
1890 SwDoc* pInsDoc = pDestNd->GetDoc();
1891 BOOL bIsUndo = pInsDoc->DoesUndo();
1892 pInsDoc->DoUndo( FALSE );
1893 pInsDoc->SplitNode( rPos, false );
1894 pInsDoc->DoUndo( bIsUndo );
1896 else
1897 pDestNd->SplitCntntNode( rPos );
1899 pDestNd = rPos.nNode.GetNode().GetTxtNode();
1901 if( bCorrEnde )
1902 aEndIdx--;
1905 // am Ende steht noch ein leerer Text Node herum.
1906 bSplitDestNd = TRUE;
1909 pSrcNd = (*this)[ aEndIdx ]->GetTxtNode();
1910 if( pSrcNd )
1912 // if( pEnd->nContent.GetIndex() ? TRUE : aEndIdx != pStt->nNode )
1914 // am Bereichsende entsteht ein neuer TextNode
1915 if( !bSplitDestNd )
1917 if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() )
1918 rPos.nNode++;
1920 pDestNd = rNodes.MakeTxtNode( rPos.nNode, pSrcNd->GetTxtColl() );
1921 rPos.nNode--;
1922 rPos.nContent.Assign( pDestNd, 0 );
1924 else
1925 pDestNd = rNodes[ rPos.nNode ]->GetTxtNode();
1927 if( pDestNd && pEnd->nContent.GetIndex() )
1929 // verschiebe jetzt noch den Inhalt in den neuen Node
1930 SwIndex aIdx( pSrcNd, 0 );
1931 pSrcNd->Cut( pDestNd, rPos.nContent, aIdx,
1932 pEnd->nContent.GetIndex());
1935 if( bCopyCollFmt )
1937 SwDoc* pInsDoc = pDestNd->GetDoc();
1938 BOOL bIsUndo = pInsDoc->DoesUndo();
1939 pInsDoc->DoUndo( FALSE );
1940 pSrcNd->CopyCollFmt( *pDestNd );
1941 pInsDoc->DoUndo( bIsUndo );
1945 else
1947 if( bSttTxtNd && aEndIdx.GetNode().IsCntntNode() )
1948 aEndIdx++;
1949 //!NOSPLIT
1950 if( !bSplitDestNd )
1952 rPos.nNode++;
1953 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 );
1955 //!NOSPLIT
1958 if( aEndIdx != aSttIdx )
1960 // verschiebe jetzt die Nodes in das NodesArary
1961 SwNodeIndex aPrvIdx( rPos.nNode, -1 );
1962 ULONG nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex();
1963 SwNodeRange aRg( aSttIdx, aEndIdx );
1964 _MoveNodes( aRg, rNodes, rPos.nNode );
1965 // falls ins gleiche Nodes-Array verschoben wurde, stehen die
1966 // Indizies jetzt auch an der neuen Position !!!!
1967 // (also alles wieder umsetzen)
1968 if( &rNodes == this )
1969 pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff;
1972 // falls der Start-Node verschoben wurde, in dem der Cursor stand, so
1973 // muss der Content im akt. Content angemeldet werden !!!
1974 if( &pStt->nNode.GetNode() == &GetEndOfContent() &&
1975 !GoPrevious( &pStt->nNode ))
1977 ASSERT( FALSE, "Move() - kein ContentNode mehr vorhanden" );
1979 pStt->nContent.Assign( (*this)[ pStt->nNode ]->GetCntntNode(),
1980 pStt->nContent.GetIndex() );
1981 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
1982 // wurde, so stehen sie in unterschielichen Nodes. Auch die Selektion
1983 // wird aufgehoben !
1984 *pEnd = *pStt;
1985 rPam.DeleteMark();
1986 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0, rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
1991 /*************************************************************************
1993 |* SwNodes::_Copy()
1995 |* Beschreibung
1996 |* Parameter SwNodeRange& zu kopierender Bereich
1997 |* SwDoc& in dieses Dokument
1998 |* SwIndex& auf diese Position im Nodes-Array
1999 |* Ersterstellung JP 11.11.92
2000 |* Letzte Aenderung JP 11.11.92
2002 *************************************************************************/
2004 inline BYTE MaxLvl( BYTE nMin, BYTE nMax, short nNew )
2006 return (BYTE)(nNew < nMin ? nMin : nNew > nMax ? nMax : nNew);
2009 void SwNodes::_CopyNodes( const SwNodeRange& rRange,
2010 const SwNodeIndex& rIndex, BOOL bNewFrms, BOOL bTblInsDummyNode ) const
2012 SwDoc* pDoc = rIndex.GetNode().GetDoc();
2014 SwNode * pAktNode;
2015 if( rIndex == 0 ||
2016 ( (pAktNode = &rIndex.GetNode())->GetStartNode() &&
2017 !pAktNode->StartOfSectionIndex() ))
2018 return;
2020 SwNodeRange aRg( rRange );
2022 // "einfache" StartNodes oder EndNodes ueberspringen
2023 while( ND_STARTNODE == (pAktNode = (*this)[ aRg.aStart ])->GetNodeType()
2024 || ( pAktNode->IsEndNode() &&
2025 !pAktNode->pStartOfSection->IsSectionNode() ) )
2026 aRg.aStart++;
2028 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
2029 aRg.aEnd--;
2030 while( (( pAktNode = (*this)[ aRg.aEnd ])->GetStartNode() &&
2031 !pAktNode->IsSectionNode() ) ||
2032 ( pAktNode->IsEndNode() &&
2033 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) )
2034 aRg.aEnd--;
2035 aRg.aEnd++;
2037 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
2038 if( aRg.aStart >= aRg.aEnd )
2039 return;
2041 // when inserting into the source range, nothing need to be done
2042 DBG_ASSERT( &aRg.aStart.GetNodes() == this,
2043 "aRg should use thisnodes array" );
2044 DBG_ASSERT( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(),
2045 "Range across different nodes arrays? You deserve punishment!");
2046 if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() &&
2047 rIndex.GetIndex() >= aRg.aStart.GetIndex() &&
2048 rIndex.GetIndex() < aRg.aEnd.GetIndex() )
2049 return;
2051 SwNodeIndex aInsPos( rIndex );
2052 SwNodeIndex aOrigInsPos( rIndex, -1 ); // Originale Insert Pos
2053 USHORT nLevel = 0; // Level-Counter
2055 for( ULONG nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
2056 nNodeCnt > 0; --nNodeCnt )
2058 pAktNode = &aRg.aStart.GetNode();
2059 switch( pAktNode->GetNodeType() )
2061 case ND_TABLENODE:
2062 // dann kopiere mal den TableNode
2063 // Tabell in Fussnote kopieren ?
2064 if( aInsPos < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
2065 pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex()
2066 < aInsPos.GetIndex() )
2068 nNodeCnt -=
2069 ( pAktNode->EndOfSectionIndex() -
2070 aRg.aStart.GetIndex() );
2072 // dann alle Nodes der Tabelle in die akt. Zelle kopieren
2073 // fuer den TabellenNode einen DummyNode einfuegen?
2074 if( bTblInsDummyNode )
2075 new SwNode( aInsPos, ND_SECTIONDUMMY );
2077 for( aRg.aStart++; aRg.aStart.GetIndex() <
2078 pAktNode->EndOfSectionIndex();
2079 aRg.aStart++ )
2081 // fuer den Box-StartNode einen DummyNode einfuegen?
2082 if( bTblInsDummyNode )
2083 new SwNode( aInsPos, ND_SECTIONDUMMY );
2085 SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode();
2086 _CopyNodes( SwNodeRange( *pSttNd, + 1,
2087 *pSttNd->EndOfSectionNode() ),
2088 aInsPos, bNewFrms, FALSE );
2090 // fuer den Box-EndNode einen DummyNode einfuegen?
2091 if( bTblInsDummyNode )
2092 new SwNode( aInsPos, ND_SECTIONDUMMY );
2093 aRg.aStart = *pSttNd->EndOfSectionNode();
2095 // fuer den TabellenEndNode einen DummyNode einfuegen?
2096 if( bTblInsDummyNode )
2097 new SwNode( aInsPos, ND_SECTIONDUMMY );
2098 aRg.aStart = *pAktNode->EndOfSectionNode();
2100 else
2102 SwNodeIndex nStt( aInsPos, -1 );
2103 SwTableNode* pTblNd = ((SwTableNode*)pAktNode)->
2104 MakeCopy( pDoc, aInsPos );
2105 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2;
2107 aRg.aStart = pAktNode->EndOfSectionIndex();
2109 if( bNewFrms && pTblNd )
2111 nStt = aInsPos;
2112 pTblNd->MakeFrms( &nStt );
2115 break;
2117 case ND_SECTIONNODE: // SectionNode
2118 // If the end of the section is outside the copy range,
2119 // the section node will skipped, not copied!
2120 // If someone want to change this behaviour, he has to adjust the function
2121 // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
2122 if( pAktNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
2124 // also der gesamte, lege einen neuen SectionNode an
2125 SwNodeIndex nStt( aInsPos, -1 );
2126 SwSectionNode* pSectNd = ((SwSectionNode*)pAktNode)->
2127 MakeCopy( pDoc, aInsPos );
2129 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2;
2130 aRg.aStart = pAktNode->EndOfSectionIndex();
2132 if( bNewFrms && pSectNd &&
2133 !pSectNd->GetSection().IsHidden() )
2134 pSectNd->MakeFrms( &nStt );
2136 break;
2138 case ND_STARTNODE: // StartNode gefunden
2140 SwStartNode* pTmp = new SwStartNode( aInsPos, ND_STARTNODE,
2141 ((SwStartNode*)pAktNode)->GetStartNodeType() );
2142 new SwEndNode( aInsPos, *pTmp );
2143 aInsPos--;
2144 nLevel++;
2146 break;
2148 case ND_ENDNODE:
2149 if( nLevel ) // vollstaendige Section
2151 --nLevel;
2152 aInsPos++; // EndNode schon vorhanden
2154 else if( !pAktNode->pStartOfSection->IsSectionNode() )
2156 // erzeuge eine Section an der originalen InsertPosition
2157 SwNodeRange aTmpRg( aOrigInsPos, 1, aInsPos );
2158 pDoc->GetNodes().SectionDown( &aTmpRg,
2159 pAktNode->pStartOfSection->GetStartNodeType() );
2161 break;
2163 case ND_TEXTNODE:
2164 case ND_GRFNODE:
2165 case ND_OLENODE:
2167 SwCntntNode* pNew = ((SwCntntNode*)pAktNode)->MakeCopy(
2168 pDoc, aInsPos );
2169 if( !bNewFrms ) // dflt. werden die Frames immer angelegt
2170 pNew->DelFrms();
2172 break;
2174 case ND_SECTIONDUMMY:
2175 if( (const SwNodes*)this == GetDoc()->GetUndoNds() )
2177 // dann muss an der akt. InsPos auch ein SectionNode
2178 // (Start/Ende) stehen; dann diesen ueberspringen.
2179 // Andernfalls nicht weiter beachten.
2180 SwNode* pTmpNd = pDoc->GetNodes()[ aInsPos ];
2181 if( pTmpNd->IsSectionNode() ||
2182 pTmpNd->StartOfSectionNode()->IsSectionNode() )
2183 aInsPos++; // ueberspringen
2185 else {
2186 ASSERT( FALSE, "wie kommt diser Node ins Nodes-Array??" );
2188 break;
2190 default:
2191 ASSERT( FALSE, "weder Start-/End-/Content-Node, unbekannter Typ" );
2193 aRg.aStart++;
2197 #ifdef JP_DEBUG
2199 extern Writer* GetDebugWriter(const String&);
2201 Writer* pWriter = GetDebugWriter(aEmptyStr);
2202 if( pWriter )
2204 int nError;
2205 SvFileStream aStrm( "c:\\$$copy.db", STREAM_WRITE );
2206 SwWriter aWriter( aStrm, *pMyDoc );
2207 aWriter.Write( &nError, pWriter );
2210 #endif
2213 void SwNodes::_DelDummyNodes( const SwNodeRange& rRg )
2215 SwNodeIndex aIdx( rRg.aStart );
2216 while( aIdx.GetIndex() < rRg.aEnd.GetIndex() )
2218 if( ND_SECTIONDUMMY == aIdx.GetNode().GetNodeType() )
2219 RemoveNode( aIdx.GetIndex(), 1, TRUE );
2220 else
2221 aIdx++;
2225 SwStartNode* SwNodes::MakeEmptySection( const SwNodeIndex& rIdx,
2226 SwStartNodeType eSttNdTyp )
2228 SwStartNode* pSttNd = new SwStartNode( rIdx, ND_STARTNODE, eSttNdTyp );
2229 new SwEndNode( rIdx, *pSttNd );
2230 return pSttNd;
2234 SwStartNode* SwNodes::MakeTextSection( const SwNodeIndex & rWhere,
2235 SwStartNodeType eSttNdTyp,
2236 SwTxtFmtColl *pColl,
2237 SwAttrSet* pAutoAttr )
2239 SwStartNode* pSttNd = new SwStartNode( rWhere, ND_STARTNODE, eSttNdTyp );
2240 new SwEndNode( rWhere, *pSttNd );
2241 MakeTxtNode( SwNodeIndex( rWhere, - 1 ), pColl, pAutoAttr );
2242 return pSttNd;
2245 // zum naechsten Content-Node, der nicht geschuetzt oder versteckt ist
2246 // (beides auf FALSE ==> GoNext/GoPrevious!!!)
2247 SwCntntNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
2248 int bSkipHidden, int bSkipProtect ) const
2250 int bFirst = TRUE;
2251 SwNodeIndex aTmp( *pIdx );
2252 const SwNode* pNd;
2253 while( aTmp < Count() - 1 )
2255 if( ND_SECTIONNODE == ( pNd = (*this)[aTmp])->GetNodeType() )
2257 const SwSection& rSect = ((SwSectionNode*)pNd)->GetSection();
2258 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2259 (bSkipProtect && rSect.IsProtectFlag()) )
2260 // dann diese Section ueberspringen
2261 aTmp = *pNd->EndOfSectionNode();
2262 bFirst = FALSE;
2264 else if( bFirst )
2266 bFirst = FALSE;
2267 if( pNd->pStartOfSection->IsSectionNode() )
2269 const SwSection& rSect = ((SwSectionNode*)pNd->
2270 pStartOfSection)->GetSection();
2271 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2272 (bSkipProtect && rSect.IsProtectFlag()) )
2273 // dann diese Section ueberspringen
2274 aTmp = *pNd->EndOfSectionNode();
2277 else if( ND_CONTENTNODE & pNd->GetNodeType() )
2279 const SwSectionNode* pSectNd;
2280 if( ( bSkipHidden || bSkipProtect ) &&
2281 0 != (pSectNd = pNd->FindSectionNode() ) &&
2282 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
2283 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2285 aTmp = *pSectNd->EndOfSectionNode();
2287 else
2289 (*pIdx) = aTmp;
2290 return (SwCntntNode*)pNd;
2293 aTmp++;
2294 bFirst = FALSE;
2296 return 0;
2299 SwCntntNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
2300 int bSkipHidden, int bSkipProtect ) const
2302 int bFirst = TRUE;
2303 SwNodeIndex aTmp( *pIdx );
2304 const SwNode* pNd;
2305 while( aTmp > 0 )
2307 if( ND_ENDNODE == ( pNd = (*this)[aTmp])->GetNodeType() )
2309 if( pNd->pStartOfSection->IsSectionNode() )
2311 const SwSection& rSect = ((SwSectionNode*)pNd->
2312 pStartOfSection)->GetSection();
2313 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2314 (bSkipProtect && rSect.IsProtectFlag()) )
2315 // dann diese Section ueberspringen
2316 aTmp = *pNd->StartOfSectionNode();
2318 bFirst = FALSE;
2320 else if( bFirst )
2322 bFirst = FALSE;
2323 if( pNd->pStartOfSection->IsSectionNode() )
2325 const SwSection& rSect = ((SwSectionNode*)pNd->
2326 pStartOfSection)->GetSection();
2327 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2328 (bSkipProtect && rSect.IsProtectFlag()) )
2329 // dann diese Section ueberspringen
2330 aTmp = *pNd->StartOfSectionNode();
2333 else if( ND_CONTENTNODE & pNd->GetNodeType() )
2335 const SwSectionNode* pSectNd;
2336 if( ( bSkipHidden || bSkipProtect ) &&
2337 0 != (pSectNd = pNd->FindSectionNode() ) &&
2338 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
2339 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2341 aTmp = *pSectNd;
2343 else
2345 (*pIdx) = aTmp;
2346 return (SwCntntNode*)pNd;
2349 aTmp--;
2351 return 0;
2355 // suche den vorhergehenden [/nachfolgenden ] ContentNode oder
2356 // TabellenNode mit Frames. Wird kein Ende angeben, dann wird mit
2357 // dem FrameIndex begonnen; ansonsten, wird mit dem vor rFrmIdx und
2358 // dem hintern pEnd die Suche gestartet. Sollte kein gueltiger Node
2359 // gefunden werden, wird 0 returnt. rFrmIdx zeigt auf dem Node mit
2360 // Frames
2361 SwNode* SwNodes::FindPrvNxtFrmNode( SwNodeIndex& rFrmIdx,
2362 const SwNode* pEnd ) const
2364 SwNode* pFrmNd = 0;
2366 // habe wir gar kein Layout, vergiss es
2367 if( GetDoc()->GetRootFrm() )
2369 SwNode* pSttNd = &rFrmIdx.GetNode();
2371 // wird in eine versteckte Section verschoben ??
2372 SwSectionNode* pSectNd = pSttNd->IsSectionNode()
2373 ? pSttNd->StartOfSectionNode()->FindSectionNode()
2374 : pSttNd->FindSectionNode();
2375 if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag()/*IsHiddenFlag()*/ ) )
2377 // #130650# in a table in table situation we have to assure that we don't leave the
2378 // outer table cell when the inner table is looking for a PrvNxt...
2379 SwTableNode* pTableNd = pSttNd->IsTableNode()
2380 ? pSttNd->StartOfSectionNode()->FindTableNode()
2381 : pSttNd->FindTableNode();
2382 SwNodeIndex aIdx( rFrmIdx );
2383 SwNode* pNd;
2384 if( pEnd )
2386 aIdx--;
2387 pNd = &aIdx.GetNode();
2389 else
2390 pNd = pSttNd;
2392 if( ( pFrmNd = pNd )->IsCntntNode() )
2393 rFrmIdx = aIdx;
2395 // suche nach vorne/hinten nach einem Content Node
2396 else if( 0 != ( pFrmNd = GoPrevSection( &aIdx, TRUE, FALSE )) &&
2397 ::CheckNodesRange( aIdx, rFrmIdx, TRUE ) &&
2398 // nach vorne nie aus der Tabelle hinaus!
2399 pFrmNd->FindTableNode() == pTableNd &&
2400 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
2401 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
2402 == pSttNd->FindTableBoxStartNode() ) &&
2403 (!pSectNd || pSttNd->IsSectionNode() ||
2404 pSectNd->GetIndex() < pFrmNd->GetIndex())
2407 rFrmIdx = aIdx;
2409 else
2411 if( pEnd )
2412 aIdx = pEnd->GetIndex() + 1;
2413 else
2414 aIdx = rFrmIdx;
2416 // JP 19.09.93: aber nie die Section dafuer verlassen !!
2417 if( ( pEnd && ( pFrmNd = &aIdx.GetNode())->IsCntntNode() ) ||
2418 ( 0 != ( pFrmNd = GoNextSection( &aIdx, TRUE, FALSE )) &&
2419 ::CheckNodesRange( aIdx, rFrmIdx, TRUE ) &&
2420 ( pFrmNd->FindTableNode() == pTableNd &&
2421 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
2422 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
2423 == pSttNd->FindTableBoxStartNode() ) ) &&
2424 (!pSectNd || pSttNd->IsSectionNode() ||
2425 pSectNd->EndOfSectionIndex() > pFrmNd->GetIndex())
2428 //JP 18.02.99: Undo von Merge einer Tabelle mit der
2429 // der vorherigen, wenn dahinter auch noch eine steht
2430 // falls aber der Node in einer Tabelle steht, muss
2431 // natuerlich dieser returnt werden, wenn der SttNode eine
2432 // Section oder Tabelle ist!
2433 SwTableNode* pTblNd;
2434 if( pSttNd->IsTableNode() &&
2435 0 != ( pTblNd = pFrmNd->FindTableNode() ) &&
2436 // TABLE IN TABLE:
2437 pTblNd != pSttNd->StartOfSectionNode()->FindTableNode() )
2439 pFrmNd = pTblNd;
2440 rFrmIdx = *pFrmNd;
2442 else
2443 rFrmIdx = aIdx;
2445 else if( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
2447 pFrmNd = pNd->StartOfSectionNode();
2448 rFrmIdx = *pFrmNd;
2450 else
2452 if( pEnd )
2453 aIdx = pEnd->GetIndex() + 1;
2454 else
2455 aIdx = rFrmIdx.GetIndex() + 1;
2457 if( (pFrmNd = &aIdx.GetNode())->IsTableNode() )
2458 rFrmIdx = aIdx;
2459 else
2461 pFrmNd = 0;
2463 // is there some sectionnodes before a tablenode?
2464 while( aIdx.GetNode().IsSectionNode() )
2466 const SwSection& rSect = aIdx.GetNode().
2467 GetSectionNode()->GetSection();
2468 if( rSect.IsHiddenFlag() )
2469 aIdx = aIdx.GetNode().EndOfSectionIndex()+1;
2470 else
2471 aIdx++;
2473 if( aIdx.GetNode().IsTableNode() )
2475 rFrmIdx = aIdx;
2476 pFrmNd = &aIdx.GetNode();
2483 return pFrmNd;
2486 void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
2487 FnForEach_SwNodes fnForEach, void* pArgs )
2489 BigPtrArray::ForEach( rStart.GetIndex(), rEnd.GetIndex(),
2490 (FnForEach) fnForEach, pArgs );
2493 struct _TempBigPtrEntry : public BigPtrEntry
2495 _TempBigPtrEntry() {}
2499 void SwNodes::RemoveNode( ULONG nDelPos, ULONG nSz, BOOL bDel )
2501 ULONG nEnd = nDelPos + nSz;
2502 SwNode* pNew = (*this)[ nEnd ];
2504 if( pRoot )
2506 SwNodeIndex *p = pRoot;
2507 while( p )
2509 ULONG nIdx = p->GetIndex();
2510 SwNodeIndex* pNext = p->pNext;
2511 if( nDelPos <= nIdx && nIdx < nEnd )
2512 (*p) = *pNew;
2514 p = pNext;
2517 p = pRoot->pPrev;
2518 while( p )
2520 ULONG nIdx = p->GetIndex();
2521 SwNodeIndex* pPrev = p->pPrev;
2522 if( nDelPos <= nIdx && nIdx < nEnd )
2523 (*p) = *pNew;
2525 p = pPrev;
2530 for (ULONG nCnt = 0; nCnt < nSz; nCnt++)
2532 SwTxtNode * pTxtNd = ((*this)[ nDelPos + nCnt ])->GetTxtNode();
2534 if (pTxtNd)
2536 // --> OD 2008-03-13 #refactorlists#
2537 // pTxtNd->UnregisterNumber();
2538 pTxtNd->RemoveFromList();
2539 // <--
2544 if( bDel )
2546 ULONG nCnt = nSz;
2547 SwNode *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ];
2549 // temp. Object setzen
2550 //JP 24.08.98: muessten eigentlich einzeln removed werden, weil
2551 // das Remove auch rekursiv gerufen werden kann, z.B. bei
2552 // zeichengebundenen Rahmen. Da aber dabei viel zu viel
2553 // ablaueft, wird hier ein temp. Objekt eingefuegt, das
2554 // dann mit dem Remove wieder entfernt wird.
2555 // siehe Bug 55406
2556 _TempBigPtrEntry aTempEntry;
2557 BigPtrEntry* pTempEntry = &aTempEntry;
2559 while( nCnt-- )
2561 delete pDel;
2562 pDel = pPrev;
2563 ULONG nPrevNdIdx = pPrev->GetIndex();
2564 BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
2565 if( nCnt )
2566 pPrev = (*this)[ nPrevNdIdx - 1 ];
2568 nDelPos = pDel->GetIndex() + 1;
2571 BigPtrArray::Remove( nDelPos, nSz );
2574 void SwNodes::RegisterIndex( SwNodeIndex& rIdx )
2576 if( !pRoot ) // noch keine Root gesetzt?
2578 pRoot = &rIdx;
2579 pRoot->pPrev = 0;
2580 pRoot->pNext = 0;
2582 else
2584 // immer hinter die Root haengen
2585 rIdx.pNext = pRoot->pNext;
2586 pRoot->pNext = &rIdx;
2587 rIdx.pPrev = pRoot;
2588 if( rIdx.pNext )
2589 rIdx.pNext->pPrev = &rIdx;
2593 void SwNodes::DeRegisterIndex( SwNodeIndex& rIdx )
2595 SwNodeIndex* pN = rIdx.pNext;
2596 SwNodeIndex* pP = rIdx.pPrev;
2598 if( pRoot == &rIdx )
2599 pRoot = pP ? pP : pN;
2601 if( pP )
2602 pP->pNext = pN;
2603 if( pN )
2604 pN->pPrev = pP;
2606 rIdx.pNext = 0;
2607 rIdx.pPrev = 0;
2610 void SwNodes::InsertNode( const SwNodePtr pNode,
2611 const SwNodeIndex& rPos )
2613 const ElementPtr pIns = pNode;
2614 BigPtrArray::Insert( pIns, rPos.GetIndex() );
2617 void SwNodes::InsertNode( const SwNodePtr pNode,
2618 ULONG nPos )
2620 const ElementPtr pIns = pNode;
2621 BigPtrArray::Insert( pIns, nPos );
2624 // ->#112139#
2625 SwNode * SwNodes::DocumentSectionStartNode(SwNode * pNode) const
2627 if (NULL != pNode)
2629 SwNodeIndex aIdx(*pNode);
2631 if (aIdx <= (*this)[0]->EndOfSectionIndex())
2632 pNode = (*this)[0];
2633 else
2635 while ((*this)[0] != pNode->StartOfSectionNode())
2636 pNode = pNode->StartOfSectionNode();
2640 return pNode;
2643 SwNode * SwNodes::DocumentSectionEndNode(SwNode * pNode) const
2645 return DocumentSectionStartNode(pNode)->EndOfSectionNode();
2648 //SwNode * SwNodes::operator[](int n) const
2650 // return operator[]((ULONG) n);
2652 // <-#112139#
2654 sal_Bool SwNodes::IsDocNodes() const
2656 return this == &pMyDoc->GetNodes();