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