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>
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)
62 #include "shellio.hxx"
66 // Funktion zum bestimmen des hoechsten Levels innerhalb des Bereiches
68 USHORT
HighestLevel( SwNodes
& rNodes
, const SwNodeRange
& rRange
);
70 //-----------------------------------------------------------------------
72 /*******************************************************************
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?" );
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 /*******************************************************************
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
124 *******************************************************************/
132 SwNodeIndex
aNdIdx( *this );
135 pNode
= &aNdIdx
.GetNode();
136 if( pNode
== pEndOfContent
)
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();
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
);
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();
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();
220 if( RES_CONDTXTFMTCOLL
== rTxtNd
.GetTxtColl()->Which() )
221 rTxtNd
.ChkCondColl();
224 else if( rNd
.IsCntntNode() )
225 ((SwCntntNode
&)rNd
).InvalidateNumRule();
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
;
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() )
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?
260 const SwNumRule
* pNumRule
= pTxtNd
->GetNumRule();
261 if( pNumRule
&& sNumRule
!= pNumRule
->GetName() )
263 sNumRule
= pNumRule
->GetName();
264 SwNumRule
* pDestRule
= pDestDoc
->FindNumRulePtr( sNumRule
);
266 pDestRule
->SetInvalidRule( TRUE
);
268 pDestDoc
->MakeNumRule( sNumRule
, pNumRule
);
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();
282 RemoveNode( rDelPos
.GetIndex(), 1, FALSE
); // Indizies verschieben !!
283 SwCntntNode
* pCNd
= pNd
->GetCntntNode();
284 rNds
.InsertNode( pNd
, aInsPos
);
288 SwTxtNode
* pTxtNd
= pCNd
->GetTxtNode();
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();
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
; )
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
) );
327 if( RES_DDEFLD
== pTyp
->Which() )
330 ((SwDDEFieldType
*)pTyp
)->DecRefCnt();
332 ((SwDDEFieldType
*)pTyp
)->IncRefCnt();
334 nDelMsg
= RES_FIELD_DELETED
;
338 nDelMsg
= RES_FOOTNOTE_DELETED
;
341 case RES_TXTATR_TOXMARK
:
342 nDelMsg
= RES_TOXMARK_DELETED
;
345 case RES_TXTATR_REFMARK
:
346 nDelMsg
= RES_REFMARK_DELETED
;
349 if( nDelMsg
&& bToUndo
)
351 SwPtrMsgPoolItem
aMsgHint( nDelMsg
,
352 (void*)&pAttr
->GetAttr() );
353 rNds
.GetDoc()->GetUnoCallBack()->
354 Modify( &aMsgHint
, &aMsgHint
);
359 if( RES_CONDTXTFMTCOLL
== pTxtNd
->GetTxtColl()->Which() )
360 pTxtNd
->ChkCondColl();
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 );
382 bNewFrms
= &GetDoc()->GetNodes() == (const SwNodes
*)&rNds
&&
383 GetDoc()->GetRootFrm();
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() )
402 ASSERT( !this, "ChgNode() - kein FrameNode gefunden" );
406 while( aIdx
!= rInsPos
)
408 SwCntntNode
* pCNd
= aIdx
.GetNode().GetCntntNode();
411 if( pFrmNd
->IsTableNode() )
412 ((SwTableNode
*)pFrmNd
)->MakeFrms( aIdx
);
413 else if( pFrmNd
->IsSectionNode() )
414 ((SwSectionNode
*)pFrmNd
)->MakeFrms( aIdx
);
416 ((SwCntntNode
*)pFrmNd
)->MakeFrms( *pCNd
);
425 /***********************************************************************
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
)
450 ( (pAktNode
= &aIndex
.GetNode())->GetStartNode() &&
451 !pAktNode
->StartOfSectionIndex() ))
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() ) )
463 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
465 while( ( (( pAktNode
= &aRg
.aEnd
.GetNode())->GetStartNode() &&
466 !pAktNode
->IsSectionNode() ) ||
467 ( pAktNode
->IsEndNode() &&
468 ND_STARTNODE
== pAktNode
->pStartOfSection
->GetNodeType()) ) &&
469 aRg
.aEnd
> aRg
.aStart
)
473 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
474 if( aRg
.aStart
>= aRg
.aEnd
)
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() ) )
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() )
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
);
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;
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() );
540 // loesche erstmal die Frames
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();
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
);
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();
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();
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
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();
639 if( rNodes
.IsDocNodes() )
646 if( GetDoc()->GetUndoNds() == &rNodes
)
648 SwFrmFmt
* pTblFmt
= pTblNd
->GetTable().GetFrmFmt();
649 SwPtrMsgPoolItem
aMsgHint( RES_REMOVE_UNO_OBJECT
,
651 pTblFmt
->Modify( &aMsgHint
, &aMsgHint
);
656 SwNodeIndex
aTmp( aIdx
);
657 pTblNd
->MakeFrms( &aTmp
);
662 else if( pSttNd
->GetIndex() < aRg
.aStart
.GetIndex() )
664 // SectionNode: es wird nicht die gesamte Section
665 // verschoben, also bewege nur die
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
,
674 /*?? welcher NodeTyp ??*/
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
688 new SwNode( aIdx
, ND_SECTIONDUMMY
);
692 // JP 18.5.2001: neue Section anlegen?? Bug 70454
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
)
711 SwSectionNode
* pSctNd
= pSttNd
->GetSectionNode();
712 if( bNewFrms
&& pSctNd
)
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
);
728 pSttNd
->pEndOfSection
= (SwEndNode
*)pAktNode
;
732 nLevel
++; // den Index auf StartNode auf den Stack
733 aSttNdStack
.C40_INSERT( SwStartNode
, pSttNd
, nLevel
);
735 // SectionNode muss noch ein paar Indizies ummelden
738 pSctNd
->NodesArrChgd();
750 ( (const SwNodes
*)&rNodes
== GetDoc()->GetUndoNds() ) )
752 // dann muss an der akt. InsPos ein SectionDummyNode
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
);
763 new SwNode( aIdx
, ND_SECTIONDUMMY
);
772 // Bug #78589# - empty section -> nothing to do
773 // and only if it's a top level section
774 if( !nInsPos
&& !nLevel
)
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
,
786 ((SwStartNode
*)pAktNode
)->GetStartNodeType() );
790 SwNodeIndex
aTmpEIdx( aOrigInsPos
.aEnd
);
791 new SwEndNode( aTmpEIdx
, *pTmpStt
);
795 // setze die StartOfSection richtig
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();
809 pAktNode
->pStartOfSection
= pTmpStt
;
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
);
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
834 // loesche nur noch den Pointer aus dem Nodes-Array.
835 // RemoveNode( aRg.aEnd.GetIndex(), 1, FALSE );
836 RemoveNode( aRg
.aEnd
.GetIndex(), 1, TRUE
);
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
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 );
867 if( bNewFrms
&& pAktNode
->GetCntntNode() )
868 ((SwCntntNode
*)pAktNode
)->DelFrms();
870 pAktNode
->pStartOfSection
= aSttNdStack
[ nLevel
];
876 case ND_SECTIONDUMMY
:
877 if( (const SwNodes
*)this == GetDoc()->GetUndoNds() )
879 if( &rNodes
== this ) // innerhalb vom UndoNodesArray
882 pAktNode
->pStartOfSection
= aSttNdStack
[ nLevel
];
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
);
899 SwNode
* pTmpNd
= &aIdx
.GetNode();
900 if( pTmpNd
->IsSectionNode() ||
901 pTmpNd
->StartOfSectionNode()->IsSectionNode() )
902 aIdx
--; // ueberspringen
906 ASSERT( FALSE
, "wie kommt diser Node ins Nodes-Array??" );
912 ASSERT( FALSE
, "was ist das fuer ein Node??" );
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() );
942 UpdtOutlineIdx( aRg
.aEnd
.GetNode() );
943 rNodes
.UpdtOutlineIdx( aOrigInsPos
.aStart
.GetNode() );
948 extern Writer
* GetDebugWriter(const String
&);
950 Writer
* pWriter
= GetDebugWriter(aEmptyStr
);
954 SvFileStream
aStrm( "c:\\$$move.db", STREAM_WRITE
);
955 SwWriter
aWriter( aStrm
, *pMyDoc
);
956 aWriter
.Write( &nError
, pWriter
);
965 /*******************************************************************
967 |* SwNodes::SectionDown
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 !! )
987 |* rRange.aStart: Einfuegeposition des StartNodes
988 |* rRange.aEnd: Einfuegeposition des EndNodes
990 |* rRange.aStart: steht hinter dem eingefuegten Startnode
991 |* rRange.aEnd: steht auf dem eingefuegen Endnode
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.
1000 |* die Debugging Tools geben rRange beim Eintritt und beim
1001 |* Verlassen der Funktion aus
1004 |* VER0100 vb 901214
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
))
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
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
1037 if( pRange
->aEnd
.GetNode().GetStartNode() )
1038 DelNodes( pRange
->aEnd
, 1 );
1042 // fuege einen neuen EndNode ein
1043 new SwEndNode( pRange
->aEnd
, *pRange
->aStart
.GetNode().GetStartNode() );
1047 SectionUpDown( aTmpIdx
, pRange
->aEnd
);
1050 /*******************************************************************
1052 |* SwNodes::SectionUp
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 !! )
1068 |* rRange.aStart: Anfang des hoeher zubewegenden Bereiches
1069 |* rRange.aEnd: der 1.Node hinter dem Bereich
1071 |* rRange.aStart: an der ersten Position innerhalb des
1072 |* hochbewegten Bereiches
1073 |* rRange.aEnd: an der letzten Position innerhalb des
1074 |* hochbewegten Bereiches
1077 |* die Debugging Tools geben rRange beim Eintritt und beim
1078 |* Verlassen der Funktion aus
1081 |* VER0100 vb 901214
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 ))
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;
1122 DelNodes( pRange
->aStart
, 1 );
1124 else if( aIdx
== pRange
->aStart
.GetIndex()-1 ) // vor StartNode
1125 DelNodes( aIdx
, 1 );
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 );
1137 pAktNode
= new SwStartNode( pRange
->aEnd
);
1138 /*?? welcher NodeTyp ??*/
1139 aTmpIdx
= *pRange
->aEnd
.GetNode().EndOfSectionNode();
1143 SectionUpDown( aIdx
, aTmpIdx
);
1147 /*************************************************************************
1149 |* SwNodes::SectionUpDown()
1152 |* Methode setzt die Indizies die bei SectionUp oder SectionDwon
1153 |* veraendert wurden wieder richtig, sodass die Ebenen wieder
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
)
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 )
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
1208 /*******************************************************************
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.
1221 |* SwIndex &rIndex bezeichnet die Position, an der
1223 |* rIndex ist nach Aufruf der Funktion unveraendert (Kopie?!)
1224 |* USHORT nNodes bezeichnet die Anzahl der zu loeschenden
1225 |* Nodes; ist auf 1 defaulted
1228 |* geben beim Eintritt in die Funktion Position und Anzahl
1229 |* der zu loeschenden Nodes aus.
1232 |* VER0100 vb 901214
1235 |* VER0100 vb 901214
1237 *******************************************************************/
1238 void SwNodes::Delete(const SwNodeIndex
&rIndex
, ULONG nNodes
)
1240 USHORT nLevel
= 0; // Level-Counter
1243 ULONG nCnt
= Count() - rIndex
.GetIndex() - 1;
1244 if( nCnt
> nNodes
) nCnt
= nNodes
;
1246 if( nCnt
== 0 ) // keine Anzahl -> 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
) )
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() ))
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
1269 BOOL bSaveInNodesDel
= bInNodesDel
;
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();
1287 SwNode
*pNd
, *pChkNd
= pAktNode
->pStartOfSection
;
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();
1312 } while( pNd
!= pChkNd
);
1316 RemoveNode( aRg
.aEnd
.GetIndex()+1, nCnt
, TRUE
); // loesche
1318 aRg
.aEnd
--; // vor den EndNode
1322 else if( pAktNode
->GetStartNode() ) // StartNode gefunden
1324 if( nLevel
== 0 ) // es wird eine Stufe runter gestuft
1328 // loesche jetzt das Array
1330 RemoveNode( aRg
.aEnd
.GetIndex(), nCnt
, TRUE
);
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
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();
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();
1355 else // normaler Node, also ins TmpArray einfuegen
1357 SwTxtNode
* pTxtNd
= pAktNode
->GetTxtNode();
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();
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
1389 bInNodesDel
= bSaveInNodesDel
;
1393 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
1394 if( bUpdateOutline
|| bInDelUpdOutl
)
1396 UpdtOutlineIdx( aRg
.aEnd
.GetNode() );
1397 bInDelUpdOutl
= FALSE
;
1403 if( bUpdateOutline
)
1404 bInDelUpdOutl
= TRUE
;
1408 /*******************************************************************
1410 |* SwNodes::GetSectionLevel
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)
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.
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.
1436 |* VER0100 vb 901214
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
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
1464 return; // FEHLER: Steht schon hinter der Sektion
1465 aTmp
= aTmp
.GetNode().EndOfSectionIndex()+1;
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 )
1484 SwNodeIndex
aTmp(*pIdx
, +1);
1486 while( aTmp
< Count()-1 && 0 == ( pNd
= &aTmp
.GetNode())->IsCntntNode() )
1489 if( aTmp
== Count()-1 )
1493 return (SwCntntNode
*)pNd
;
1496 SwCntntNode
* SwNodes::GoPrevious(SwNodeIndex
*pIdx
) const
1498 if( !pIdx
->GetIndex() )
1501 SwNodeIndex
aTmp( *pIdx
, -1 );
1503 while( aTmp
.GetIndex() && 0 == ( pNd
= &aTmp
.GetNode())->IsCntntNode() )
1506 if( !aTmp
.GetIndex() )
1510 return (SwCntntNode
*)pNd
;
1513 SwNode
* SwNodes::GoNextWithFrm(SwNodeIndex
*pIdx
) const
1515 if( pIdx
->GetIndex() >= Count() - 1 )
1518 SwNodeIndex
aTmp(*pIdx
, +1);
1520 while( aTmp
< Count()-1 )
1522 pNd
= &aTmp
.GetNode();
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() )
1533 if ( pMod
&& pMod
->GetDepends() )
1535 SwClientIter
aIter( *pMod
);
1536 if( aIter
.First( TYPE(SwFrm
) ) )
1541 if( aTmp
== Count()-1 )
1548 SwNode
* SwNodes::GoPreviousWithFrm(SwNodeIndex
*pIdx
) const
1550 if( !pIdx
->GetIndex() )
1553 SwNodeIndex
aTmp( *pIdx
, -1 );
1555 while( aTmp
.GetIndex() )
1557 pNd
= &aTmp
.GetNode();
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() )
1568 if ( pMod
&& pMod
->GetDepends() )
1570 SwClientIter
aIter( *pMod
);
1571 if( aIter
.First( TYPE(SwFrm
) ) )
1577 if( !aTmp
.GetIndex() )
1586 /*************************************************************************
1588 |* BOOL SwNodes::CheckNodesRange()
1591 |* Teste ob der uebergene SRange nicht ueber die Grenzen der
1592 |* einzelnen Bereiche (PosIts, Autotext, Content, Icons und Inserts )
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()
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
)
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
);
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.
1688 if( pOutlineNds
->Seek_Entry( pNd
, &nIdxPos
))
1690 pOutlineNds
->Remove( nIdxPos
);
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
1704 UpdtOutlineIdx( rStart
.GetNode() );
1709 /*************************************************************************
1711 |* USHORT HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
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 *************************************************************************/
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() )
1737 else if( rpNode
->GetEndNode() )
1739 if( pHL
->nTop
> pHL
->nLevel
)
1740 pHL
->nTop
= pHL
->nLevel
;
1745 USHORT
HighestLevel( SwNodes
& rNodes
, const SwNodeRange
& rRange
)
1747 HighLevel
aPara( rNodes
.GetSectionLevel( rRange
.aStart
));
1748 rNodes
.ForEach( rRange
.aStart
, rRange
.aEnd
, _HighestLevel
, &aPara
);
1753 /*************************************************************************
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
,
1768 SwPosition
*pStt
= (SwPosition
*)rPam
.Start(), *pEnd
= (SwPosition
*)rPam
.End();
1770 if( !rPam
.HasMark() || *pStt
>= *pEnd
)
1773 if( this == &rNodes
&& *pStt
<= rPos
&& rPos
< *pEnd
)
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();
1786 // ist der 1.Node ein TextNode, dann muss im NodesArray auch
1787 // ein TextNode vorhanden sein, in den der Inhalt geschoben wird
1790 pDestNd
= rNodes
.MakeTxtNode( rPos
.nNode
, pSrcNd
->GetTxtColl() );
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() )
1811 ULONG nSttNdIdx
= pStt
->nNode
.GetIndex() + 1,
1812 nEndNdIdx
= pEnd
->nNode
.GetIndex();
1813 for( ; nSttNdIdx
< nEndNdIdx
; ++nSttNdIdx
)
1814 if( (*this)[ nSttNdIdx
]->IsCntntNode() )
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
);
1837 pDestNd
->SplitCntntNode( rPos
);
1839 if( rPos
.nNode
== aEndIdx
)
1841 bSplitDestNd
= TRUE
;
1843 pDestNd
= rNodes
[ rPos
.nNode
.GetIndex() - 1 ]->GetTxtNode();
1845 pSrcNd
->Cut( pDestNd
, SwIndex( pDestNd
, pDestNd
->Len()),
1846 pStt
->nContent
, nLen
);
1849 pSrcNd
->Cut( pDestNd
, rPos
.nContent
, pStt
->nContent
, nLen
);
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
;
1868 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0, rNodes
.IsDocNodes() ? SWFMTFLD_INSERTED
: SWFMTFLD_REMOVED
) );
1876 if( rPos
.nContent
.GetIndex() )
1878 //!NOSPLIT if( !bSplitNd && rPos.nContent.GetIndex() == pDestNd->Len() )
1879 if( rPos
.nContent
.GetIndex() == pDestNd
->Len() )
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
);
1897 pDestNd
->SplitCntntNode( rPos
);
1899 pDestNd
= rPos
.nNode
.GetNode().GetTxtNode();
1905 // am Ende steht noch ein leerer Text Node herum.
1906 bSplitDestNd
= TRUE
;
1909 pSrcNd
= (*this)[ aEndIdx
]->GetTxtNode();
1912 // if( pEnd->nContent.GetIndex() ? TRUE : aEndIdx != pStt->nNode )
1914 // am Bereichsende entsteht ein neuer TextNode
1917 if( rPos
.nNode
< rNodes
.GetEndOfContent().GetIndex() )
1920 pDestNd
= rNodes
.MakeTxtNode( rPos
.nNode
, pSrcNd
->GetTxtColl() );
1922 rPos
.nContent
.Assign( pDestNd
, 0 );
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());
1937 SwDoc
* pInsDoc
= pDestNd
->GetDoc();
1938 BOOL bIsUndo
= pInsDoc
->DoesUndo();
1939 pInsDoc
->DoUndo( FALSE
);
1940 pSrcNd
->CopyCollFmt( *pDestNd
);
1941 pInsDoc
->DoUndo( bIsUndo
);
1947 if( bSttTxtNd
&& aEndIdx
.GetNode().IsCntntNode() )
1953 rPos
.nContent
.Assign( rPos
.nNode
.GetNode().GetCntntNode(), 0 );
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 !
1986 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0, rNodes
.IsDocNodes() ? SWFMTFLD_INSERTED
: SWFMTFLD_REMOVED
) );
1991 /*************************************************************************
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();
2016 ( (pAktNode
= &rIndex
.GetNode())->GetStartNode() &&
2017 !pAktNode
->StartOfSectionIndex() ))
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() ) )
2028 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
2030 while( (( pAktNode
= (*this)[ aRg
.aEnd
])->GetStartNode() &&
2031 !pAktNode
->IsSectionNode() ) ||
2032 ( pAktNode
->IsEndNode() &&
2033 ND_STARTNODE
== pAktNode
->pStartOfSection
->GetNodeType()) )
2037 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
2038 if( aRg
.aStart
>= aRg
.aEnd
)
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() )
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() )
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() )
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();
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();
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
)
2112 pTblNd
->MakeFrms( &nStt
);
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
);
2138 case ND_STARTNODE
: // StartNode gefunden
2140 SwStartNode
* pTmp
= new SwStartNode( aInsPos
, ND_STARTNODE
,
2141 ((SwStartNode
*)pAktNode
)->GetStartNodeType() );
2142 new SwEndNode( aInsPos
, *pTmp
);
2149 if( nLevel
) // vollstaendige Section
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() );
2167 SwCntntNode
* pNew
= ((SwCntntNode
*)pAktNode
)->MakeCopy(
2169 if( !bNewFrms
) // dflt. werden die Frames immer angelegt
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
2186 ASSERT( FALSE
, "wie kommt diser Node ins Nodes-Array??" );
2191 ASSERT( FALSE
, "weder Start-/End-/Content-Node, unbekannter Typ" );
2199 extern Writer
* GetDebugWriter(const String
&);
2201 Writer
* pWriter
= GetDebugWriter(aEmptyStr
);
2205 SvFileStream
aStrm( "c:\\$$copy.db", STREAM_WRITE
);
2206 SwWriter
aWriter( aStrm
, *pMyDoc
);
2207 aWriter
.Write( &nError
, pWriter
);
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
);
2225 SwStartNode
* SwNodes::MakeEmptySection( const SwNodeIndex
& rIdx
,
2226 SwStartNodeType eSttNdTyp
)
2228 SwStartNode
* pSttNd
= new SwStartNode( rIdx
, ND_STARTNODE
, eSttNdTyp
);
2229 new SwEndNode( rIdx
, *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
);
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
2251 SwNodeIndex
aTmp( *pIdx
);
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();
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();
2290 return (SwCntntNode
*)pNd
;
2299 SwCntntNode
* SwNodes::GoPrevSection( SwNodeIndex
* pIdx
,
2300 int bSkipHidden
, int bSkipProtect
) const
2303 SwNodeIndex
aTmp( *pIdx
);
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();
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() )) )
2346 return (SwCntntNode
*)pNd
;
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
2361 SwNode
* SwNodes::FindPrvNxtFrmNode( SwNodeIndex
& rFrmIdx
,
2362 const SwNode
* pEnd
) const
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
);
2387 pNd
= &aIdx
.GetNode();
2392 if( ( pFrmNd
= pNd
)->IsCntntNode() )
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())
2412 aIdx
= pEnd
->GetIndex() + 1;
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() ) &&
2437 pTblNd
!= pSttNd
->StartOfSectionNode()->FindTableNode() )
2445 else if( pNd
->IsEndNode() && pNd
->StartOfSectionNode()->IsTableNode() )
2447 pFrmNd
= pNd
->StartOfSectionNode();
2453 aIdx
= pEnd
->GetIndex() + 1;
2455 aIdx
= rFrmIdx
.GetIndex() + 1;
2457 if( (pFrmNd
= &aIdx
.GetNode())->IsTableNode() )
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;
2473 if( aIdx
.GetNode().IsTableNode() )
2476 pFrmNd
= &aIdx
.GetNode();
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
];
2506 SwNodeIndex
*p
= pRoot
;
2509 ULONG nIdx
= p
->GetIndex();
2510 SwNodeIndex
* pNext
= p
->pNext
;
2511 if( nDelPos
<= nIdx
&& nIdx
< nEnd
)
2520 ULONG nIdx
= p
->GetIndex();
2521 SwNodeIndex
* pPrev
= p
->pPrev
;
2522 if( nDelPos
<= nIdx
&& nIdx
< nEnd
)
2530 for (ULONG nCnt
= 0; nCnt
< nSz
; nCnt
++)
2532 SwTxtNode
* pTxtNd
= ((*this)[ nDelPos
+ nCnt
])->GetTxtNode();
2536 // --> OD 2008-03-13 #refactorlists#
2537 // pTxtNd->UnregisterNumber();
2538 pTxtNd
->RemoveFromList();
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.
2556 _TempBigPtrEntry aTempEntry
;
2557 BigPtrEntry
* pTempEntry
= &aTempEntry
;
2563 ULONG nPrevNdIdx
= pPrev
->GetIndex();
2564 BigPtrArray::Replace( nPrevNdIdx
+1, pTempEntry
);
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?
2584 // immer hinter die Root haengen
2585 rIdx
.pNext
= pRoot
->pNext
;
2586 pRoot
->pNext
= &rIdx
;
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
;
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
,
2620 const ElementPtr pIns
= pNode
;
2621 BigPtrArray::Insert( pIns
, nPos
);
2625 SwNode
* SwNodes::DocumentSectionStartNode(SwNode
* pNode
) const
2629 SwNodeIndex
aIdx(*pNode
);
2631 if (aIdx
<= (*this)[0]->EndOfSectionIndex())
2635 while ((*this)[0] != pNode
->StartOfSectionNode())
2636 pNode
= pNode
->StartOfSectionNode();
2643 SwNode
* SwNodes::DocumentSectionEndNode(SwNode
* pNode
) const
2645 return DocumentSectionStartNode(pNode
)->EndOfSectionNode();
2648 //SwNode * SwNodes::operator[](int n) const
2650 // return operator[]((ULONG) n);
2654 sal_Bool
SwNodes::IsDocNodes() const
2656 return this == &pMyDoc
->GetNodes();