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 $
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"
41 #include <numrule.hxx>
43 #include <ndnotxt.hxx>
44 #include <swtable.hxx> // fuer erzuegen / loeschen der Table-Frames
46 #include <section.hxx>
48 #include <swddetbl.hxx>
50 #include <fmtmeta.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)
63 #include "shellio.hxx"
67 // Funktion zum bestimmen des hoechsten Levels innerhalb des Bereiches
69 USHORT
HighestLevel( SwNodes
& rNodes
, const SwNodeRange
& rRange
);
71 //-----------------------------------------------------------------------
73 /*******************************************************************
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?" );
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 /*******************************************************************
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
125 *******************************************************************/
133 SwNodeIndex
aNdIdx( *this );
136 pNode
= &aNdIdx
.GetNode();
137 if( pNode
== pEndOfContent
)
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();
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
);
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();
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();
221 if( RES_CONDTXTFMTCOLL
== rTxtNd
.GetTxtColl()->Which() )
222 rTxtNd
.ChkCondColl();
225 else if( rNd
.IsCntntNode() )
226 ((SwCntntNode
&)rNd
).InvalidateNumRule();
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
;
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() )
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?
261 const SwNumRule
* pNumRule
= pTxtNd
->GetNumRule();
262 if( pNumRule
&& sNumRule
!= pNumRule
->GetName() )
264 sNumRule
= pNumRule
->GetName();
265 SwNumRule
* pDestRule
= pDestDoc
->FindNumRulePtr( sNumRule
);
267 pDestRule
->SetInvalidRule( TRUE
);
269 pDestDoc
->MakeNumRule( sNumRule
, pNumRule
);
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();
283 RemoveNode( rDelPos
.GetIndex(), 1, FALSE
); // Indizies verschieben !!
284 SwCntntNode
* pCNd
= pNd
->GetCntntNode();
285 rNds
.InsertNode( pNd
, aInsPos
);
289 SwTxtNode
* pTxtNd
= pCNd
->GetTxtNode();
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();
307 // Sonderbehandlung fuer die Felder!
308 if( pHts
&& pHts
->Count() )
310 int bToUndo
= &pDestDoc
->GetNodes() != &rNds
;
311 for( USHORT i
= pHts
->Count(); i
; )
314 SwTxtAttr
* const pAttr
= pHts
->GetTextHint( --i
);
315 switch ( pAttr
->Which() )
317 case RES_TXTATR_FIELD
:
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
) );
329 if( RES_DDEFLD
== pTyp
->Which() )
332 ((SwDDEFieldType
*)pTyp
)->DecRefCnt();
334 ((SwDDEFieldType
*)pTyp
)->IncRefCnt();
336 nDelMsg
= RES_FIELD_DELETED
;
340 nDelMsg
= RES_FOOTNOTE_DELETED
;
343 case RES_TXTATR_TOXMARK
:
344 nDelMsg
= RES_TOXMARK_DELETED
;
347 case RES_TXTATR_REFMARK
:
348 nDelMsg
= RES_REFMARK_DELETED
;
351 case RES_TXTATR_META
:
352 case RES_TXTATR_METAFIELD
:
353 static_cast<SwFmtMeta
&>(pAttr
->GetAttr())
360 if( nDelMsg
&& bToUndo
)
362 SwPtrMsgPoolItem
aMsgHint( nDelMsg
,
363 (void*)&pAttr
->GetAttr() );
364 rNds
.GetDoc()->GetUnoCallBack()->
365 Modify( &aMsgHint
, &aMsgHint
);
370 if( RES_CONDTXTFMTCOLL
== pTxtNd
->GetTxtColl()->Which() )
371 pTxtNd
->ChkCondColl();
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 );
393 bNewFrms
= &GetDoc()->GetNodes() == (const SwNodes
*)&rNds
&&
394 GetDoc()->GetRootFrm();
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() )
413 ASSERT( !this, "ChgNode() - kein FrameNode gefunden" );
417 while( aIdx
!= rInsPos
)
419 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
422 if( pFrmNd
->IsTableNode() )
423 ((SwTableNode
*)pFrmNd
)->MakeFrms( aIdx
);
424 else if( pFrmNd
->IsSectionNode() )
425 ((SwSectionNode
*)pFrmNd
)->MakeFrms( aIdx
);
427 ((SwCntntNode
*)pFrmNd
)->MakeFrms( *pCNd
);
436 /***********************************************************************
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
)
461 ( (pAktNode
= &aIndex
.GetNode())->GetStartNode() &&
462 !pAktNode
->StartOfSectionIndex() ))
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() ) )
474 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
476 while( ( (( pAktNode
= &aRg
.aEnd
.GetNode())->GetStartNode() &&
477 !pAktNode
->IsSectionNode() ) ||
478 ( pAktNode
->IsEndNode() &&
479 ND_STARTNODE
== pAktNode
->pStartOfSection
->GetNodeType()) ) &&
480 aRg
.aEnd
> aRg
.aStart
)
484 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
485 if( aRg
.aStart
>= aRg
.aEnd
)
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() ) )
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() )
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
);
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;
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() );
551 // loesche erstmal die Frames
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();
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
);
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();
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();
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
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();
650 if( rNodes
.IsDocNodes() )
657 if( GetDoc()->GetUndoNds() == &rNodes
)
659 SwFrmFmt
* pTblFmt
= pTblNd
->GetTable().GetFrmFmt();
660 SwPtrMsgPoolItem
aMsgHint( RES_REMOVE_UNO_OBJECT
,
662 pTblFmt
->Modify( &aMsgHint
, &aMsgHint
);
667 SwNodeIndex
aTmp( aIdx
);
668 pTblNd
->MakeFrms( &aTmp
);
673 else if( pSttNd
->GetIndex() < aRg
.aStart
.GetIndex() )
675 // SectionNode: es wird nicht die gesamte Section
676 // verschoben, also bewege nur die
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
,
685 /*?? welcher NodeTyp ??*/
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
699 new SwNode( aIdx
, ND_SECTIONDUMMY
);
703 // JP 18.5.2001: neue Section anlegen?? Bug 70454
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
)
722 SwSectionNode
* pSctNd
= pSttNd
->GetSectionNode();
723 if( bNewFrms
&& pSctNd
)
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
);
739 pSttNd
->pEndOfSection
= (SwEndNode
*)pAktNode
;
743 nLevel
++; // den Index auf StartNode auf den Stack
744 aSttNdStack
.C40_INSERT( SwStartNode
, pSttNd
, nLevel
);
746 // SectionNode muss noch ein paar Indizies ummelden
749 pSctNd
->NodesArrChgd();
761 ( (const SwNodes
*)&rNodes
== GetDoc()->GetUndoNds() ) )
763 // dann muss an der akt. InsPos ein SectionDummyNode
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
);
774 new SwNode( aIdx
, ND_SECTIONDUMMY
);
783 // Bug #78589# - empty section -> nothing to do
784 // and only if it's a top level section
785 if( !nInsPos
&& !nLevel
)
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
,
797 ((SwStartNode
*)pAktNode
)->GetStartNodeType() );
801 SwNodeIndex
aTmpEIdx( aOrigInsPos
.aEnd
);
802 new SwEndNode( aTmpEIdx
, *pTmpStt
);
806 // setze die StartOfSection richtig
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();
820 pAktNode
->pStartOfSection
= pTmpStt
;
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
);
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
845 // loesche nur noch den Pointer aus dem Nodes-Array.
846 // RemoveNode( aRg.aEnd.GetIndex(), 1, FALSE );
847 RemoveNode( aRg
.aEnd
.GetIndex(), 1, TRUE
);
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
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 );
878 if( bNewFrms
&& pAktNode
->GetCntntNode() )
879 ((SwCntntNode
*)pAktNode
)->DelFrms();
881 pAktNode
->pStartOfSection
= aSttNdStack
[ nLevel
];
887 case ND_SECTIONDUMMY
:
888 if( (const SwNodes
*)this == GetDoc()->GetUndoNds() )
890 if( &rNodes
== this ) // innerhalb vom UndoNodesArray
893 pAktNode
->pStartOfSection
= aSttNdStack
[ nLevel
];
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
);
910 SwNode
* pTmpNd
= &aIdx
.GetNode();
911 if( pTmpNd
->IsSectionNode() ||
912 pTmpNd
->StartOfSectionNode()->IsSectionNode() )
913 aIdx
--; // ueberspringen
917 ASSERT( FALSE
, "wie kommt diser Node ins Nodes-Array??" );
923 ASSERT( FALSE
, "was ist das fuer ein Node??" );
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() );
953 UpdtOutlineIdx( aRg
.aEnd
.GetNode() );
954 rNodes
.UpdtOutlineIdx( aOrigInsPos
.aStart
.GetNode() );
959 extern Writer
* GetDebugWriter(const String
&);
961 Writer
* pWriter
= GetDebugWriter(aEmptyStr
);
965 SvFileStream
aStrm( "c:\\$$move.db", STREAM_WRITE
);
966 SwWriter
aWriter( aStrm
, *pMyDoc
);
967 aWriter
.Write( &nError
, pWriter
);
976 /*******************************************************************
978 |* SwNodes::SectionDown
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 !! )
998 |* rRange.aStart: Einfuegeposition des StartNodes
999 |* rRange.aEnd: Einfuegeposition des EndNodes
1001 |* rRange.aStart: steht hinter dem eingefuegten Startnode
1002 |* rRange.aEnd: steht auf dem eingefuegen Endnode
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.
1011 |* die Debugging Tools geben rRange beim Eintritt und beim
1012 |* Verlassen der Funktion aus
1015 |* VER0100 vb 901214
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
))
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
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
1048 if( pRange
->aEnd
.GetNode().GetStartNode() )
1049 DelNodes( pRange
->aEnd
, 1 );
1053 // fuege einen neuen EndNode ein
1054 new SwEndNode( pRange
->aEnd
, *pRange
->aStart
.GetNode().GetStartNode() );
1058 SectionUpDown( aTmpIdx
, pRange
->aEnd
);
1061 /*******************************************************************
1063 |* SwNodes::SectionUp
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 !! )
1079 |* rRange.aStart: Anfang des hoeher zubewegenden Bereiches
1080 |* rRange.aEnd: der 1.Node hinter dem Bereich
1082 |* rRange.aStart: an der ersten Position innerhalb des
1083 |* hochbewegten Bereiches
1084 |* rRange.aEnd: an der letzten Position innerhalb des
1085 |* hochbewegten Bereiches
1088 |* die Debugging Tools geben rRange beim Eintritt und beim
1089 |* Verlassen der Funktion aus
1092 |* VER0100 vb 901214
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 ))
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;
1133 DelNodes( pRange
->aStart
, 1 );
1135 else if( aIdx
== pRange
->aStart
.GetIndex()-1 ) // vor StartNode
1136 DelNodes( aIdx
, 1 );
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 );
1148 pAktNode
= new SwStartNode( pRange
->aEnd
);
1149 /*?? welcher NodeTyp ??*/
1150 aTmpIdx
= *pRange
->aEnd
.GetNode().EndOfSectionNode();
1154 SectionUpDown( aIdx
, aTmpIdx
);
1158 /*************************************************************************
1160 |* SwNodes::SectionUpDown()
1163 |* Methode setzt die Indizies die bei SectionUp oder SectionDwon
1164 |* veraendert wurden wieder richtig, sodass die Ebenen wieder
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
)
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 )
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
1219 /*******************************************************************
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.
1232 |* SwIndex &rIndex bezeichnet die Position, an der
1234 |* rIndex ist nach Aufruf der Funktion unveraendert (Kopie?!)
1235 |* USHORT nNodes bezeichnet die Anzahl der zu loeschenden
1236 |* Nodes; ist auf 1 defaulted
1239 |* geben beim Eintritt in die Funktion Position und Anzahl
1240 |* der zu loeschenden Nodes aus.
1243 |* VER0100 vb 901214
1246 |* VER0100 vb 901214
1248 *******************************************************************/
1249 void SwNodes::Delete(const SwNodeIndex
&rIndex
, ULONG nNodes
)
1251 USHORT nLevel
= 0; // Level-Counter
1254 ULONG nCnt
= Count() - rIndex
.GetIndex() - 1;
1255 if( nCnt
> nNodes
) nCnt
= nNodes
;
1257 if( nCnt
== 0 ) // keine Anzahl -> 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
) )
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() ))
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
1280 BOOL bSaveInNodesDel
= bInNodesDel
;
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();
1298 SwNode
*pNd
, *pChkNd
= pAktNode
->pStartOfSection
;
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();
1323 } while( pNd
!= pChkNd
);
1327 RemoveNode( aRg
.aEnd
.GetIndex()+1, nCnt
, TRUE
); // loesche
1329 aRg
.aEnd
--; // vor den EndNode
1333 else if( pAktNode
->GetStartNode() ) // StartNode gefunden
1335 if( nLevel
== 0 ) // es wird eine Stufe runter gestuft
1339 // loesche jetzt das Array
1341 RemoveNode( aRg
.aEnd
.GetIndex(), nCnt
, TRUE
);
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
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();
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();
1366 else // normaler Node, also ins TmpArray einfuegen
1368 SwTxtNode
* pTxtNd
= pAktNode
->GetTxtNode();
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();
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
1400 bInNodesDel
= bSaveInNodesDel
;
1404 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
1405 if( bUpdateOutline
|| bInDelUpdOutl
)
1407 UpdtOutlineIdx( aRg
.aEnd
.GetNode() );
1408 bInDelUpdOutl
= FALSE
;
1414 if( bUpdateOutline
)
1415 bInDelUpdOutl
= TRUE
;
1419 /*******************************************************************
1421 |* SwNodes::GetSectionLevel
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)
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.
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.
1447 |* VER0100 vb 901214
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
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
1475 return; // FEHLER: Steht schon hinter der Sektion
1476 aTmp
= aTmp
.GetNode().EndOfSectionIndex()+1;
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 )
1495 SwNodeIndex
aTmp(*pIdx
, +1);
1497 while( aTmp
< Count()-1 && 0 == ( pNd
= &aTmp
.GetNode())->IsCntntNode() )
1500 if( aTmp
== Count()-1 )
1504 return (SwCntntNode
*)pNd
;
1507 SwCntntNode
* SwNodes::GoPrevious(SwNodeIndex
*pIdx
) const
1509 if( !pIdx
->GetIndex() )
1512 SwNodeIndex
aTmp( *pIdx
, -1 );
1514 while( aTmp
.GetIndex() && 0 == ( pNd
= &aTmp
.GetNode())->IsCntntNode() )
1517 if( !aTmp
.GetIndex() )
1521 return (SwCntntNode
*)pNd
;
1524 SwNode
* SwNodes::GoNextWithFrm(SwNodeIndex
*pIdx
) const
1526 if( pIdx
->GetIndex() >= Count() - 1 )
1529 SwNodeIndex
aTmp(*pIdx
, +1);
1531 while( aTmp
< Count()-1 )
1533 pNd
= &aTmp
.GetNode();
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() )
1544 if ( pMod
&& pMod
->GetDepends() )
1546 SwClientIter
aIter( *pMod
);
1547 if( aIter
.First( TYPE(SwFrm
) ) )
1552 if( aTmp
== Count()-1 )
1559 SwNode
* SwNodes::GoPreviousWithFrm(SwNodeIndex
*pIdx
) const
1561 if( !pIdx
->GetIndex() )
1564 SwNodeIndex
aTmp( *pIdx
, -1 );
1566 while( aTmp
.GetIndex() )
1568 pNd
= &aTmp
.GetNode();
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() )
1579 if ( pMod
&& pMod
->GetDepends() )
1581 SwClientIter
aIter( *pMod
);
1582 if( aIter
.First( TYPE(SwFrm
) ) )
1588 if( !aTmp
.GetIndex() )
1597 /*************************************************************************
1599 |* BOOL SwNodes::CheckNodesRange()
1602 |* Teste ob der uebergene SRange nicht ueber die Grenzen der
1603 |* einzelnen Bereiche (PosIts, Autotext, Content, Icons und Inserts )
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()
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
)
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
);
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.
1699 if( pOutlineNds
->Seek_Entry( pNd
, &nIdxPos
))
1701 pOutlineNds
->Remove( nIdxPos
);
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
1715 UpdtOutlineIdx( rStart
.GetNode() );
1720 /*************************************************************************
1722 |* USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
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 *************************************************************************/
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() )
1748 else if( rpNode
->GetEndNode() )
1750 if( pHL
->nTop
> pHL
->nLevel
)
1751 pHL
->nTop
= pHL
->nLevel
;
1756 USHORT
HighestLevel( SwNodes
& rNodes
, const SwNodeRange
& rRange
)
1758 HighLevel
aPara( rNodes
.GetSectionLevel( rRange
.aStart
));
1759 rNodes
.ForEach( rRange
.aStart
, rRange
.aEnd
, _HighestLevel
, &aPara
);
1764 /*************************************************************************
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
)
1784 if( this == &rNodes
&& *pStt
<= rPos
&& rPos
< *pEnd
)
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();
1796 // ist der 1.Node ein TextNode, dann muss im NodesArray auch
1797 // ein TextNode vorhanden sein, in den der Inhalt geschoben wird
1800 pDestNd
= rNodes
.MakeTxtNode( rPos
.nNode
, pSrcNd
->GetTxtColl() );
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() )
1817 ULONG nSttNdIdx
= pStt
->nNode
.GetIndex() + 1;
1818 const ULONG nEndNdIdx
= pEnd
->nNode
.GetIndex();
1819 for( ; nSttNdIdx
< nEndNdIdx
; ++nSttNdIdx
)
1821 if( (*this)[ nSttNdIdx
]->IsCntntNode() )
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
);
1847 pDestNd
->SplitCntntNode( rPos
);
1850 if( rPos
.nNode
== aEndIdx
)
1854 bSplitDestNd
= TRUE
;
1856 pDestNd
= rNodes
[ rPos
.nNode
.GetIndex() - 1 ]->GetTxtNode();
1859 pSrcNd
->CutText( pDestNd
, SwIndex( pDestNd
, pDestNd
->Len()),
1860 pStt
->nContent
, nLen
);
1865 pSrcNd
->CutText( pDestNd
, rPos
.nContent
, pStt
->nContent
, nLen
);
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
;
1885 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
1886 rNodes
.IsDocNodes() ? SWFMTFLD_INSERTED
: SWFMTFLD_REMOVED
) );
1894 if( rPos
.nContent
.GetIndex() )
1896 if( rPos
.nContent
.GetIndex() == pDestNd
->Len() )
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
);
1917 pDestNd
->SplitCntntNode( rPos
);
1920 pDestNd
= rPos
.nNode
.GetNode().GetTxtNode();
1928 // am Ende steht noch ein leerer Text Node herum.
1929 bSplitDestNd
= TRUE
;
1932 SwTxtNode
* const pEndSrcNd
= (*this)[ aEndIdx
]->GetTxtNode();
1936 // am Bereichsende entsteht ein neuer TextNode
1939 if( rPos
.nNode
< rNodes
.GetEndOfContent().GetIndex() )
1945 rNodes
.MakeTxtNode( rPos
.nNode
, pEndSrcNd
->GetTxtColl() );
1947 rPos
.nContent
.Assign( pDestNd
, 0 );
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());
1964 SwDoc
* const pInsDoc
= pDestNd
->GetDoc();
1965 const bool bIsUndo
= pInsDoc
->DoesUndo();
1966 pInsDoc
->DoUndo( false );
1967 pEndSrcNd
->CopyCollFmt( *pDestNd
);
1968 pInsDoc
->DoUndo( bIsUndo
);
1974 if ( pSrcNd
&& aEndIdx
.GetNode().IsCntntNode() )
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" );
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 !
2015 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
2016 rNodes
.IsDocNodes() ? SWFMTFLD_INSERTED
: SWFMTFLD_REMOVED
) );
2021 /*************************************************************************
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();
2046 ( (pAktNode
= &rIndex
.GetNode())->GetStartNode() &&
2047 !pAktNode
->StartOfSectionIndex() ))
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() ) )
2058 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
2060 while( (( pAktNode
= (*this)[ aRg
.aEnd
])->GetStartNode() &&
2061 !pAktNode
->IsSectionNode() ) ||
2062 ( pAktNode
->IsEndNode() &&
2063 ND_STARTNODE
== pAktNode
->pStartOfSection
->GetNodeType()) )
2067 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
2068 if( aRg
.aStart
>= aRg
.aEnd
)
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() )
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() )
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() )
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();
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();
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
)
2142 pTblNd
->MakeFrms( &nStt
);
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
);
2168 case ND_STARTNODE
: // StartNode gefunden
2170 SwStartNode
* pTmp
= new SwStartNode( aInsPos
, ND_STARTNODE
,
2171 ((SwStartNode
*)pAktNode
)->GetStartNodeType() );
2172 new SwEndNode( aInsPos
, *pTmp
);
2179 if( nLevel
) // vollstaendige Section
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() );
2197 SwCntntNode
* pNew
= ((SwCntntNode
*)pAktNode
)->MakeCopy(
2199 if( !bNewFrms
) // dflt. werden die Frames immer angelegt
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
2216 ASSERT( FALSE
, "wie kommt diser Node ins Nodes-Array??" );
2221 ASSERT( FALSE
, "weder Start-/End-/Content-Node, unbekannter Typ" );
2229 extern Writer
* GetDebugWriter(const String
&);
2231 Writer
* pWriter
= GetDebugWriter(aEmptyStr
);
2235 SvFileStream
aStrm( "c:\\$$copy.db", STREAM_WRITE
);
2236 SwWriter
aWriter( aStrm
, *pMyDoc
);
2237 aWriter
.Write( &nError
, pWriter
);
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
);
2255 SwStartNode
* SwNodes::MakeEmptySection( const SwNodeIndex
& rIdx
,
2256 SwStartNodeType eSttNdTyp
)
2258 SwStartNode
* pSttNd
= new SwStartNode( rIdx
, ND_STARTNODE
, eSttNdTyp
);
2259 new SwEndNode( rIdx
, *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
);
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
2281 SwNodeIndex
aTmp( *pIdx
);
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();
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();
2320 return (SwCntntNode
*)pNd
;
2329 SwCntntNode
* SwNodes::GoPrevSection( SwNodeIndex
* pIdx
,
2330 int bSkipHidden
, int bSkipProtect
) const
2333 SwNodeIndex
aTmp( *pIdx
);
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();
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() )) )
2376 return (SwCntntNode
*)pNd
;
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
2391 SwNode
* SwNodes::FindPrvNxtFrmNode( SwNodeIndex
& rFrmIdx
,
2392 const SwNode
* pEnd
) const
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
);
2417 pNd
= &aIdx
.GetNode();
2422 if( ( pFrmNd
= pNd
)->IsCntntNode() )
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())
2442 aIdx
= pEnd
->GetIndex() + 1;
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() ) &&
2467 pTblNd
!= pSttNd
->StartOfSectionNode()->FindTableNode() )
2475 else if( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsTableNode() )
2477 pFrmNd
= pNd
->StartOfSectionNode();
2483 aIdx
= pEnd
->GetIndex() + 1;
2485 aIdx
= rFrmIdx
.GetIndex() + 1;
2487 if( (pFrmNd
= &aIdx
.GetNode())->IsTableNode() )
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;
2503 if( aIdx
.GetNode().IsTableNode() )
2506 pFrmNd
= &aIdx
.GetNode();
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
];
2536 SwNodeIndex
*p
= pRoot
;
2539 ULONG nIdx
= p
->GetIndex();
2540 SwNodeIndex
* pNext
= p
->pNext
;
2541 if( nDelPos
<= nIdx
&& nIdx
< nEnd
)
2550 ULONG nIdx
= p
->GetIndex();
2551 SwNodeIndex
* pPrev
= p
->pPrev
;
2552 if( nDelPos
<= nIdx
&& nIdx
< nEnd
)
2560 for (ULONG nCnt
= 0; nCnt
< nSz
; nCnt
++)
2562 SwTxtNode
* pTxtNd
= ((*this)[ nDelPos
+ nCnt
])->GetTxtNode();
2566 // --> OD 2008-03-13 #refactorlists#
2567 // pTxtNd->UnregisterNumber();
2568 pTxtNd
->RemoveFromList();
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.
2586 _TempBigPtrEntry aTempEntry
;
2587 BigPtrEntry
* pTempEntry
= &aTempEntry
;
2593 ULONG nPrevNdIdx
= pPrev
->GetIndex();
2594 BigPtrArray::Replace( nPrevNdIdx
+1, pTempEntry
);
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?
2614 // immer hinter die Root haengen
2615 rIdx
.pNext
= pRoot
->pNext
;
2616 pRoot
->pNext
= &rIdx
;
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
;
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
,
2650 const ElementPtr pIns
= pNode
;
2651 BigPtrArray::Insert( pIns
, nPos
);
2655 SwNode
* SwNodes::DocumentSectionStartNode(SwNode
* pNode
) const
2659 SwNodeIndex
aIdx(*pNode
);
2661 if (aIdx
<= (*this)[0]->EndOfSectionIndex())
2665 while ((*this)[0] != pNode
->StartOfSectionNode())
2666 pNode
= pNode
->StartOfSectionNode();
2673 SwNode
* SwNodes::DocumentSectionEndNode(SwNode
* pNode
) const
2675 return DocumentSectionStartNode(pNode
)->EndOfSectionNode();
2678 //SwNode * SwNodes::operator[](int n) const
2680 // return operator[]((ULONG) n);
2684 sal_Bool
SwNodes::IsDocNodes() const
2686 return this == &pMyDoc
->GetNodes();