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