1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <stdlib.h>
28
29 #include <node.hxx>
30 #include <doc.hxx>
31 #include <IDocumentUndoRedo.hxx>
32 #include <pam.hxx>
33 #include <txtfld.hxx>
34 #include <fmtfld.hxx>
35 #include <hints.hxx>
36 #include <numrule.hxx>
37 #include <ndtxt.hxx>
38 #include <ndnotxt.hxx>
39 #include <swtable.hxx> // fuer erzuegen / loeschen der Table-Frames
40 #include <tblsel.hxx>
41 #include <section.hxx>
42 #include <ddefld.hxx>
43 #include <swddetbl.hxx>
44 #include <frame.hxx>
45 #include <txtatr.hxx>
46 #include <tox.hxx> // InvalidateTOXMark
47
48 #include <docsh.hxx>
49 #include <svl/smplhint.hxx>
50
51 extern sal_Bool CheckNodesRange( const SwNodeIndex& rStt,
52 const SwNodeIndex& rEnd, sal_Bool bChkSection );
53
54 SV_DECL_PTRARR(SwSttNdPtrs,SwStartNode*,2,2)
55
56
57 //#define JP_DEBUG
58 #ifdef JP_DEBUG
59 #include "shellio.hxx"
60 #endif
61
62
63 // Funktion zum bestimmen des hoechsten Levels innerhalb des Bereiches
64
65 sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange );
66
67 //-----------------------------------------------------------------------
68
69 /*******************************************************************
70 |* SwNodes::SwNodes
71 |*
72 |* Beschreibung
73 |* Konstruktor; legt die vier Grundsektions (PostIts,
74 |* Inserts, Icons, Inhalt) an
75 *******************************************************************/
SwNodes(SwDoc * pDocument)76 SwNodes::SwNodes( SwDoc* pDocument )
77 : pRoot( 0 ), pMyDoc( pDocument )
78 {
79 bInNodesDel = bInDelUpdOutl = bInDelUpdNum = sal_False;
80
81 ASSERT( pMyDoc, "in welchem Doc stehe ich denn?" );
82
83 sal_uLong nPos = 0;
84 SwStartNode* pSttNd = new SwStartNode( *this, nPos++ );
85 pEndOfPostIts = new SwEndNode( *this, nPos++, *pSttNd );
86
87 SwStartNode* pTmp = new SwStartNode( *this, nPos++ );
88 pEndOfInserts = new SwEndNode( *this, nPos++, *pTmp );
89
90 pTmp = new SwStartNode( *this, nPos++ );
91 pTmp->pStartOfSection = pSttNd;
92 pEndOfAutotext = new SwEndNode( *this, nPos++, *pTmp );
93
94 pTmp = new SwStartNode( *this, nPos++ );
95 pTmp->pStartOfSection = pSttNd;
96 pEndOfRedlines = new SwEndNode( *this, nPos++, *pTmp );
97
98 pTmp = new SwStartNode( *this, nPos++ );
99 pTmp->pStartOfSection = pSttNd;
100 pEndOfContent = new SwEndNode( *this, nPos++, *pTmp );
101
102 pOutlineNds = new SwOutlineNodes;
103 }
104
105 /*******************************************************************
106 |*
107 |* SwNodes::~SwNodes
108 |*
109 |* Beschreibung
110 |* dtor, loescht alle Nodes, deren Pointer in diesem dynamischen
111 |* Array sind. Ist kein Problem, da Nodes ausserhalb dieses
112 |* Arrays nicht erzeugt werden koennen und somit auch nicht
113 |* in mehreren drin sein koennen
114 |*
115 |* Ersterstellung
116 |* VER0100 vb 901214
117 |*
118 |* Stand
119 |* VER0100 vb 901214
120 |*
121 *******************************************************************/
122
~SwNodes()123 SwNodes::~SwNodes()
124 {
125 delete pOutlineNds;
126
127 {
128 SwNode *pNode;
129 SwNodeIndex aNdIdx( *this );
130 while( sal_True )
131 {
132 pNode = &aNdIdx.GetNode();
133 if( pNode == pEndOfContent )
134 break;
135
136 aNdIdx++;
137 delete pNode;
138 }
139 }
140
141 // jetzt muessen alle SwNodeIndizies abgemeldet sein!!!
142 delete pEndOfContent;
143 }
144
ChgNode(SwNodeIndex & rDelPos,sal_uLong nSz,SwNodeIndex & rInsPos,sal_Bool bNewFrms)145 void SwNodes::ChgNode( SwNodeIndex& rDelPos, sal_uLong nSz,
146 SwNodeIndex& rInsPos, sal_Bool bNewFrms )
147 {
148 // im UndoBereich brauchen wir keine Frames
149 SwNodes& rNds = rInsPos.GetNodes();
150 const SwNode* pPrevInsNd = rNds[ rInsPos.GetIndex() -1 ];
151
152 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
153 // Idle-Handler des Docs
154 if( GetDoc()->SetFieldsDirty( sal_True, &rDelPos.GetNode(), nSz ) &&
155 rNds.GetDoc() != GetDoc() )
156 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
157
158 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
159 sal_uLong nNd = rInsPos.GetIndex();
160 sal_Bool bInsOutlineIdx = !(
161 rNds.GetEndOfRedlines().StartOfSectionNode()->GetIndex() < nNd &&
162 nNd < rNds.GetEndOfRedlines().GetIndex() );
163
164 if( &rNds == this ) // im gleichen Nodes-Array -> moven !!
165 {
166 // wird von vorne nach hinten gemovt, so wird nach vorne immer
167 // nachgeschoben, d.H. die Loeschposition ist immer gleich
168 sal_uInt16 nDiff = rDelPos.GetIndex() < rInsPos.GetIndex() ? 0 : 1;
169
170 for( sal_uLong n = rDelPos.GetIndex(); nSz; n += nDiff, --nSz )
171 {
172 SwNodeIndex aDelIdx( *this, n );
173 SwNode& rNd = aDelIdx.GetNode();
174
175 // --> OD 2005-11-16 #i57920#
176 // correction of refactoring done by cws swnumtree:
177 // - <SwTxtNode::SetLevel( NO_NUMBERING ) is deprecated and
178 // set <IsCounted> state of the text node to <false>, which
179 // isn't correct here.
180 if ( rNd.IsTxtNode() )
181 {
182 SwTxtNode* pTxtNode = rNd.GetTxtNode();
183 pTxtNode->RemoveFromList();
184
185 //if ( pTxtNode->GetTxtColl()->GetOutlineLevel() != NO_NUMBERING )//#outline level,zhaojianwei
186 if ( pTxtNode->GetAttrOutlineLevel() != 0 )//<-end,zhaojianwei
187 {
188 const SwNodePtr pSrch = (SwNodePtr)&rNd;
189 pOutlineNds->Remove( pSrch );
190 }
191 }
192 // <--
193
194 BigPtrArray::Move( aDelIdx.GetIndex(), rInsPos.GetIndex() );
195
196 if( rNd.IsTxtNode() )
197 {
198 SwTxtNode& rTxtNd = (SwTxtNode&)rNd;
199 rTxtNd.AddToList();
200
201 if( bInsOutlineIdx &&
202 //NO_NUMBERING != rTxtNd.GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
203 0 != rTxtNd.GetAttrOutlineLevel() )//<-end,zhaojianwei
204 {
205 const SwNodePtr pSrch = (SwNodePtr)&rNd;
206 pOutlineNds->Insert( pSrch );
207 }
208 rTxtNd.InvalidateNumRule();
209
210 //FEATURE::CONDCOLL
211 if( RES_CONDTXTFMTCOLL == rTxtNd.GetTxtColl()->Which() )
212 rTxtNd.ChkCondColl();
213 //FEATURE::CONDCOLL
214 }
215 else if( rNd.IsCntntNode() )
216 ((SwCntntNode&)rNd).InvalidateNumRule();
217 }
218 }
219 else
220 {
221 bool bSavePersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds));
222 bool bRestPersData(GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this));
223 SwDoc* pDestDoc = rNds.GetDoc() != GetDoc() ? rNds.GetDoc() : 0;
224 OSL_ENSURE(!pDestDoc, "SwNodes::ChgNode(): "
225 "the code to handle text fields here looks broken\n"
226 "if the target is in a different document.");
227 if( !bRestPersData && !bSavePersData && pDestDoc )
228 bSavePersData = bRestPersData = sal_True;
229
230 String sNumRule;
231 SwNodeIndex aInsPos( rInsPos );
232 for( sal_uLong n = 0; n < nSz; n++ )
233 {
234 SwNode* pNd = &rDelPos.GetNode();
235
236 // NoTextNode muessen ihre Persitenten Daten mitnehmen
237 if( pNd->IsNoTxtNode() )
238 {
239 if( bSavePersData )
240 ((SwNoTxtNode*)pNd)->SavePersistentData();
241 }
242 else if( pNd->IsTxtNode() )
243 {
244 SwTxtNode* pTxtNd = (SwTxtNode*)pNd;
245
246 // loesche die Gliederungs-Indizies aus dem alten Nodes-Array
247 //if( NO_NUMBERING != pTxtNd->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
248 if( 0 != pTxtNd->GetAttrOutlineLevel() )//<-end,zhaojianwei
249 pOutlineNds->Remove( pNd );
250
251 // muss die Rule kopiere werden?
252 if( pDestDoc )
253 {
254 const SwNumRule* pNumRule = pTxtNd->GetNumRule();
255 if( pNumRule && sNumRule != pNumRule->GetName() )
256 {
257 sNumRule = pNumRule->GetName();
258 SwNumRule* pDestRule = pDestDoc->FindNumRulePtr( sNumRule );
259 if( pDestRule )
260 pDestRule->SetInvalidRule( sal_True );
261 else
262 pDestDoc->MakeNumRule( sNumRule, pNumRule );
263 }
264 }
265 else
266 // wenns ins UndoNodes-Array gemoved wird, sollten die
267 // Numerierungen auch aktualisiert werden.
268 pTxtNd->InvalidateNumRule();
269
270 pTxtNd->RemoveFromList();
271 }
272
273 RemoveNode( rDelPos.GetIndex(), 1, sal_False ); // Indizies verschieben !!
274 SwCntntNode * pCNd = pNd->GetCntntNode();
275 rNds.InsertNode( pNd, aInsPos );
276
277 if( pCNd )
278 {
279 SwTxtNode* pTxtNd = pCNd->GetTxtNode();
280 if( pTxtNd )
281 {
282 SwpHints * const pHts = pTxtNd->GetpSwpHints();
283 // setze die OultineNodes im neuen Nodes-Array
284 //if( bInsOutlineIdx && NO_NUMBERING != //#outline level,removed by zhaojianwei
285 // pTxtNd->GetTxtColl()->GetOutlineLevel() )
286 if( bInsOutlineIdx &&
287 0 != pTxtNd->GetAttrOutlineLevel() ) //#outline level,added by zhaojianwei
288 {
289 rNds.pOutlineNds->Insert( pTxtNd );
290 }
291
292 pTxtNd->AddToList();
293
294 // Sonderbehandlung fuer die Felder!
295 if( pHts && pHts->Count() )
296 {
297 // this looks fishy if pDestDoc != 0
298 bool const bToUndo = !pDestDoc &&
299 GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNds);
300 for( sal_uInt16 i = pHts->Count(); i; )
301 {
302 sal_uInt16 nDelMsg = 0;
303 SwTxtAttr * const pAttr = pHts->GetTextHint( --i );
304 switch ( pAttr->Which() )
305 {
306 case RES_TXTATR_FIELD:
307 case RES_TXTATR_ANNOTATION:
308 case RES_TXTATR_INPUTFIELD:
309 {
310 SwTxtFld* pTxtFld = static_cast<SwTxtFld*>(pAttr);
311 rNds.GetDoc()->InsDelFldInFldLst( !bToUndo, *pTxtFld );
312
313 const SwFieldType* pTyp = pTxtFld->GetFmtFld().GetField()->GetTyp();
314 if ( RES_POSTITFLD == pTyp->Which() )
315 {
316 rNds.GetDoc()->GetDocShell()->Broadcast(
317 SwFmtFldHint(
318 &pTxtFld->GetFmtFld(),
319 ( pTxtFld->GetFmtFld().IsFldInDoc()
320 ? SWFMTFLD_INSERTED
321 : SWFMTFLD_REMOVED ) ) );
322 }
323 else
324 if( RES_DDEFLD == pTyp->Which() )
325 {
326 if( bToUndo )
327 ((SwDDEFieldType*)pTyp)->DecRefCnt();
328 else
329 ((SwDDEFieldType*)pTyp)->IncRefCnt();
330 }
331 nDelMsg = RES_FIELD_DELETED;
332 }
333 break;
334
335 case RES_TXTATR_FTN:
336 nDelMsg = RES_FOOTNOTE_DELETED;
337 break;
338
339 case RES_TXTATR_TOXMARK:
340 static_cast<SwTOXMark&>(pAttr->GetAttr())
341 .InvalidateTOXMark();
342 break;
343
344 case RES_TXTATR_REFMARK:
345 nDelMsg = RES_REFMARK_DELETED;
346 break;
347
348 case RES_TXTATR_META:
349 case RES_TXTATR_METAFIELD:
350 {
351 SwTxtMeta *const pTxtMeta(
352 static_cast<SwTxtMeta*>(pAttr));
353 // force removal of UNO object
354 pTxtMeta->ChgTxtNode(0);
355 pTxtMeta->ChgTxtNode(pTxtNd);
356 }
357 break;
358
359 default:
360 break;
361 }
362
363 if( nDelMsg && bToUndo )
364 {
365 SwPtrMsgPoolItem aMsgHint( nDelMsg,
366 (void*)&pAttr->GetAttr() );
367 rNds.GetDoc()->GetUnoCallBack()->
368 ModifyNotification( &aMsgHint, &aMsgHint );
369 }
370 }
371 }
372 //FEATURE::CONDCOLL
373 if( RES_CONDTXTFMTCOLL == pTxtNd->GetTxtColl()->Which() )
374 pTxtNd->ChkCondColl();
375 //FEATURE::CONDCOLL
376 }
377 else
378 {
379 // in unterschiedliche Docs gemoved ?
380 // dann die Daten wieder persistent machen
381 if( pCNd->IsNoTxtNode() && bRestPersData )
382 ((SwNoTxtNode*)pCNd)->RestorePersistentData();
383 }
384 }
385 }
386 }
387
388 //JP 03.02.99: alle Felder als invalide erklaeren, aktu. erfolgt im
389 // Idle-Handler des Docs
390 GetDoc()->SetFieldsDirty( true, NULL, 0 );
391 if( rNds.GetDoc() != GetDoc() )
392 rNds.GetDoc()->SetFieldsDirty( true, NULL, 0 );
393
394
395 if( bNewFrms )
396 bNewFrms = &GetDoc()->GetNodes() == (const SwNodes*)&rNds &&
397 GetDoc()->GetCurrentViewShell(); //swmod 071108//swmod 071225
398 if( bNewFrms )
399 {
400 // Frames besorgen:
401 SwNodeIndex aIdx( *pPrevInsNd, 1 );
402 SwNodeIndex aFrmNdIdx( aIdx );
403 SwNode* pFrmNd = rNds.FindPrvNxtFrmNode( aFrmNdIdx,
404 rNds[ rInsPos.GetIndex() - 1 ] );
405
406 if( !pFrmNd && aFrmNdIdx > rNds.GetEndOfExtras().GetIndex() )
407 {
408 ASSERT( !this, "ob das so richtig ist ??" );
409 aFrmNdIdx = rNds.GetEndOfContent();
410 pFrmNd = rNds.GoPrevSection( &aFrmNdIdx, sal_True, sal_False );
411 if( pFrmNd && !((SwCntntNode*)pFrmNd)->GetDepends() )
412 pFrmNd = 0;
413
414 #ifdef DBG_UTIL
415 if( !pFrmNd )
416 ASSERT( !this, "ChgNode() - kein FrameNode gefunden" );
417 #endif
418 }
419 if( pFrmNd )
420 while( aIdx != rInsPos )
421 {
422 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
423 if( pCNd )
424 {
425 if( pFrmNd->IsTableNode() )
426 ((SwTableNode*)pFrmNd)->MakeFrms( aIdx );
427 else if( pFrmNd->IsSectionNode() )
428 ((SwSectionNode*)pFrmNd)->MakeFrms( aIdx );
429 else
430 ((SwCntntNode*)pFrmNd)->MakeFrms( *pCNd );
431 pFrmNd = pCNd;
432 }
433 aIdx++;
434 }
435 }
436 }
437
438
439 /***********************************************************************
440 |*
441 |* SwNodes::Move
442 |*
443 |* Beschreibung
444 |* Move loescht die Node-Pointer ab und einschliesslich der Startposition
445 |* bis zu und ausschliesslich der Endposition und fuegt sie an
446 |* der vor der Zielposition ein.
447 |* Wenn das Ziel vor dem ersten oder dem letzten zu bewegenden Element oder
448 |* dazwischen liegt, geschieht nichts.
449 |* Wenn der zu bewegende Bereich leer ist oder das Ende vor
450 |* dem Anfang liegt, geschieht nichts.
451 |*
452 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
453 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
454 |*
455 |*
456 |*
457 ***********************************************************************/
458
_MoveNodes(const SwNodeRange & aRange,SwNodes & rNodes,const SwNodeIndex & aIndex,sal_Bool bNewFrms)459 sal_Bool SwNodes::_MoveNodes( const SwNodeRange& aRange, SwNodes & rNodes,
460 const SwNodeIndex& aIndex, sal_Bool bNewFrms )
461 {
462 SwNode * pAktNode;
463 if( aIndex == 0 ||
464 ( (pAktNode = &aIndex.GetNode())->GetStartNode() &&
465 !pAktNode->StartOfSectionIndex() ))
466 return sal_False;
467
468 SwNodeRange aRg( aRange );
469
470 // "einfache" StartNodes oder EndNodes ueberspringen
471 while( ND_STARTNODE == (pAktNode = &aRg.aStart.GetNode())->GetNodeType()
472 || ( pAktNode->IsEndNode() &&
473 !pAktNode->pStartOfSection->IsSectionNode() ) )
474 aRg.aStart++;
475 aRg.aStart--;
476
477 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
478 aRg.aEnd--;
479 while( ( (( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
480 !pAktNode->IsSectionNode() ) ||
481 ( pAktNode->IsEndNode() &&
482 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) ) &&
483 aRg.aEnd > aRg.aStart )
484 aRg.aEnd--;
485
486
487 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
488 if( aRg.aStart >= aRg.aEnd )
489 return sal_False;
490
491 if( this == &rNodes )
492 {
493 if( ( aIndex.GetIndex()-1 >= aRg.aStart.GetIndex() &&
494 aIndex.GetIndex()-1 < aRg.aEnd.GetIndex()) ||
495 ( aIndex.GetIndex()-1 == aRg.aEnd.GetIndex() ) )
496 return sal_False;
497 }
498
499 sal_uInt16 nLevel = 0; // Level-Counter
500 sal_uLong nInsPos = 0; // Cnt fuer das TmpArray
501
502 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
503 SwSttNdPtrs aSttNdStack( 1, 5 );
504
505 // setze den Start-Index
506 SwNodeIndex aIdx( aIndex );
507 /*
508 --- JP 17.11.94: sollte ueberholt sein, wird im ChgNode schon erledigt!
509 sal_Bool bCorrNum = pSect && pSect->aStart.GetIndex() == aIdx.GetIndex();
510 */
511
512 SwStartNode* pStartNode = aIdx.GetNode().pStartOfSection;
513 aSttNdStack.C40_INSERT( SwStartNode, pStartNode, 0 );
514 // aSttNdStack.Insert( rNodes[ aIdx ]->pStartOfSection, 0 );
515 SwNodeRange aOrigInsPos( aIdx, -1, aIdx ); // Originale Insert Pos
516
517 //JP 16.01.98: SectionNodes: DelFrms/MakeFrms beim obersten SectionNode!
518 sal_uInt16 nSectNdCnt = 0;
519 sal_Bool bSaveNewFrms = bNewFrms;
520
521 // Check that the range of nodes to move is valid.
522 // This is a very specific test that only checks that table nodes
523 // are completely covered by the range. Issue 121479 has a
524 // document for which this test fails.
525 SwNodeIndex aNodeIndex (aRg.aEnd);
526 while (aNodeIndex > aRg.aStart)
527 {
528 SwNode& rNode (aNodeIndex.GetNode());
529 if (rNode.GetNodeType() != ND_ENDNODE)
530 break;
531 SwStartNode* pStartNode = rNode.pStartOfSection;
532 if (pStartNode==NULL)
533 break;
534 if ( ! pStartNode->IsTableNode())
535 break;
536 aNodeIndex = *pStartNode;
537 if (aNodeIndex < aRg.aStart.GetIndex())
538 {
539 return sal_False;
540 }
541 --aNodeIndex;
542 }
543
544
545 // bis alles verschoben ist
546 while( aRg.aStart < aRg.aEnd )
547 switch( (pAktNode = &aRg.aEnd.GetNode())->GetNodeType() )
548 {
549 case ND_ENDNODE:
550 {
551 if( nInsPos ) // verschieb schon mal alle bis hier her
552 {
553 // loeschen und kopieren. ACHTUNG: die Indizies ab
554 // "aRg.aEnd+1" werden mit verschoben !!
555 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
556 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
557 aIdx -= nInsPos;
558 nInsPos = 0;
559 }
560
561 SwStartNode* pSttNd = pAktNode->pStartOfSection;
562 if( pSttNd->IsTableNode() )
563 {
564 SwTableNode* pTblNd = (SwTableNode*)pSttNd;
565
566 // dann bewege die gesamte Tabelle/den Bereich !!
567 nInsPos = (aRg.aEnd.GetIndex() -
568 pSttNd->GetIndex() )+1;
569 aRg.aEnd -= nInsPos;
570
571 //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
572 sal_uLong nNd = aIdx.GetIndex();
573 sal_Bool bInsOutlineIdx = !( rNodes.GetEndOfRedlines().
574 StartOfSectionNode()->GetIndex() < nNd &&
575 nNd < rNodes.GetEndOfRedlines().GetIndex() );
576
577 if( bNewFrms )
578 // loesche erstmal die Frames
579 pTblNd->DelFrms();
580 if( &rNodes == this ) // in sich selbst moven ??
581 {
582 // dann bewege alle Start/End/ContentNodes. Loesche
583 // bei den ContentNodes auch die Frames !!
584 pTblNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
585 for( sal_uLong n = 0; n < nInsPos; ++n )
586 {
587 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
588 SwCntntNode* pCNd = 0;
589 SwNode* pTmpNd = &aMvIdx.GetNode();
590 if( pTmpNd->IsCntntNode() )
591 {
592 pCNd = (SwCntntNode*)pTmpNd;
593 if( pTmpNd->IsTxtNode() )
594 ((SwTxtNode*)pTmpNd)->RemoveFromList();
595
596 // if( bNewFrms )
597 // pCNd->DelFrms();
598
599 // setze bei Start/EndNodes die richtigen Indizies
600 // loesche die Gliederungs-Indizies aus
601 // dem alten Nodes-Array
602 //if( pCNd->IsTxtNode() && NO_NUMBERING != //#outline level,zhaojianwei
603 // ((SwTxtNode*)pCNd)->GetTxtColl()->GetOutlineLevel() )
604 if( pCNd->IsTxtNode() && 0 !=
605 ((SwTxtNode*)pCNd)->GetAttrOutlineLevel() )//<-end,by zhaojianwei
606 pOutlineNds->Remove( pCNd );
607 else
608 pCNd = 0;
609 }
610 // else if( bNewFrms && pTmpNd->IsSectionNode() )
611 // ((SwSectionNode*)pTmpNd)->DelFrms();
612 BigPtrArray::Move( aMvIdx.GetIndex(), aIdx.GetIndex() );
613
614 if( bInsOutlineIdx && pCNd )
615 pOutlineNds->Insert( pCNd );
616 if( pTmpNd->IsTxtNode() )
617 ((SwTxtNode*)pTmpNd)->AddToList();
618 }
619 }
620 else
621 {
622 // StartNode holen
623 // Even aIdx points to a startnode, we need the startnode
624 // of the environment of aIdx (#i80941)
625 SwStartNode* pSttNode = aIdx.GetNode().pStartOfSection;
626
627 // Hole alle Boxen mit Inhalt. Deren Indizies auf die
628 // StartNodes muessen umgemeldet werden !!
629 // (Array kopieren und alle gefunden wieder loeschen;
630 // erleichtert das suchen!!)
631 SwNodeIndex aMvIdx( aRg.aEnd, 1 );
632 for( sal_uLong n = 0; n < nInsPos; ++n )
633 {
634 SwNode* pNd = &aMvIdx.GetNode();
635 /* if( bNewFrms )
636 {
637 if( pNd->IsCntntNode() )
638 ((SwCntntNode*)pNd)->DelFrms();
639 else if( pNd->IsSectionNode() )
640 ((SwSectionNode*)pNd)->DelFrms();
641 }
642 */
643 //sal_Bool bOutlNd = pNd->IsTxtNode() && NO_NUMBERING !=//#outline level,zhaojianwei
644 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel();
645 const bool bOutlNd = pNd->IsTxtNode() &&
646 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel();//<-end,zhaojianwei
647 // loesche die Gliederungs-Indizies aus
648 // dem alten Nodes-Array
649 if( bOutlNd )
650 pOutlineNds->Remove( pNd );
651
652 RemoveNode( aMvIdx.GetIndex(), 1, sal_False );
653 pNd->pStartOfSection = pSttNode;
654 rNodes.InsertNode( pNd, aIdx );
655
656 // setze bei Start/EndNodes die richtigen Indizies
657 if( bInsOutlineIdx && bOutlNd )
658 // und setze sie im neuen Nodes-Array
659 rNodes.pOutlineNds->Insert( pNd );
660 else if( pNd->IsStartNode() )
661 pSttNode = (SwStartNode*)pNd;
662 else if( pNd->IsEndNode() )
663 {
664 pSttNode->pEndOfSection = (SwEndNode*)pNd;
665 if( pSttNode->IsSectionNode() )
666 ((SwSectionNode*)pSttNode)->NodesArrChgd();
667 pSttNode = pSttNode->pStartOfSection;
668 }
669 }
670
671 if( pTblNd->GetTable().IsA( TYPE( SwDDETable ) ))
672 {
673 SwDDEFieldType* pTyp = ((SwDDETable&)pTblNd->
674 GetTable()).GetDDEFldType();
675 if( pTyp )
676 {
677 if( rNodes.IsDocNodes() )
678 pTyp->IncRefCnt();
679 else
680 pTyp->DecRefCnt();
681 }
682 }
683
684 if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(
685 rNodes))
686 {
687 SwFrmFmt* pTblFmt = pTblNd->GetTable().GetFrmFmt();
688 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT,
689 pTblFmt );
690 pTblFmt->ModifyNotification( &aMsgHint, &aMsgHint );
691 }
692 }
693 if( bNewFrms )
694 {
695 SwNodeIndex aTmp( aIdx );
696 pTblNd->MakeFrms( &aTmp );
697 }
698 aIdx -= nInsPos;
699 nInsPos = 0;
700 }
701 else if( pSttNd->GetIndex() < aRg.aStart.GetIndex() )
702 {
703 // SectionNode: es wird nicht die gesamte Section
704 // verschoben, also bewege nur die
705 // ContentNodes
706 // StartNode: erzeuge an der Postion eine neue Section
707 do { // middle check loop
708 if( !pSttNd->IsSectionNode() )
709 {
710 // Start und EndNode an der InsertPos erzeugen
711 SwStartNode* pTmp = new SwStartNode( aIdx,
712 ND_STARTNODE,
713 /*?? welcher NodeTyp ??*/
714 SwNormalStartNode );
715
716 nLevel++; // den Index auf StartNode auf den Stack
717 aSttNdStack.C40_INSERT( SwStartNode, pTmp, nLevel );
718
719 // noch den EndNode erzeugen
720 new SwEndNode( aIdx, *pTmp );
721 }
722 else if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(
723 rNodes))
724 {
725 // im UndoNodes-Array spendieren wir einen
726 // Platzhalter
727 new SwNode( aIdx, ND_SECTIONDUMMY );
728 }
729 else
730 {
731 // JP 18.5.2001: neue Section anlegen?? Bug 70454
732 aRg.aEnd--;
733 break;
734
735 }
736
737 aRg.aEnd--;
738 aIdx--;
739 } while( sal_False );
740 }
741 else
742 {
743 // Start und EndNode komplett verschieben
744 // s. u. SwIndex aOldStt( pSttNd->theIndex );
745 //JP 21.05.97: sollte der Start genau der Start des Bereiches sein, so muss
746 // der Node auf jedenfall noch besucht werden!
747 if( &aRg.aStart.GetNode() == pSttNd )
748 --aRg.aStart;
749
750 SwSectionNode* pSctNd = pSttNd->GetSectionNode();
751 if( bNewFrms && pSctNd )
752 pSctNd->DelFrms();
753
754 RemoveNode( aRg.aEnd.GetIndex(), 1, sal_False ); // EndNode loeschen
755 sal_uLong nSttPos = pSttNd->GetIndex();
756
757 // dieser StartNode wird spaeter wieder entfernt!
758 SwStartNode* pTmpSttNd = new SwStartNode( *this, nSttPos+1 );
759 pTmpSttNd->pStartOfSection = pSttNd->pStartOfSection;
760
761 RemoveNode( nSttPos, 1, sal_False ); // SttNode loeschen
762
763 pSttNd->pStartOfSection = aIdx.GetNode().pStartOfSection;
764 rNodes.InsertNode( pSttNd, aIdx );
765 rNodes.InsertNode( pAktNode, aIdx );
766 aIdx--;
767 pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
768
769 aRg.aEnd--;
770
771 nLevel++; // den Index auf StartNode auf den Stack
772 aSttNdStack.C40_INSERT( SwStartNode, pSttNd, nLevel );
773
774 // SectionNode muss noch ein paar Indizies ummelden
775 if( pSctNd )
776 {
777 pSctNd->NodesArrChgd();
778 ++nSectNdCnt;
779 bNewFrms = sal_False;
780 }
781 }
782 }
783 break;
784
785
786
787 case ND_SECTIONNODE:
788 if( !nLevel &&
789 GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(rNodes))
790 {
791 // dann muss an der akt. InsPos ein SectionDummyNode
792 // eingefuegt werden
793 if( nInsPos ) // verschieb schon mal alle bis hier her
794 {
795 // loeschen und kopieren. ACHTUNG: die Indizies ab
796 // "aRg.aEnd+1" werden mit verschoben !!
797 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
798 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
799 aIdx -= nInsPos;
800 nInsPos = 0;
801 }
802 new SwNode( aIdx, ND_SECTIONDUMMY );
803 aRg.aEnd--;
804 aIdx--;
805 break;
806 }
807 // kein break !!
808 case ND_TABLENODE:
809 case ND_STARTNODE:
810 {
811 // Bug #78589# - empty section -> nothing to do
812 // and only if it's a top level section
813 if( !nInsPos && !nLevel )
814 {
815 aRg.aEnd--;
816 break;
817 }
818
819 if( !nLevel ) // es wird eine Stufe runter gestuft
820 {
821 // erzeuge die Runterstufung
822 SwNodeIndex aTmpSIdx( aOrigInsPos.aStart, 1 );
823 SwStartNode* pTmpStt = new SwStartNode( aTmpSIdx,
824 ND_STARTNODE,
825 ((SwStartNode*)pAktNode)->GetStartNodeType() );
826
827 aTmpSIdx--;
828
829 SwNodeIndex aTmpEIdx( aOrigInsPos.aEnd );
830 new SwEndNode( aTmpEIdx, *pTmpStt );
831 aTmpEIdx--;
832 aTmpSIdx++;
833
834 // setze die StartOfSection richtig
835 aRg.aEnd++;
836 {
837 SwNodeIndex aCntIdx( aRg.aEnd );
838 for( sal_uLong n = 0; n < nInsPos; n++, aCntIdx++)
839 aCntIdx.GetNode().pStartOfSection = pTmpStt;
840 }
841
842 // Setze auch bei allen runtergestuften den richtigen StartNode
843 while( aTmpSIdx < aTmpEIdx )
844 if( 0 != (( pAktNode = &aTmpEIdx.GetNode())->GetEndNode()) )
845 aTmpEIdx = pAktNode->StartOfSectionIndex();
846 else
847 {
848 pAktNode->pStartOfSection = pTmpStt;
849 aTmpEIdx--;
850 }
851
852 aIdx--; // hinter den eingefuegten StartNode
853 aRg.aEnd--; // vor den StartNode
854 // kopiere jetzt das Array. ACHTUNG: die Indizies ab
855 // "aRg.aEnd+1" werden mit verschoben !!
856 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
857 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
858 aIdx -= nInsPos+1;
859 nInsPos = 0;
860 }
861 else // es wurden alle Nodes innerhalb eines
862 { // Start- und End-Nodes verschoben
863 ASSERT( pAktNode == aSttNdStack[nLevel] ||
864 ( pAktNode->IsStartNode() &&
865 aSttNdStack[nLevel]->IsSectionNode()),
866 "falscher StartNode" );
867
868 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
869 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
870 aIdx -= nInsPos+1; // vor den eingefuegten StartNode
871 nInsPos = 0;
872
873 // loesche nur noch den Pointer aus dem Nodes-Array.
874 // RemoveNode( aRg.aEnd.GetIndex(), 1, sal_False );
875 RemoveNode( aRg.aEnd.GetIndex(), 1, sal_True );
876 aRg.aEnd--;
877
878 SwSectionNode* pSectNd = aSttNdStack[ nLevel ]->GetSectionNode();
879 if( pSectNd && !--nSectNdCnt )
880 {
881 SwNodeIndex aTmp( *pSectNd );
882 pSectNd->MakeFrms( &aTmp );
883 bNewFrms = bSaveNewFrms;
884 }
885 aSttNdStack.Remove( nLevel ); // vom Stack loeschen
886 nLevel--;
887 }
888
889 // loesche alle entstehenden leeren Start-/End-Node-Paare
890 SwNode* pTmpNode = (*this)[ aRg.aEnd.GetIndex()+1 ]->GetEndNode();
891 if( pTmpNode && ND_STARTNODE == (pAktNode = &aRg.aEnd.GetNode())
892 ->GetNodeType() && pAktNode->StartOfSectionIndex() &&
893 pTmpNode->StartOfSectionNode() == pAktNode )
894 {
895 DelNodes( aRg.aEnd, 2 );
896 aRg.aEnd--;
897 }
898 // aRg.aEnd--;
899 }
900 break;
901
902 case ND_TEXTNODE:
903 //Solution:Add special function to text node.
904 {
905 if( bNewFrms && pAktNode->GetCntntNode() )
906 ((SwCntntNode*)pAktNode)->DelFrms( sal_False );
907 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
908 nInsPos++;
909 aRg.aEnd--;
910 }
911 break;
912 case ND_GRFNODE:
913 case ND_OLENODE:
914 {
915 if( bNewFrms && pAktNode->GetCntntNode() )
916 ((SwCntntNode*)pAktNode)->DelFrms();
917
918 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
919 nInsPos++;
920 aRg.aEnd--;
921 }
922 break;
923
924 case ND_SECTIONDUMMY:
925 if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
926 {
927 if( &rNodes == this ) // innerhalb vom UndoNodesArray
928 {
929 // mit verschieben
930 pAktNode->pStartOfSection = aSttNdStack[ nLevel ];
931 nInsPos++;
932 }
933 else // in ein "normales" Nodes-Array verschieben
934 {
935 // dann muss an der akt. InsPos auch ein SectionNode
936 // (Start/Ende) stehen; dann diesen ueberspringen.
937 // Andernfalls nicht weiter beachten.
938 if( nInsPos ) // verschieb schon mal alle bis hier her
939 {
940 // loeschen und kopieren. ACHTUNG: die Indizies ab
941 // "aRg.aEnd+1" werden mit verschoben !!
942 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
943 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
944 aIdx -= nInsPos;
945 nInsPos = 0;
946 }
947 SwNode* pTmpNd = &aIdx.GetNode();
948 if( pTmpNd->IsSectionNode() ||
949 pTmpNd->StartOfSectionNode()->IsSectionNode() )
950 aIdx--; // ueberspringen
951 }
952 }
953 else {
954 ASSERT( sal_False, "wie kommt diser Node ins Nodes-Array??" );
955 }
956 aRg.aEnd--;
957 break;
958
959 default:
960 ASSERT( sal_False, "was ist das fuer ein Node??" );
961 break;
962 }
963
964 if( nInsPos ) // kopiere den Rest
965 {
966 // der Rest muesste so stimmen
967 SwNodeIndex aSwIndex( aRg.aEnd, 1 );
968 ChgNode( aSwIndex, nInsPos, aIdx, bNewFrms );
969 }
970 aRg.aEnd++; // wieder exklusive Ende
971
972 // loesche alle leeren Start-/End-Node-Paare
973 if( ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
974 pAktNode->StartOfSectionIndex() &&
975 aRg.aEnd.GetNode().GetEndNode() )
976 DelNodes( aRg.aStart, 2 );
977
978 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
979 aOrigInsPos.aStart++;
980 // im gleichen Nodes-Array verschoben ??,
981 // dann von oben nach unten das Update aufrufen !!
982 if( this == &rNodes &&
983 aRg.aEnd.GetIndex() >= aOrigInsPos.aStart.GetIndex() )
984 {
985 UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
986 UpdtOutlineIdx( aRg.aEnd.GetNode() );
987 }
988 else
989 {
990 UpdtOutlineIdx( aRg.aEnd.GetNode() );
991 rNodes.UpdtOutlineIdx( aOrigInsPos.aStart.GetNode() );
992 }
993
994 #ifdef JP_DEBUG
995 {
996 extern Writer* GetDebugWriter(const String&);
997
998 Writer* pWriter = GetDebugWriter(aEmptyStr);
999 if( pWriter )
1000 {
1001 int nError;
1002 SvFileStream aStrm( "c:\\$$move.db", STREAM_WRITE );
1003 SwWriter aWriter( aStrm, *pMyDoc );
1004 aWriter.Write( &nError, pWriter );
1005 }
1006 }
1007 #endif
1008
1009 return sal_True;
1010 }
1011
1012
1013 /*******************************************************************
1014 |*
1015 |* SwNodes::SectionDown
1016 |*
1017 |* Beschreibung
1018 |* SectionDown() legt ein Paar von Start- und EndSection-Node
1019 |* (andere Nodes koennen dazwischen liegen) an.
1020 |*
1021 |* Zustand des SRange beim Verlassen der Funktion: nStart ist der
1022 |* Index des ersten Node hinter dem Start Section Node, nEnd ist
1023 |* der Index des End Section Nodes. Beispiel: Wird Insert Section
1024 |* mehrmals hintereinander aufgerufen, so werden mehrere
1025 |* unmittelbar geschachtelte Sections (keine Content Nodes
1026 |* zwischen Start- bzw. End Nodes) angelegt.
1027 |*
1028 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
1029 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
1030 |*
1031 |* Parameter
1032 |* SwRange &rRange
1033 |* IO:
1034 |* IN
1035 |* rRange.aStart: Einfuegeposition des StartNodes
1036 |* rRange.aEnd: Einfuegeposition des EndNodes
1037 |* OUT
1038 |* rRange.aStart: steht hinter dem eingefuegten Startnode
1039 |* rRange.aEnd: steht auf dem eingefuegen Endnode
1040 |*
1041 |* Ausnahmen
1042 |* 1. SRange-Anfang und SRange-Ende muessen auf dem gleichen Level sein
1043 |* 2. duerfen nicht auf dem obersten Level sein
1044 |* Ist dies nicht der Fall, wird die
1045 |* Funktion durch Aufruf von ERR_RAISE verlassen.
1046 |*
1047 |* Debug-Funktionen
1048 |* die Debugging Tools geben rRange beim Eintritt und beim
1049 |* Verlassen der Funktion aus
1050 |*
1051 |* Ersterstellung
1052 |* VER0100 vb 901214
1053 |*
1054 |* Stand
1055 |* VER0100 vb 901214
1056 |*
1057 *******************************************************************/
SectionDown(SwNodeRange * pRange,SwStartNodeType eSttNdTyp)1058 void SwNodes::SectionDown(SwNodeRange *pRange, SwStartNodeType eSttNdTyp )
1059 {
1060 if( pRange->aStart >= pRange->aEnd ||
1061 pRange->aEnd >= Count() ||
1062 !CheckNodesRange( pRange->aStart, pRange->aEnd ))
1063 return;
1064
1065 // Ist der Anfang vom Bereich vor oder auf einem EndNode, so loesche
1066 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
1067 // Bei anderen Nodes wird eine neuer StartNode eingefuegt
1068 SwNode * pAktNode = &pRange->aStart.GetNode();
1069 SwNodeIndex aTmpIdx( *pAktNode->StartOfSectionNode() );
1070
1071 if( pAktNode->GetEndNode() )
1072 DelNodes( pRange->aStart, 1 ); // verhinder leere Section
1073 else
1074 {
1075 // fuege einen neuen StartNode ein
1076 SwNode* pSttNd = new SwStartNode( pRange->aStart, ND_STARTNODE, eSttNdTyp );
1077 pRange->aStart = *pSttNd;
1078 aTmpIdx = pRange->aStart;
1079 }
1080
1081 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
1082 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen
1083 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1084 pRange->aEnd--;
1085 if( pRange->aEnd.GetNode().GetStartNode() )
1086 DelNodes( pRange->aEnd, 1 );
1087 else
1088 {
1089 pRange->aEnd++;
1090 // fuege einen neuen EndNode ein
1091 new SwEndNode( pRange->aEnd, *pRange->aStart.GetNode().GetStartNode() );
1092 }
1093 pRange->aEnd--;
1094
1095 SectionUpDown( aTmpIdx, pRange->aEnd );
1096 }
1097
1098 /*******************************************************************
1099 |*
1100 |* SwNodes::SectionUp
1101 |*
1102 |* Beschreibung
1103 |* Der von rRange umspannte Bereich wird auf die naechst hoehere
1104 |* Ebene gehoben. Das geschieht dadurch, dass bei
1105 |* rRange.aStart ein Endnode und bei rRange.aEnd ein
1106 |* Startnode eingefuegt wird. Die Indices fuer den Bereich
1107 |* innerhalb von rRange werden geupdated.
1108 |*
1109 |* Allg.: aRange beschreibt den Bereich -exklusive- aEnd !!
1110 |* ( 1.Node: aStart, letzer Node: aEnd-1 !! )
1111 |*
1112 |* Parameter
1113 |* SwRange &rRange
1114 |* IO:
1115 |* IN
1116 |* rRange.aStart: Anfang des hoeher zubewegenden Bereiches
1117 |* rRange.aEnd: der 1.Node hinter dem Bereich
1118 |* OUT
1119 |* rRange.aStart: an der ersten Position innerhalb des
1120 |* hochbewegten Bereiches
1121 |* rRange.aEnd: an der letzten Position innerhalb des
1122 |* hochbewegten Bereiches
1123 |*
1124 |* Debug-Funktionen
1125 |* die Debugging Tools geben rRange beim Eintritt und beim
1126 |* Verlassen der Funktion aus
1127 |*
1128 |* Ersterstellung
1129 |* VER0100 vb 901214
1130 |*
1131 |* Stand
1132 |* VER0100 vb 901214
1133 |*
1134 *******************************************************************/
SectionUp(SwNodeRange * pRange)1135 void SwNodes::SectionUp(SwNodeRange *pRange)
1136 {
1137 if( pRange->aStart >= pRange->aEnd ||
1138 pRange->aEnd >= Count() ||
1139 !CheckNodesRange( pRange->aStart, pRange->aEnd ) ||
1140 !( HighestLevel( *this, *pRange ) > 1 ))
1141 return;
1142
1143 // Ist der Anfang vom Bereich vor oder auf einem StartNode, so loesche
1144 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes enstehen.
1145 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1146 SwNode * pAktNode = &pRange->aStart.GetNode();
1147 SwNodeIndex aIdx( *pAktNode->StartOfSectionNode() );
1148 if( pAktNode->IsStartNode() ) // selbst StartNode
1149 {
1150 SwEndNode* pEndNd = pRange->aEnd.GetNode().GetEndNode();
1151 if( pAktNode == pEndNd->pStartOfSection )
1152 {
1153 // dann wurde paarig aufgehoben, also nur die im Berich neu anpassen
1154 SwStartNode* pTmpSttNd = pAktNode->pStartOfSection;
1155 RemoveNode( pRange->aStart.GetIndex(), 1, sal_True );
1156 RemoveNode( pRange->aEnd.GetIndex(), 1, sal_True );
1157
1158 SwNodeIndex aTmpIdx( pRange->aStart );
1159 while( aTmpIdx < pRange->aEnd )
1160 {
1161 pAktNode = &aTmpIdx.GetNode();
1162 pAktNode->pStartOfSection = pTmpSttNd;
1163 if( pAktNode->IsStartNode() )
1164 aTmpIdx = pAktNode->EndOfSectionIndex() + 1;
1165 else
1166 aTmpIdx++;
1167 }
1168 return ;
1169 }
1170 DelNodes( pRange->aStart, 1 );
1171 }
1172 else if( aIdx == pRange->aStart.GetIndex()-1 ) // vor StartNode
1173 DelNodes( aIdx, 1 );
1174 else
1175 new SwEndNode( pRange->aStart, *aIdx.GetNode().GetStartNode() );
1176
1177 // Ist das Ende vom Bereich vor oder auf einem StartNode, so loesche
1178 // diesen, denn sonst wuerden leere S/E-Nodes oder E/S-Nodes entstehen
1179 // Bei anderen Nodes wird eine neuer EndNode eingefuegt
1180 SwNodeIndex aTmpIdx( pRange->aEnd );
1181 if( pRange->aEnd.GetNode().IsEndNode() )
1182 DelNodes( pRange->aEnd, 1 );
1183 else
1184 {
1185 pAktNode = new SwStartNode( pRange->aEnd );
1186 /*?? welcher NodeTyp ??*/
1187 aTmpIdx = *pRange->aEnd.GetNode().EndOfSectionNode();
1188 pRange->aEnd--;
1189 }
1190
1191 SectionUpDown( aIdx, aTmpIdx );
1192 }
1193
1194
1195 /*************************************************************************
1196 |*
1197 |* SwNodes::SectionUpDown()
1198 |*
1199 |* Beschreibung
1200 |* Methode setzt die Indizies die bei SectionUp oder SectionDwon
1201 |* veraendert wurden wieder richtig, sodass die Ebenen wieder
1202 |* Konsistent sind.
1203 |*
1204 |* Parameter
1205 |* SwIndex & aStart StartNode !!!
1206 |* SwIndex & aEnd EndPunkt
1207 |*
1208 |* Ersterstellung JP 23.04.91
1209 |* Letzte Aenderung JP 23.04.91
1210 |*
1211 *************************************************************************/
SectionUpDown(const SwNodeIndex & aStart,const SwNodeIndex & aEnd)1212 void SwNodes::SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd )
1213 {
1214 SwNode * pAktNode;
1215 SwNodeIndex aTmpIdx( aStart, +1 );
1216 // das Array bildet einen Stack, es werden alle StartOfSelction's gesichert
1217 SwSttNdPtrs aSttNdStack( 1, 5 );
1218 SwStartNode* pTmp = aStart.GetNode().GetStartNode();
1219 aSttNdStack.C40_INSERT( SwStartNode, pTmp, 0 );
1220
1221 // durchlaufe bis der erste zu aendernde Start-Node gefunden wurde
1222 // ( Es wird vom eingefuegten EndNode bis nach vorne die Indexe gesetzt )
1223 for( ;; aTmpIdx++ )
1224 {
1225 pAktNode = &aTmpIdx.GetNode();
1226 pAktNode->pStartOfSection = aSttNdStack[ aSttNdStack.Count()-1 ];
1227
1228 if( pAktNode->GetStartNode() )
1229 {
1230 pTmp = (SwStartNode*)pAktNode;
1231 aSttNdStack.C40_INSERT( SwStartNode, pTmp, aSttNdStack.Count() );
1232 }
1233 else if( pAktNode->GetEndNode() )
1234 {
1235 SwStartNode* pSttNd = aSttNdStack[ aSttNdStack.Count() - 1 ];
1236 pSttNd->pEndOfSection = (SwEndNode*)pAktNode;
1237 aSttNdStack.Remove( aSttNdStack.Count() - 1 );
1238 if( aSttNdStack.Count() )
1239 continue; // noch genuegend EndNodes auf dem Stack
1240
1241 else if( aTmpIdx < aEnd ) // Uebergewicht an StartNodes
1242 // ist das Ende noch nicht erreicht, so hole den Start von
1243 // der uebergeordneten Section
1244 {
1245 aSttNdStack.C40_INSERT( SwStartNode, pSttNd->pStartOfSection, 0 );
1246 }
1247 else // wenn ueber den Bereich hinaus, dann Ende
1248 break;
1249 }
1250 }
1251 }
1252
1253
1254
1255
1256 /*******************************************************************
1257 |*
1258 |* SwNodes::Delete
1259 |*
1260 |* Beschreibung
1261 |* Spezielle Implementierung der Delete-Funktion des
1262 |* variablen Array. Diese spezielle Implementierung ist
1263 |* notwendig, da durch das Loeschen von Start- bzw.
1264 |* Endnodes Inkonsistenzen entstehen koennen. Diese werden
1265 |* durch diese Funktion beseitigt.
1266 |*
1267 |* Parameter
1268 |* IN
1269 |* SwIndex &rIndex bezeichnet die Position, an der
1270 |* geloescht wird
1271 |* rIndex ist nach Aufruf der Funktion unveraendert (Kopie?!)
1272 |* sal_uInt16 nNodes bezeichnet die Anzahl der zu loeschenden
1273 |* Nodes; ist auf 1 defaulted
1274 |*
1275 |* Debug-Funktionen
1276 |* geben beim Eintritt in die Funktion Position und Anzahl
1277 |* der zu loeschenden Nodes aus.
1278 |*
1279 |* Ersterstellung
1280 |* VER0100 vb 901214
1281 |*
1282 |* Stand
1283 |* VER0100 vb 901214
1284 |*
1285 *******************************************************************/
Delete(const SwNodeIndex & rIndex,sal_uLong nNodes)1286 void SwNodes::Delete(const SwNodeIndex &rIndex, sal_uLong nNodes)
1287 {
1288 sal_uInt16 nLevel = 0; // Level-Counter
1289 SwNode * pAktNode;
1290
1291 sal_uLong nCnt = Count() - rIndex.GetIndex() - 1;
1292 if( nCnt > nNodes ) nCnt = nNodes;
1293
1294 if( nCnt == 0 ) // keine Anzahl -> return
1295 return;
1296
1297 SwNodeRange aRg( rIndex, 0, rIndex, nCnt-1 );
1298 // ueberprufe ob rIndex..rIndex + nCnt ueber einen Bereich hinausragt !!
1299 if( ( !aRg.aStart.GetNode().StartOfSectionIndex() &&
1300 !aRg.aStart.GetIndex() ) ||
1301 ! CheckNodesRange( aRg.aStart, aRg.aEnd ) )
1302 return;
1303
1304
1305 // falls aEnd auf keinem ContentNode steht, dann suche den vorherigen
1306 while( ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() ||
1307 ( pAktNode->GetEndNode() &&
1308 !pAktNode->pStartOfSection->IsTableNode() ))
1309 aRg.aEnd--;
1310
1311 nCnt = 0;
1312 // Start erhoehen, damit auf < abgefragt wird. ( bei <= kann es zu
1313 // Problemen fuehren; ist aEnd == aStart und wird aEnd geloscht,
1314 // so ist aEnd <= aStart
1315 aRg.aStart--;
1316
1317 sal_Bool bSaveInNodesDel = bInNodesDel;
1318 bInNodesDel = sal_True;
1319 sal_Bool bUpdateOutline = sal_False;
1320
1321 // bis alles geloescht ist
1322 while( aRg.aStart < aRg.aEnd )
1323 {
1324 pAktNode = &aRg.aEnd.GetNode();
1325
1326 if( pAktNode->GetEndNode() )
1327 {
1328 // die gesamte Section loeschen ?
1329 if( pAktNode->StartOfSectionIndex() > aRg.aStart.GetIndex() )
1330 {
1331 SwTableNode* pTblNd = pAktNode->pStartOfSection->GetTableNode();
1332 if( pTblNd )
1333 pTblNd->DelFrms();
1334
1335 SwNode *pNd, *pChkNd = pAktNode->pStartOfSection;
1336 sal_uInt16 nIdxPos;
1337 do {
1338 pNd = &aRg.aEnd.GetNode();
1339
1340 if( pNd->IsTxtNode() )
1341 {
1342 //if( NO_NUMBERING != //#outline level,zhaojianwei
1343 // ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() &&
1344 if( 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() &&//<-end,zhaojianwei
1345 pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
1346 {
1347 // loesche die Gliederungs-Indizies.
1348 pOutlineNds->Remove( nIdxPos );
1349 bUpdateOutline = sal_True;
1350 }
1351 ((SwTxtNode*)pNd)->InvalidateNumRule();
1352 }
1353 else if( pNd->IsEndNode() &&
1354 pNd->pStartOfSection->IsTableNode() )
1355 ((SwTableNode*)pNd->pStartOfSection)->DelFrms();
1356
1357 aRg.aEnd--;
1358 nCnt++;
1359
1360 } while( pNd != pChkNd );
1361 }
1362 else
1363 {
1364 RemoveNode( aRg.aEnd.GetIndex()+1, nCnt, sal_True ); // loesche
1365 nCnt = 0;
1366 aRg.aEnd--; // vor den EndNode
1367 nLevel++;
1368 }
1369 }
1370 else if( pAktNode->GetStartNode() ) // StartNode gefunden
1371 {
1372 if( nLevel == 0 ) // es wird eine Stufe runter gestuft
1373 {
1374 if( nCnt )
1375 {
1376 // loesche jetzt das Array
1377 aRg.aEnd++;
1378 RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True );
1379 nCnt = 0;
1380 }
1381 }
1382 else // es werden alle Nodes Innerhalb eines Start- und
1383 { // End-Nodes geloescht, loesche mit Start/EndNode
1384 RemoveNode( aRg.aEnd.GetIndex(), nCnt + 2, sal_True ); // loesche Array
1385 nCnt = 0;
1386 nLevel--;
1387 }
1388
1389 // nach dem loeschen kann aEnd auf einem EndNode stehen
1390 // loesche alle leeren Start-/End-Node-Paare
1391 SwNode* pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1392 aRg.aEnd--;
1393 while( pTmpNode &&
1394 ( pAktNode = &aRg.aEnd.GetNode())->GetStartNode() &&
1395 pAktNode->StartOfSectionIndex() )
1396 {
1397 // loesche den EndNode und StartNode
1398 DelNodes( aRg.aEnd, 2 );
1399 pTmpNode = aRg.aEnd.GetNode().GetEndNode();
1400 aRg.aEnd--;
1401 }
1402 }
1403 else // normaler Node, also ins TmpArray einfuegen
1404 {
1405 SwTxtNode* pTxtNd = pAktNode->GetTxtNode();
1406 if( pTxtNd )
1407 {
1408 if( pTxtNd->IsOutline())
1409 { // loesche die Gliederungs-Indizies.
1410 pOutlineNds->Remove( pTxtNd );
1411 bUpdateOutline = sal_True;
1412 }
1413 pTxtNd->InvalidateNumRule();
1414 }
1415 else if( pAktNode->IsCntntNode() )
1416 ((SwCntntNode*)pAktNode)->InvalidateNumRule();
1417
1418 aRg.aEnd--;
1419 nCnt++;
1420 }
1421 }
1422
1423 aRg.aEnd++;
1424 if( nCnt != 0 )
1425 RemoveNode( aRg.aEnd.GetIndex(), nCnt, sal_True ); // loesche den Rest
1426
1427 // loesche alle leeren Start-/End-Node-Paare
1428 while( aRg.aEnd.GetNode().GetEndNode() &&
1429 ( pAktNode = &aRg.aStart.GetNode())->GetStartNode() &&
1430 pAktNode->StartOfSectionIndex() )
1431 // aber ja keinen der heiligen 5.
1432 {
1433 DelNodes( aRg.aStart, 2 ); // loesche den Start- und EndNode
1434 aRg.aStart--;
1435 }
1436
1437 bInNodesDel = bSaveInNodesDel;
1438
1439 if( !bInNodesDel )
1440 {
1441 // rufe jetzt noch das Update fuer die Gliederung/Nummerierung auf
1442 if( bUpdateOutline || bInDelUpdOutl )
1443 {
1444 UpdtOutlineIdx( aRg.aEnd.GetNode() );
1445 bInDelUpdOutl = sal_False;
1446 }
1447
1448 }
1449 else
1450 {
1451 if( bUpdateOutline )
1452 bInDelUpdOutl = sal_True;
1453 }
1454 }
1455
1456 /*******************************************************************
1457 |*
1458 |* SwNodes::GetSectionLevel
1459 |*
1460 |* Beschreibung
1461 |* Die Funktion liefert den Sectionlevel an der durch
1462 |* aIndex bezeichneten Position. Die Funktion ruft die
1463 |* GetSectionlevel-Funktion des durch aIndex bezeichneten
1464 |* Nodes. Diese ist eine virtuelle Funktion, die fuer
1465 |* Endnodes speziell implementiert werden musste.
1466 |* Die Sectionlevels werden ermittelt, indem rekursiv durch
1467 |* die Nodesstruktur (jeweils zum naechsten theEndOfSection)
1468 |* gegangen wird, bis die oberste Ebene erreicht ist
1469 |* (theEndOfSection == 0)
1470 |*
1471 |* Parameter
1472 |* aIndex bezeichnet die Position des Nodes, dessen
1473 |* Sectionlevel ermittelt werden soll. Hier wird eine Kopie
1474 |* uebergeben, da eine Veraenderung der Variablen in der
1475 |* rufenden Funktion nicht wuenschenswert ist.
1476 |*
1477 |* Ausnahmen
1478 |* Der erste Node im Array sollte immer ein Startnode sein.
1479 |* Dieser erfaehrt in der Funktion SwNodes::GetSectionLevel()
1480 |* eine Sonderbehandlung; es wird davon ausgegangen, dass der
1481 |* erste Node auch ein Startnode ist.
1482 |*
1483 |* Ersterstellung
1484 |* VER0100 vb 901214
1485 |*
1486 |* Stand
1487 |* VER0100 vb 901214
1488 |*
1489 *******************************************************************/
GetSectionLevel(const SwNodeIndex & rIdx) const1490 sal_uInt16 SwNodes::GetSectionLevel(const SwNodeIndex &rIdx) const {
1491 // Sonderbehandlung 1. Node
1492 if(rIdx == 0) return 1;
1493 /*
1494 * Keine Rekursion! - hier wird das SwNode::GetSectionLevel
1495 * aufgerufen
1496 */
1497 return rIdx.GetNode().GetSectionLevel();
1498 }
1499
GoStartOfSection(SwNodeIndex * pIdx) const1500 void SwNodes::GoStartOfSection(SwNodeIndex *pIdx) const
1501 {
1502 // hinter den naechsten Startnode
1503 SwNodeIndex aTmp( *pIdx->GetNode().StartOfSectionNode(), +1 );
1504
1505 // steht der Index auf keinem ContentNode, dann gehe dahin. Ist aber
1506 // kein weiterer vorhanden, dann lasse den Index an alter Pos stehen !!!
1507 while( !aTmp.GetNode().IsCntntNode() )
1508 { // gehe vom StartNode ( es kann nur ein StartNode sein ! ) an sein
1509 // Ende
1510 if( *pIdx <= aTmp )
1511 return; // FEHLER: Steht schon hinter der Sektion
1512 aTmp = aTmp.GetNode().EndOfSectionIndex()+1;
1513 if( *pIdx <= aTmp )
1514 return; // FEHLER: Steht schon hinter der Sektion
1515 }
1516 (*pIdx) = aTmp; // steht auf einem ContentNode
1517 }
1518
GoEndOfSection(SwNodeIndex * pIdx) const1519 void SwNodes::GoEndOfSection(SwNodeIndex *pIdx) const
1520 {
1521 // falls er vor einem Endnode steht --> nichts tun
1522 if( !pIdx->GetNode().IsEndNode() )
1523 (*pIdx) = *pIdx->GetNode().EndOfSectionNode();
1524 }
1525
GoNext(SwNodeIndex * pIdx) const1526 SwCntntNode* SwNodes::GoNext(SwNodeIndex *pIdx) const
1527 {
1528 if( pIdx->GetIndex() >= Count() - 1 )
1529 return 0;
1530
1531 SwNodeIndex aTmp(*pIdx, +1);
1532 SwNode* pNd = 0;
1533 while( aTmp < Count()-1 && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
1534 aTmp++;
1535
1536 if( aTmp == Count()-1 )
1537 pNd = 0;
1538 else
1539 (*pIdx) = aTmp;
1540 return (SwCntntNode*)pNd;
1541 }
1542
GoPrevious(SwNodeIndex * pIdx) const1543 SwCntntNode* SwNodes::GoPrevious(SwNodeIndex *pIdx) const
1544 {
1545 if( !pIdx->GetIndex() )
1546 return 0;
1547
1548 SwNodeIndex aTmp( *pIdx, -1 );
1549 SwNode* pNd = 0;
1550 while( aTmp.GetIndex() && 0 == ( pNd = &aTmp.GetNode())->IsCntntNode() )
1551 aTmp--;
1552
1553 if( !aTmp.GetIndex() )
1554 pNd = 0;
1555 else
1556 (*pIdx) = aTmp;
1557 return (SwCntntNode*)pNd;
1558 }
1559
1560 /*************************************************************************
1561 |*
1562 |* sal_Bool SwNodes::CheckNodesRange()
1563 |*
1564 |* Beschreibung
1565 |* Teste ob der uebergene SRange nicht ueber die Grenzen der
1566 |* einzelnen Bereiche (PosIts, Autotext, Content, Icons und Inserts )
1567 |* hinaus reicht.
1568 |* Nach Wahrscheinlichkeit des Ranges sortiert.
1569 |*
1570 |* Alg.: Da festgelegt ist, das aRange.aEnd den 1.Node hinter dem Bereich
1571 |* bezeichnet, wird hier auf aEnd <= End.. getestet !!
1572 |*
1573 |* Parameter SwIndex & Start-Index vom Bereich
1574 |* SwIndex & End-Index vom Bereich
1575 |* sal_Bool sal_True: Start+End in gleicher Section!
1576 |* sal_False: Start+End in verschiedenen Sect.
1577 |* Return-Wert sal_Bool sal_True: gueltiger SRange
1578 |* sal_False: ungueltiger SRange
1579 |*
1580 |* Ersterstellung JP 23.04.91
1581 |* Letzte Aenderung JP 18.06.92
1582 |*
1583 *************************************************************************/
1584
TstIdx(sal_uLong nSttIdx,sal_uLong nEndIdx,sal_uLong nStt,sal_uLong nEnd)1585 inline int TstIdx( sal_uLong nSttIdx, sal_uLong nEndIdx, sal_uLong nStt, sal_uLong nEnd )
1586 {
1587 return nStt < nSttIdx && nEnd >= nSttIdx &&
1588 nStt < nEndIdx && nEnd >= nEndIdx;
1589 }
1590
CheckNodesRange(const SwNodeIndex & rStt,const SwNodeIndex & rEnd) const1591 sal_Bool SwNodes::CheckNodesRange( const SwNodeIndex& rStt, const SwNodeIndex& rEnd ) const
1592 {
1593 sal_uLong nStt = rStt.GetIndex(), nEnd = rEnd.GetIndex();
1594 if( TstIdx( nStt, nEnd, pEndOfContent->StartOfSectionIndex(),
1595 pEndOfContent->GetIndex() )) return sal_True;
1596 if( TstIdx( nStt, nEnd, pEndOfAutotext->StartOfSectionIndex(),
1597 pEndOfAutotext->GetIndex() )) return sal_True;
1598 if( TstIdx( nStt, nEnd, pEndOfPostIts->StartOfSectionIndex(),
1599 pEndOfPostIts->GetIndex() )) return sal_True;
1600 if( TstIdx( nStt, nEnd, pEndOfInserts->StartOfSectionIndex(),
1601 pEndOfInserts->GetIndex() )) return sal_True;
1602 if( TstIdx( nStt, nEnd, pEndOfRedlines->StartOfSectionIndex(),
1603 pEndOfRedlines->GetIndex() )) return sal_True;
1604
1605 return sal_False; // liegt irgendwo dazwischen, FEHLER
1606 }
1607
1608
1609 /*************************************************************************
1610 |*
1611 |* void SwNodes::DelNodes()
1612 |*
1613 |* Beschreibung
1614 |* Loesche aus den NodesArray ab einer Position entsprechend Node's.
1615 |*
1616 |* Parameter SwIndex & Der Startpunkt im Nodes-Array
1617 |* sal_uInt16 die Anzahl
1618 |*
1619 |* Ersterstellung JP 23.04.91
1620 |* Letzte Aenderung JP 23.04.91
1621 |*
1622 *************************************************************************/
DelNodes(const SwNodeIndex & rStart,sal_uLong nCnt)1623 void SwNodes::DelNodes( const SwNodeIndex & rStart, sal_uLong nCnt )
1624 {
1625 int bUpdateNum = 0;
1626 sal_uLong nSttIdx = rStart.GetIndex();
1627
1628 if( !nSttIdx && nCnt == GetEndOfContent().GetIndex()+1 )
1629 {
1630 // es wird das gesamte Nodes-Array zerstoert, man ist im Doc DTOR!
1631 // Die initialen Start-/End-Nodes duerfen nur im SwNodes-DTOR
1632 // zerstoert werden!
1633 SwNode* aEndNdArr[] = { pEndOfContent,
1634 pEndOfPostIts, pEndOfInserts,
1635 pEndOfAutotext, pEndOfRedlines,
1636 0
1637 };
1638
1639 SwNode** ppEndNdArr = aEndNdArr;
1640 while( *ppEndNdArr )
1641 {
1642 nSttIdx = (*ppEndNdArr)->StartOfSectionIndex() + 1;
1643 sal_uLong nEndIdx = (*ppEndNdArr)->GetIndex();
1644
1645 if( nSttIdx != nEndIdx )
1646 RemoveNode( nSttIdx, nEndIdx - nSttIdx, sal_True );
1647
1648 ++ppEndNdArr;
1649 }
1650 }
1651 else
1652 {
1653 for( sal_uLong n = nSttIdx, nEnd = nSttIdx + nCnt; n < nEnd; ++n )
1654 {
1655 SwNode* pNd = (*this)[ n ];
1656
1657 if( pNd->IsTxtNode() &&
1658 //NO_NUMBERING != ((SwTxtNode*)pNd)->GetTxtColl()->GetOutlineLevel() )//#outline level,zhaojianwei
1659 0 != ((SwTxtNode*)pNd)->GetAttrOutlineLevel() ) //<-end,zhaojianwei
1660 { // loesche die Gliederungs-Indizies.
1661 sal_uInt16 nIdxPos;
1662 if( pOutlineNds->Seek_Entry( pNd, &nIdxPos ))
1663 {
1664 pOutlineNds->Remove( nIdxPos );
1665 bUpdateNum = 1;
1666 }
1667 }
1668 if( pNd->IsCntntNode() )
1669 {
1670 ((SwCntntNode*)pNd)->InvalidateNumRule();
1671 ((SwCntntNode*)pNd)->DelFrms();
1672 }
1673 }
1674 RemoveNode( nSttIdx, nCnt, sal_True );
1675
1676 // rufe noch das Update fuer die Gliederungsnumerierung auf
1677 if( bUpdateNum )
1678 UpdtOutlineIdx( rStart.GetNode() );
1679 }
1680 }
1681
1682
1683 /*************************************************************************
1684 |*
1685 |* sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1686 |*
1687 |* Beschreibung
1688 |* Berechne den hoehsten Level innerhalb des Bereiches
1689 |*
1690 |* Parameter SwNodes & das Node-Array
1691 |* SwNodeRange & der zu ueberpruefende Bereich
1692 |* Return sal_uInt16 der hoechste Level
1693 |*
1694 |* Ersterstellung JP 24.04.91
1695 |* Letzte Aenderung JP 24.04.91
1696 |*
1697 *************************************************************************/
1698
1699 struct HighLevel
1700 {
1701 sal_uInt16 nLevel, nTop;
HighLevelHighLevel1702 HighLevel( sal_uInt16 nLv ) : nLevel( nLv ), nTop( nLv ) {}
1703
1704 };
1705
_HighestLevel(const SwNodePtr & rpNode,void * pPara)1706 sal_Bool _HighestLevel( const SwNodePtr& rpNode, void * pPara )
1707 {
1708 HighLevel * pHL = (HighLevel*)pPara;
1709 if( rpNode->GetStartNode() )
1710 pHL->nLevel++;
1711 else if( rpNode->GetEndNode() )
1712 pHL->nLevel--;
1713 if( pHL->nTop > pHL->nLevel )
1714 pHL->nTop = pHL->nLevel;
1715 return sal_True;
1716
1717 }
1718
HighestLevel(SwNodes & rNodes,const SwNodeRange & rRange)1719 sal_uInt16 HighestLevel( SwNodes & rNodes, const SwNodeRange & rRange )
1720 {
1721 HighLevel aPara( rNodes.GetSectionLevel( rRange.aStart ));
1722 rNodes.ForEach( rRange.aStart, rRange.aEnd, _HighestLevel, &aPara );
1723 return aPara.nTop;
1724
1725 }
1726
1727 /*************************************************************************
1728 |*
1729 |* SwNodes::Move()
1730 |*
1731 |* Beschreibung
1732 |* Parameter SwPaM& zu kopierender Bereich
1733 |* SwNodes& in dieses Nodes-Array
1734 |* SwPosition& auf diese Position im Nodes-Array
1735 |* Ersterstellung JP 09.07.92
1736 |* Letzte Aenderung JP 09.07.92
1737 |*
1738 *************************************************************************/
MoveRange(SwPaM & rPam,SwPosition & rPos,SwNodes & rNodes)1739 void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
1740 {
1741 SwPosition * const pStt = rPam.Start();
1742 SwPosition * const pEnd = rPam.End();
1743
1744 if( !rPam.HasMark() || *pStt >= *pEnd )
1745 return;
1746
1747 if( this == &rNodes && *pStt <= rPos && rPos < *pEnd )
1748 return;
1749
1750 SwNodeIndex aEndIdx( pEnd->nNode );
1751 SwNodeIndex aSttIdx( pStt->nNode );
1752 SwTxtNode *const pSrcNd = aSttIdx.GetNode().GetTxtNode();
1753 SwTxtNode * pDestNd = rPos.nNode.GetNode().GetTxtNode();
1754 sal_Bool bSplitDestNd = sal_True;
1755 sal_Bool bCopyCollFmt = pDestNd && !pDestNd->GetTxt().Len();
1756
1757 if( pSrcNd )
1758 {
1759 // ist der 1.Node ein TextNode, dann muss im NodesArray auch
1760 // ein TextNode vorhanden sein, in den der Inhalt geschoben wird
1761 if( !pDestNd )
1762 {
1763 pDestNd = rNodes.MakeTxtNode( rPos.nNode, pSrcNd->GetTxtColl() );
1764 rPos.nNode--;
1765 rPos.nContent.Assign( pDestNd, 0 );
1766 bCopyCollFmt = sal_True;
1767 }
1768 bSplitDestNd = pDestNd->Len() > rPos.nContent.GetIndex() ||
1769 pEnd->nNode.GetNode().IsTxtNode();
1770
1771 // verschiebe jetzt noch den Inhalt in den neuen Node
1772 sal_Bool bOneNd = pStt->nNode == pEnd->nNode;
1773 const xub_StrLen nLen =
1774 ( (bOneNd) ? pEnd->nContent.GetIndex() : pSrcNd->Len() )
1775 - pStt->nContent.GetIndex();
1776
1777 if( !pEnd->nNode.GetNode().IsCntntNode() )
1778 {
1779 bOneNd = sal_True;
1780 sal_uLong nSttNdIdx = pStt->nNode.GetIndex() + 1;
1781 const sal_uLong nEndNdIdx = pEnd->nNode.GetIndex();
1782 for( ; nSttNdIdx < nEndNdIdx; ++nSttNdIdx )
1783 {
1784 if( (*this)[ nSttNdIdx ]->IsCntntNode() )
1785 {
1786 bOneNd = sal_False;
1787 break;
1788 }
1789 }
1790 }
1791
1792 // das kopieren / setzen der Vorlagen darf erst nach
1793 // dem Splitten erfolgen
1794 if( !bOneNd && bSplitDestNd )
1795 {
1796 if( !rPos.nContent.GetIndex() )
1797 {
1798 bCopyCollFmt = sal_True;
1799 }
1800 if( rNodes.IsDocNodes() )
1801 {
1802 SwDoc* const pInsDoc = pDestNd->GetDoc();
1803 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
1804 pInsDoc->SplitNode( rPos, false );
1805 }
1806 else
1807 {
1808 pDestNd->SplitCntntNode( rPos );
1809 }
1810
1811 if( rPos.nNode == aEndIdx )
1812 {
1813 aEndIdx--;
1814 }
1815 bSplitDestNd = sal_True;
1816
1817 pDestNd = rNodes[ rPos.nNode.GetIndex() - 1 ]->GetTxtNode();
1818 if( nLen )
1819 {
1820 pSrcNd->CutText( pDestNd, SwIndex( pDestNd, pDestNd->Len()),
1821 pStt->nContent, nLen );
1822 }
1823 }
1824 else if ( nLen )
1825 {
1826 pSrcNd->CutText( pDestNd, rPos.nContent, pStt->nContent, nLen );
1827 }
1828
1829 if( bCopyCollFmt )
1830 {
1831 SwDoc* const pInsDoc = pDestNd->GetDoc();
1832 ::sw::UndoGuard const undoGuard(pInsDoc->GetIDocumentUndoRedo());
1833 pSrcNd->CopyCollFmt( *pDestNd );
1834 bCopyCollFmt = sal_False;
1835 }
1836
1837 if( bOneNd ) // das wars schon
1838 {
1839 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
1840 // wurde, so stehen sie in unterschieden Nodes. Auch die Selektion
1841 // wird aufgehoben !
1842 pEnd->nContent = pStt->nContent;
1843 rPam.DeleteMark();
1844 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
1845 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
1846 return;
1847 }
1848
1849 aSttIdx++;
1850 }
1851 else if( pDestNd )
1852 {
1853 if( rPos.nContent.GetIndex() )
1854 {
1855 if( rPos.nContent.GetIndex() == pDestNd->Len() )
1856 {
1857 rPos.nNode++;
1858 }
1859 else if( rPos.nContent.GetIndex() )
1860 {
1861 // falls im EndNode gesplittet wird, dann muss der EndIdx
1862 // korrigiert werden !!
1863 const bool bCorrEnd = aEndIdx == rPos.nNode;
1864 // es wird kein Text an den TextNode angehaengt, also splitte ihn
1865
1866 if( rNodes.IsDocNodes() )
1867 {
1868 SwDoc* const pInsDoc = pDestNd->GetDoc();
1869 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
1870 pInsDoc->SplitNode( rPos, false );
1871 }
1872 else
1873 {
1874 pDestNd->SplitCntntNode( rPos );
1875 }
1876
1877 pDestNd = rPos.nNode.GetNode().GetTxtNode();
1878
1879 if ( bCorrEnd )
1880 {
1881 aEndIdx--;
1882 }
1883 }
1884 }
1885 // am Ende steht noch ein leerer Text Node herum.
1886 bSplitDestNd = sal_True;
1887 }
1888
1889 SwTxtNode* const pEndSrcNd = aEndIdx.GetNode().GetTxtNode();
1890 if ( pEndSrcNd )
1891 {
1892 {
1893 // am Bereichsende entsteht ein neuer TextNode
1894 if( !bSplitDestNd )
1895 {
1896 if( rPos.nNode < rNodes.GetEndOfContent().GetIndex() )
1897 {
1898 rPos.nNode++;
1899 }
1900
1901 pDestNd =
1902 rNodes.MakeTxtNode( rPos.nNode, pEndSrcNd->GetTxtColl() );
1903 rPos.nNode--;
1904 rPos.nContent.Assign( pDestNd, 0 );
1905 }
1906 else
1907 {
1908 pDestNd = rPos.nNode.GetNode().GetTxtNode();
1909 }
1910
1911 if( pDestNd && pEnd->nContent.GetIndex() )
1912 {
1913 // verschiebe jetzt noch den Inhalt in den neuen Node
1914 SwIndex aIdx( pEndSrcNd, 0 );
1915 pEndSrcNd->CutText( pDestNd, rPos.nContent, aIdx,
1916 pEnd->nContent.GetIndex());
1917 }
1918
1919 if( bCopyCollFmt )
1920 {
1921 SwDoc* const pInsDoc = pDestNd->GetDoc();
1922 ::sw::UndoGuard const ug(pInsDoc->GetIDocumentUndoRedo());
1923 pEndSrcNd->CopyCollFmt( *pDestNd );
1924 }
1925 }
1926 }
1927 else
1928 {
1929 if ( pSrcNd && aEndIdx.GetNode().IsCntntNode() )
1930 {
1931 aEndIdx++;
1932 }
1933 if( !bSplitDestNd )
1934 {
1935 rPos.nNode++;
1936 rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(), 0 );
1937 }
1938 }
1939
1940 if( aEndIdx != aSttIdx )
1941 {
1942 // verschiebe jetzt die Nodes in das NodesArary
1943 const sal_uLong nSttDiff = aSttIdx.GetIndex() - pStt->nNode.GetIndex();
1944 SwNodeRange aRg( aSttIdx, aEndIdx );
1945 _MoveNodes( aRg, rNodes, rPos.nNode );
1946 // falls ins gleiche Nodes-Array verschoben wurde, stehen die
1947 // Indizies jetzt auch an der neuen Position !!!!
1948 // (also alles wieder umsetzen)
1949 if( &rNodes == this )
1950 {
1951 pStt->nNode = aRg.aEnd.GetIndex() - nSttDiff;
1952 }
1953 }
1954
1955 // falls der Start-Node verschoben wurde, in dem der Cursor stand, so
1956 // muss der Content im akt. Content angemeldet werden !!!
1957 if ( &pStt->nNode.GetNode() == &GetEndOfContent() )
1958 {
1959 const bool bSuccess = GoPrevious( &pStt->nNode );
1960 ASSERT( bSuccess, "Move() - no ContentNode here" );
1961 (void) bSuccess;
1962 }
1963 pStt->nContent.Assign( pStt->nNode.GetNode().GetCntntNode(),
1964 pStt->nContent.GetIndex() );
1965 // der PaM wird korrigiert, denn falls ueber Nodegrenzen verschoben
1966 // wurde, so stehen sie in unterschielichen Nodes. Auch die Selektion
1967 // wird aufgehoben !
1968 *pEnd = *pStt;
1969 rPam.DeleteMark();
1970 GetDoc()->GetDocShell()->Broadcast( SwFmtFldHint( 0,
1971 rNodes.IsDocNodes() ? SWFMTFLD_INSERTED : SWFMTFLD_REMOVED ) );
1972 }
1973
1974
1975
1976 /*************************************************************************
1977 |*
1978 |* SwNodes::_Copy()
1979 |*
1980 |* Beschreibung
1981 |* Parameter SwNodeRange& zu kopierender Bereich
1982 |* SwDoc& in dieses Dokument
1983 |* SwIndex& auf diese Position im Nodes-Array
1984 |* Ersterstellung JP 11.11.92
1985 |* Letzte Aenderung JP 11.11.92
1986 |*
1987 *************************************************************************/
1988
MaxLvl(sal_uInt8 nMin,sal_uInt8 nMax,short nNew)1989 inline sal_uInt8 MaxLvl( sal_uInt8 nMin, sal_uInt8 nMax, short nNew )
1990 {
1991 return (sal_uInt8)(nNew < nMin ? nMin : nNew > nMax ? nMax : nNew);
1992 }
1993
_CopyNodes(const SwNodeRange & rRange,const SwNodeIndex & rIndex,sal_Bool bNewFrms,sal_Bool bTblInsDummyNode) const1994 void SwNodes::_CopyNodes( const SwNodeRange& rRange,
1995 const SwNodeIndex& rIndex, sal_Bool bNewFrms, sal_Bool bTblInsDummyNode ) const
1996 {
1997 SwDoc* pDoc = rIndex.GetNode().GetDoc();
1998
1999 SwNode * pAktNode;
2000 if( rIndex == 0 ||
2001 ( (pAktNode = &rIndex.GetNode())->GetStartNode() &&
2002 !pAktNode->StartOfSectionIndex() ))
2003 return;
2004
2005 SwNodeRange aRg( rRange );
2006
2007 // "einfache" StartNodes oder EndNodes ueberspringen
2008 while( ND_STARTNODE == (pAktNode = & aRg.aStart.GetNode())->GetNodeType()
2009 || ( pAktNode->IsEndNode() &&
2010 !pAktNode->pStartOfSection->IsSectionNode() ) )
2011 aRg.aStart++;
2012
2013 // falls aEnd-1 auf keinem ContentNode steht, dann suche den vorherigen
2014 aRg.aEnd--;
2015 // #i107142#: if aEnd is start node of a special section, do nothing.
2016 // Otherwise this could lead to crash: going through all previous
2017 // special section nodes and then one before the first.
2018 if (aRg.aEnd.GetNode().StartOfSectionIndex() != 0)
2019 {
2020 while( ((pAktNode = & aRg.aEnd.GetNode())->GetStartNode() &&
2021 !pAktNode->IsSectionNode() ) ||
2022 ( pAktNode->IsEndNode() &&
2023 ND_STARTNODE == pAktNode->pStartOfSection->GetNodeType()) )
2024 {
2025 aRg.aEnd--;
2026 }
2027 }
2028 aRg.aEnd++;
2029
2030 // wird im selben Array's verschoben, dann ueberpruefe die Einfuegepos.
2031 if( aRg.aStart >= aRg.aEnd )
2032 return;
2033
2034 // when inserting into the source range, nothing need to be done
2035 DBG_ASSERT( &aRg.aStart.GetNodes() == this,
2036 "aRg should use thisnodes array" );
2037 DBG_ASSERT( &aRg.aStart.GetNodes() == &aRg.aEnd.GetNodes(),
2038 "Range across different nodes arrays? You deserve punishment!");
2039 if( &rIndex.GetNodes() == &aRg.aStart.GetNodes() &&
2040 rIndex.GetIndex() >= aRg.aStart.GetIndex() &&
2041 rIndex.GetIndex() < aRg.aEnd.GetIndex() )
2042 return;
2043
2044 SwNodeIndex aInsPos( rIndex );
2045 SwNodeIndex aOrigInsPos( rIndex, -1 ); // Originale Insert Pos
2046 sal_uInt16 nLevel = 0; // Level-Counter
2047
2048 for( sal_uLong nNodeCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
2049 nNodeCnt > 0; --nNodeCnt )
2050 {
2051 pAktNode = &aRg.aStart.GetNode();
2052 switch( pAktNode->GetNodeType() )
2053 {
2054 case ND_TABLENODE:
2055 // dann kopiere mal den TableNode
2056 // Tabell in Fussnote kopieren ?
2057 if( aInsPos < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
2058 pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex()
2059 < aInsPos.GetIndex() )
2060 {
2061 nNodeCnt -=
2062 ( pAktNode->EndOfSectionIndex() -
2063 aRg.aStart.GetIndex() );
2064
2065 // dann alle Nodes der Tabelle in die akt. Zelle kopieren
2066 // fuer den TabellenNode einen DummyNode einfuegen?
2067 if( bTblInsDummyNode )
2068 new SwNode( aInsPos, ND_SECTIONDUMMY );
2069
2070 for( aRg.aStart++; aRg.aStart.GetIndex() <
2071 pAktNode->EndOfSectionIndex();
2072 aRg.aStart++ )
2073 {
2074 // fuer den Box-StartNode einen DummyNode einfuegen?
2075 if( bTblInsDummyNode )
2076 new SwNode( aInsPos, ND_SECTIONDUMMY );
2077
2078 SwStartNode* pSttNd = aRg.aStart.GetNode().GetStartNode();
2079 _CopyNodes( SwNodeRange( *pSttNd, + 1,
2080 *pSttNd->EndOfSectionNode() ),
2081 aInsPos, bNewFrms, sal_False );
2082
2083 // fuer den Box-EndNode einen DummyNode einfuegen?
2084 if( bTblInsDummyNode )
2085 new SwNode( aInsPos, ND_SECTIONDUMMY );
2086 aRg.aStart = *pSttNd->EndOfSectionNode();
2087 }
2088 // fuer den TabellenEndNode einen DummyNode einfuegen?
2089 if( bTblInsDummyNode )
2090 new SwNode( aInsPos, ND_SECTIONDUMMY );
2091 aRg.aStart = *pAktNode->EndOfSectionNode();
2092 }
2093 else
2094 {
2095 SwNodeIndex nStt( aInsPos, -1 );
2096 SwTableNode* pTblNd = ((SwTableNode*)pAktNode)->
2097 MakeCopy( pDoc, aInsPos );
2098 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2;
2099
2100 aRg.aStart = pAktNode->EndOfSectionIndex();
2101
2102 if( bNewFrms && pTblNd )
2103 {
2104 nStt = aInsPos;
2105 pTblNd->MakeFrms( &nStt );
2106 }
2107 }
2108 break;
2109
2110 case ND_SECTIONNODE: // SectionNode
2111 // If the end of the section is outside the copy range,
2112 // the section node will skipped, not copied!
2113 // If someone want to change this behaviour, he has to adjust the function
2114 // lcl_NonCopyCount(..) in ndcopy.cxx which relies on it.
2115 if( pAktNode->EndOfSectionIndex() < aRg.aEnd.GetIndex() )
2116 {
2117 // also der gesamte, lege einen neuen SectionNode an
2118 SwNodeIndex nStt( aInsPos, -1 );
2119 SwSectionNode* pSectNd = ((SwSectionNode*)pAktNode)->
2120 MakeCopy( pDoc, aInsPos );
2121
2122 nNodeCnt -= aInsPos.GetIndex() - nStt.GetIndex() -2;
2123 aRg.aStart = pAktNode->EndOfSectionIndex();
2124
2125 if( bNewFrms && pSectNd &&
2126 !pSectNd->GetSection().IsHidden() )
2127 pSectNd->MakeFrms( &nStt );
2128 }
2129 break;
2130
2131 case ND_STARTNODE: // StartNode gefunden
2132 {
2133 SwStartNode* pTmp = new SwStartNode( aInsPos, ND_STARTNODE,
2134 ((SwStartNode*)pAktNode)->GetStartNodeType() );
2135 new SwEndNode( aInsPos, *pTmp );
2136 aInsPos--;
2137 nLevel++;
2138 }
2139 break;
2140
2141 case ND_ENDNODE:
2142 if( nLevel ) // vollstaendige Section
2143 {
2144 --nLevel;
2145 aInsPos++; // EndNode schon vorhanden
2146 }
2147 else if( !pAktNode->pStartOfSection->IsSectionNode() )
2148 {
2149 // erzeuge eine Section an der originalen InsertPosition
2150 SwNodeRange aTmpRg( aOrigInsPos, 1, aInsPos );
2151 pDoc->GetNodes().SectionDown( &aTmpRg,
2152 pAktNode->pStartOfSection->GetStartNodeType() );
2153 }
2154 break;
2155
2156 case ND_TEXTNODE:
2157 case ND_GRFNODE:
2158 case ND_OLENODE:
2159 {
2160 SwCntntNode* pNew = ((SwCntntNode*)pAktNode)->MakeCopy(
2161 pDoc, aInsPos );
2162 if( !bNewFrms ) // dflt. werden die Frames immer angelegt
2163 pNew->DelFrms();
2164 }
2165 break;
2166
2167 case ND_SECTIONDUMMY:
2168 if (GetDoc()->GetIDocumentUndoRedo().IsUndoNodes(*this))
2169 {
2170 // dann muss an der akt. InsPos auch ein SectionNode
2171 // (Start/Ende) stehen; dann diesen ueberspringen.
2172 // Andernfalls nicht weiter beachten.
2173 SwNode *const pTmpNd = & aInsPos.GetNode();
2174 if( pTmpNd->IsSectionNode() ||
2175 pTmpNd->StartOfSectionNode()->IsSectionNode() )
2176 aInsPos++; // ueberspringen
2177 }
2178 else {
2179 ASSERT( sal_False, "wie kommt diser Node ins Nodes-Array??" );
2180 }
2181 break;
2182
2183 default:
2184 ASSERT( sal_False, "weder Start-/End-/Content-Node, unbekannter Typ" );
2185 }
2186 aRg.aStart++;
2187 }
2188
2189
2190 #ifdef JP_DEBUG
2191 {
2192 extern Writer* GetDebugWriter(const String&);
2193
2194 Writer* pWriter = GetDebugWriter(aEmptyStr);
2195 if( pWriter )
2196 {
2197 int nError;
2198 SvFileStream aStrm( "c:\\$$copy.db", STREAM_WRITE );
2199 SwWriter aWriter( aStrm, *pMyDoc );
2200 aWriter.Write( &nError, pWriter );
2201 }
2202 }
2203 #endif
2204 }
2205
_DelDummyNodes(const SwNodeRange & rRg)2206 void SwNodes::_DelDummyNodes( const SwNodeRange& rRg )
2207 {
2208 SwNodeIndex aIdx( rRg.aStart );
2209 while( aIdx.GetIndex() < rRg.aEnd.GetIndex() )
2210 {
2211 if( ND_SECTIONDUMMY == aIdx.GetNode().GetNodeType() )
2212 RemoveNode( aIdx.GetIndex(), 1, sal_True );
2213 else
2214 aIdx++;
2215 }
2216 }
2217
MakeEmptySection(const SwNodeIndex & rIdx,SwStartNodeType eSttNdTyp)2218 SwStartNode* SwNodes::MakeEmptySection( const SwNodeIndex& rIdx,
2219 SwStartNodeType eSttNdTyp )
2220 {
2221 SwStartNode* pSttNd = new SwStartNode( rIdx, ND_STARTNODE, eSttNdTyp );
2222 new SwEndNode( rIdx, *pSttNd );
2223 return pSttNd;
2224 }
2225
2226
MakeTextSection(const SwNodeIndex & rWhere,SwStartNodeType eSttNdTyp,SwTxtFmtColl * pColl,SwAttrSet * pAutoAttr)2227 SwStartNode* SwNodes::MakeTextSection( const SwNodeIndex & rWhere,
2228 SwStartNodeType eSttNdTyp,
2229 SwTxtFmtColl *pColl,
2230 SwAttrSet* pAutoAttr )
2231 {
2232 SwStartNode* pSttNd = new SwStartNode( rWhere, ND_STARTNODE, eSttNdTyp );
2233 new SwEndNode( rWhere, *pSttNd );
2234 MakeTxtNode( SwNodeIndex( rWhere, - 1 ), pColl, pAutoAttr );
2235 return pSttNd;
2236 }
2237
2238 // zum naechsten Content-Node, der nicht geschuetzt oder versteckt ist
2239 // (beides auf sal_False ==> GoNext/GoPrevious!!!)
GoNextSection(SwNodeIndex * pIdx,int bSkipHidden,int bSkipProtect) const2240 SwCntntNode* SwNodes::GoNextSection( SwNodeIndex * pIdx,
2241 int bSkipHidden, int bSkipProtect ) const
2242 {
2243 int bFirst = sal_True;
2244 SwNodeIndex aTmp( *pIdx );
2245 const SwNode* pNd;
2246 while( aTmp < Count() - 1 )
2247 {
2248 pNd = & aTmp.GetNode();
2249 if (ND_SECTIONNODE == pNd->GetNodeType())
2250 {
2251 const SwSection& rSect = ((SwSectionNode*)pNd)->GetSection();
2252 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2253 (bSkipProtect && rSect.IsProtectFlag()) )
2254 // dann diese Section ueberspringen
2255 aTmp = *pNd->EndOfSectionNode();
2256 bFirst = sal_False;
2257 }
2258 else if( bFirst )
2259 {
2260 bFirst = sal_False;
2261 if( pNd->pStartOfSection->IsSectionNode() )
2262 {
2263 const SwSection& rSect = ((SwSectionNode*)pNd->
2264 pStartOfSection)->GetSection();
2265 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2266 (bSkipProtect && rSect.IsProtectFlag()) )
2267 // dann diese Section ueberspringen
2268 aTmp = *pNd->EndOfSectionNode();
2269 }
2270 }
2271 else if( ND_CONTENTNODE & pNd->GetNodeType() )
2272 {
2273 const SwSectionNode* pSectNd;
2274 if( ( bSkipHidden || bSkipProtect ) &&
2275 0 != (pSectNd = pNd->FindSectionNode() ) &&
2276 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
2277 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2278 {
2279 aTmp = *pSectNd->EndOfSectionNode();
2280 }
2281 else
2282 {
2283 (*pIdx) = aTmp;
2284 return (SwCntntNode*)pNd;
2285 }
2286 }
2287 aTmp++;
2288 bFirst = sal_False;
2289 }
2290 return 0;
2291 }
2292
GoPrevSection(SwNodeIndex * pIdx,int bSkipHidden,int bSkipProtect) const2293 SwCntntNode* SwNodes::GoPrevSection( SwNodeIndex * pIdx,
2294 int bSkipHidden, int bSkipProtect ) const
2295 {
2296 int bFirst = sal_True;
2297 SwNodeIndex aTmp( *pIdx );
2298 const SwNode* pNd;
2299 while( aTmp > 0 )
2300 {
2301 pNd = & aTmp.GetNode();
2302 if (ND_ENDNODE == pNd->GetNodeType())
2303 {
2304 if( pNd->pStartOfSection->IsSectionNode() )
2305 {
2306 const SwSection& rSect = ((SwSectionNode*)pNd->
2307 pStartOfSection)->GetSection();
2308 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2309 (bSkipProtect && rSect.IsProtectFlag()) )
2310 // dann diese Section ueberspringen
2311 aTmp = *pNd->StartOfSectionNode();
2312 }
2313 bFirst = sal_False;
2314 }
2315 else if( bFirst )
2316 {
2317 bFirst = sal_False;
2318 if( pNd->pStartOfSection->IsSectionNode() )
2319 {
2320 const SwSection& rSect = ((SwSectionNode*)pNd->
2321 pStartOfSection)->GetSection();
2322 if( (bSkipHidden && rSect.IsHiddenFlag()) ||
2323 (bSkipProtect && rSect.IsProtectFlag()) )
2324 // dann diese Section ueberspringen
2325 aTmp = *pNd->StartOfSectionNode();
2326 }
2327 }
2328 else if( ND_CONTENTNODE & pNd->GetNodeType() )
2329 {
2330 const SwSectionNode* pSectNd;
2331 if( ( bSkipHidden || bSkipProtect ) &&
2332 0 != (pSectNd = pNd->FindSectionNode() ) &&
2333 ( ( bSkipHidden && pSectNd->GetSection().IsHiddenFlag() ) ||
2334 ( bSkipProtect && pSectNd->GetSection().IsProtectFlag() )) )
2335 {
2336 aTmp = *pSectNd;
2337 }
2338 else
2339 {
2340 (*pIdx) = aTmp;
2341 return (SwCntntNode*)pNd;
2342 }
2343 }
2344 aTmp--;
2345 }
2346 return 0;
2347 }
2348
2349
2350 // suche den vorhergehenden [/nachfolgenden ] ContentNode oder
2351 // TabellenNode mit Frames. Wird kein Ende angeben, dann wird mit
2352 // dem FrameIndex begonnen; ansonsten, wird mit dem vor rFrmIdx und
2353 // dem hintern pEnd die Suche gestartet. Sollte kein gueltiger Node
2354 // gefunden werden, wird 0 returnt. rFrmIdx zeigt auf dem Node mit
2355 // Frames
FindPrvNxtFrmNode(SwNodeIndex & rFrmIdx,const SwNode * pEnd) const2356 SwNode* SwNodes::FindPrvNxtFrmNode( SwNodeIndex& rFrmIdx,
2357 const SwNode* pEnd ) const
2358 {
2359 SwNode* pFrmNd = 0;
2360
2361 // habe wir gar kein Layout, vergiss es
2362 if( GetDoc()->GetCurrentViewShell() ) //swmod 071108//swmod 071225
2363 {
2364 SwNode* pSttNd = &rFrmIdx.GetNode();
2365
2366 // wird in eine versteckte Section verschoben ??
2367 SwSectionNode* pSectNd = pSttNd->IsSectionNode()
2368 ? pSttNd->StartOfSectionNode()->FindSectionNode()
2369 : pSttNd->FindSectionNode();
2370 if( !( pSectNd && pSectNd->GetSection().CalcHiddenFlag()/*IsHiddenFlag()*/ ) )
2371 {
2372 // #130650# in a table in table situation we have to assure that we don't leave the
2373 // outer table cell when the inner table is looking for a PrvNxt...
2374 SwTableNode* pTableNd = pSttNd->IsTableNode()
2375 ? pSttNd->StartOfSectionNode()->FindTableNode()
2376 : pSttNd->FindTableNode();
2377 SwNodeIndex aIdx( rFrmIdx );
2378 SwNode* pNd;
2379 if( pEnd )
2380 {
2381 aIdx--;
2382 pNd = &aIdx.GetNode();
2383 }
2384 else
2385 pNd = pSttNd;
2386
2387 if( ( pFrmNd = pNd )->IsCntntNode() )
2388 rFrmIdx = aIdx;
2389
2390 // suche nach vorne/hinten nach einem Content Node
2391 else if( 0 != ( pFrmNd = GoPrevSection( &aIdx, sal_True, sal_False )) &&
2392 ::CheckNodesRange( aIdx, rFrmIdx, sal_True ) &&
2393 // nach vorne nie aus der Tabelle hinaus!
2394 pFrmNd->FindTableNode() == pTableNd &&
2395 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
2396 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
2397 == pSttNd->FindTableBoxStartNode() ) &&
2398 (!pSectNd || pSttNd->IsSectionNode() ||
2399 pSectNd->GetIndex() < pFrmNd->GetIndex())
2400 )
2401 {
2402 rFrmIdx = aIdx;
2403 }
2404 else
2405 {
2406 if( pEnd )
2407 aIdx = pEnd->GetIndex() + 1;
2408 else
2409 aIdx = rFrmIdx;
2410
2411 // JP 19.09.93: aber nie die Section dafuer verlassen !!
2412 if( ( pEnd && ( pFrmNd = &aIdx.GetNode())->IsCntntNode() ) ||
2413 ( 0 != ( pFrmNd = GoNextSection( &aIdx, sal_True, sal_False )) &&
2414 ::CheckNodesRange( aIdx, rFrmIdx, sal_True ) &&
2415 ( pFrmNd->FindTableNode() == pTableNd &&
2416 // Bug 37652: nach hinten nie aus der Tabellenzelle hinaus!
2417 (!pFrmNd->FindTableNode() || pFrmNd->FindTableBoxStartNode()
2418 == pSttNd->FindTableBoxStartNode() ) ) &&
2419 (!pSectNd || pSttNd->IsSectionNode() ||
2420 pSectNd->EndOfSectionIndex() > pFrmNd->GetIndex())
2421 ))
2422 {
2423 //JP 18.02.99: Undo von Merge einer Tabelle mit der
2424 // der vorherigen, wenn dahinter auch noch eine steht
2425 // falls aber der Node in einer Tabelle steht, muss
2426 // natuerlich dieser returnt werden, wenn der SttNode eine
2427 // Section oder Tabelle ist!
2428 SwTableNode* pTblNd;
2429 if( pSttNd->IsTableNode() &&
2430 0 != ( pTblNd = pFrmNd->FindTableNode() ) &&
2431 // TABLE IN TABLE:
2432 pTblNd != pSttNd->StartOfSectionNode()->FindTableNode() )
2433 {
2434 pFrmNd = pTblNd;
2435 rFrmIdx = *pFrmNd;
2436 }
2437 else
2438 rFrmIdx = aIdx;
2439 }
2440 else if( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsTableNode() )
2441 {
2442 pFrmNd = pNd->StartOfSectionNode();
2443 rFrmIdx = *pFrmNd;
2444 }
2445 else
2446 {
2447 if( pEnd )
2448 aIdx = pEnd->GetIndex() + 1;
2449 else
2450 aIdx = rFrmIdx.GetIndex() + 1;
2451
2452 if( (pFrmNd = &aIdx.GetNode())->IsTableNode() )
2453 rFrmIdx = aIdx;
2454 else
2455 {
2456 pFrmNd = 0;
2457
2458 // is there some sectionnodes before a tablenode?
2459 while( aIdx.GetNode().IsSectionNode() )
2460 {
2461 const SwSection& rSect = aIdx.GetNode().
2462 GetSectionNode()->GetSection();
2463 if( rSect.IsHiddenFlag() )
2464 aIdx = aIdx.GetNode().EndOfSectionIndex()+1;
2465 else
2466 aIdx++;
2467 }
2468 if( aIdx.GetNode().IsTableNode() )
2469 {
2470 rFrmIdx = aIdx;
2471 pFrmNd = &aIdx.GetNode();
2472 }
2473 }
2474 }
2475 }
2476 }
2477 }
2478 return pFrmNd;
2479 }
2480
ForEach(const SwNodeIndex & rStart,const SwNodeIndex & rEnd,FnForEach_SwNodes fnForEach,void * pArgs)2481 void SwNodes::ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd,
2482 FnForEach_SwNodes fnForEach, void* pArgs )
2483 {
2484 BigPtrArray::ForEach( rStart.GetIndex(), rEnd.GetIndex(),
2485 (FnForEach) fnForEach, pArgs );
2486 }
2487
2488 struct _TempBigPtrEntry : public BigPtrEntry
2489 {
_TempBigPtrEntry_TempBigPtrEntry2490 _TempBigPtrEntry() {}
2491 };
2492
2493
RemoveNode(sal_uLong nDelPos,sal_uLong nSz,sal_Bool bDel)2494 void SwNodes::RemoveNode( sal_uLong nDelPos, sal_uLong nSz, sal_Bool bDel )
2495 {
2496 sal_uLong nEnd = nDelPos + nSz;
2497 SwNode* pNew = (*this)[ nEnd ];
2498
2499 if( pRoot )
2500 {
2501 SwNodeIndex *p = pRoot;
2502 while( p )
2503 {
2504 sal_uLong nIdx = p->GetIndex();
2505 SwNodeIndex* pNext = p->pNext;
2506 if( nDelPos <= nIdx && nIdx < nEnd )
2507 (*p) = *pNew;
2508
2509 p = pNext;
2510 }
2511
2512 p = pRoot->pPrev;
2513 while( p )
2514 {
2515 sal_uLong nIdx = p->GetIndex();
2516 SwNodeIndex* pPrev = p->pPrev;
2517 if( nDelPos <= nIdx && nIdx < nEnd )
2518 (*p) = *pNew;
2519
2520 p = pPrev;
2521 }
2522 }
2523
2524 {
2525 for (sal_uLong nCnt = 0; nCnt < nSz; nCnt++)
2526 {
2527 SwTxtNode * pTxtNd = ((*this)[ nDelPos + nCnt ])->GetTxtNode();
2528
2529 if (pTxtNd)
2530 {
2531 // --> OD 2008-03-13 #refactorlists#
2532 // pTxtNd->UnregisterNumber();
2533 pTxtNd->RemoveFromList();
2534 // <--
2535 }
2536 }
2537 }
2538
2539 if( bDel )
2540 {
2541 sal_uLong nCnt = nSz;
2542 SwNode *pDel = (*this)[ nDelPos+nCnt-1 ], *pPrev = (*this)[ nDelPos+nCnt-2 ];
2543
2544 // temp. Object setzen
2545 //JP 24.08.98: muessten eigentlich einzeln removed werden, weil
2546 // das Remove auch rekursiv gerufen werden kann, z.B. bei
2547 // zeichengebundenen Rahmen. Da aber dabei viel zu viel
2548 // ablaueft, wird hier ein temp. Objekt eingefuegt, das
2549 // dann mit dem Remove wieder entfernt wird.
2550 // siehe Bug 55406
2551 _TempBigPtrEntry aTempEntry;
2552 BigPtrEntry* pTempEntry = &aTempEntry;
2553
2554 while( nCnt-- )
2555 {
2556 delete pDel;
2557 pDel = pPrev;
2558 sal_uLong nPrevNdIdx = pPrev->GetIndex();
2559 BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
2560 if( nCnt )
2561 pPrev = (*this)[ nPrevNdIdx - 1 ];
2562 }
2563 nDelPos = pDel->GetIndex() + 1;
2564 }
2565
2566 BigPtrArray::Remove( nDelPos, nSz );
2567 }
2568
RegisterIndex(SwNodeIndex & rIdx)2569 void SwNodes::RegisterIndex( SwNodeIndex& rIdx )
2570 {
2571 if( !pRoot ) // noch keine Root gesetzt?
2572 {
2573 pRoot = &rIdx;
2574 pRoot->pPrev = 0;
2575 pRoot->pNext = 0;
2576 }
2577 else
2578 {
2579 // immer hinter die Root haengen
2580 rIdx.pNext = pRoot->pNext;
2581 pRoot->pNext = &rIdx;
2582 rIdx.pPrev = pRoot;
2583 if( rIdx.pNext )
2584 rIdx.pNext->pPrev = &rIdx;
2585 }
2586 }
2587
DeRegisterIndex(SwNodeIndex & rIdx)2588 void SwNodes::DeRegisterIndex( SwNodeIndex& rIdx )
2589 {
2590 SwNodeIndex* pN = rIdx.pNext;
2591 SwNodeIndex* pP = rIdx.pPrev;
2592
2593 if( pRoot == &rIdx )
2594 pRoot = pP ? pP : pN;
2595
2596 if( pP )
2597 pP->pNext = pN;
2598 if( pN )
2599 pN->pPrev = pP;
2600
2601 rIdx.pNext = 0;
2602 rIdx.pPrev = 0;
2603 }
2604
InsertNode(const SwNodePtr pNode,const SwNodeIndex & rPos)2605 void SwNodes::InsertNode( const SwNodePtr pNode,
2606 const SwNodeIndex& rPos )
2607 {
2608 const ElementPtr pIns = pNode;
2609 BigPtrArray::Insert( pIns, rPos.GetIndex() );
2610 }
2611
InsertNode(const SwNodePtr pNode,sal_uLong nPos)2612 void SwNodes::InsertNode( const SwNodePtr pNode,
2613 sal_uLong nPos )
2614 {
2615 const ElementPtr pIns = pNode;
2616 BigPtrArray::Insert( pIns, nPos );
2617 }
2618
2619 // ->#112139#
DocumentSectionStartNode(SwNode * pNode) const2620 SwNode * SwNodes::DocumentSectionStartNode(SwNode * pNode) const
2621 {
2622 if (NULL != pNode)
2623 {
2624 SwNodeIndex aIdx(*pNode);
2625
2626 if (aIdx <= (*this)[0]->EndOfSectionIndex())
2627 pNode = (*this)[0];
2628 else
2629 {
2630 while ((*this)[0] != pNode->StartOfSectionNode())
2631 pNode = pNode->StartOfSectionNode();
2632 }
2633 }
2634
2635 return pNode;
2636 }
2637
DocumentSectionEndNode(SwNode * pNode) const2638 SwNode * SwNodes::DocumentSectionEndNode(SwNode * pNode) const
2639 {
2640 return DocumentSectionStartNode(pNode)->EndOfSectionNode();
2641 }
2642
2643 //SwNode * SwNodes::operator[](int n) const
2644 //{
2645 // return operator[]((sal_uLong) n);
2646 //}
2647 // <-#112139#
2648
IsDocNodes() const2649 sal_Bool SwNodes::IsDocNodes() const
2650 {
2651 return this == &pMyDoc->GetNodes();
2652 }
2653