xref: /aoo42x/main/sw/source/core/docnode/ndcopy.cxx (revision a2e27fc1)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 #include <editeng/brkitem.hxx>
28 
29 #define _ZFORLIST_DECLARE_TABLE
30 #include <hintids.hxx>
31 #include <fmtpdsc.hxx>
32 #include <fmtanchr.hxx>
33 #include <fmtcntnt.hxx>
34 #include <doc.hxx>
35 #include <IDocumentUndoRedo.hxx>
36 #include <pam.hxx>
37 #include <ndtxt.hxx>
38 #include <fldbas.hxx>
39 #include <swtable.hxx>
40 #include <ddefld.hxx>
41 #include <undobj.hxx>
42 #include <IMark.hxx>
43 #include <mvsave.hxx>
44 #include <cellatr.hxx>
45 #include <swtblfmt.hxx>
46 #include <swddetbl.hxx>
47 #include <docary.hxx>
48 #include <fmtcnct.hxx>
49 #include <redline.hxx>
50 #include <paratr.hxx>
51 #include <pagedesc.hxx>
52 #include <poolfmt.hxx>
53 #include <SwNodeNum.hxx>
54 #ifndef DBG_UTIL
55 #define CHECK_TABLE(t)
56 #else
57 #ifdef DEBUG
58 #define CHECK_TABLE(t) (t).CheckConsistency();
59 #else
60 #define CHECK_TABLE(t)
61 #endif
62 #endif
63 
64 namespace
65 {
66     /*
67         The lcl_CopyBookmarks function has to copy bookmarks from the source to the destination nodes
68         array. It is called after a call of the _CopyNodes(..) function. But this function does not copy
69         every node (at least at the moment: 2/08/2006 ), section start and end nodes will not be copied if the corresponding end/start node is outside the copied pam.
70         The lcl_NonCopyCount function counts the number of these nodes, given the copied pam and a node
71         index inside the pam.
72         rPam is the original source pam, rLastIdx is the last calculated position, rDelCount the number
73         of "non-copy" nodes between rPam.Start() and rLastIdx.
74         nNewIdx is the new position of interest.
75     */
76 
77     static void lcl_NonCopyCount( const SwPaM& rPam, SwNodeIndex& rLastIdx, const sal_uLong nNewIdx, sal_uLong& rDelCount )
78     {
79         sal_uLong nStart = rPam.Start()->nNode.GetIndex();
80         sal_uLong nEnd = rPam.End()->nNode.GetIndex();
81         if( rLastIdx.GetIndex() < nNewIdx ) // Moving forward?
82         {
83             do // count "non-copy" nodes
84             {
85                 SwNode& rNode = rLastIdx.GetNode();
86                 if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
87                     || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
88                     ++rDelCount;
89                 rLastIdx++;
90             }
91             while( rLastIdx.GetIndex() < nNewIdx );
92         }
93         else if( rDelCount ) // optimization: if there are no "non-copy" nodes until now,
94                              // no move backward needed
95         {
96             while( rLastIdx.GetIndex() > nNewIdx )
97             {
98                 SwNode& rNode = rLastIdx.GetNode();
99                 if( ( rNode.IsSectionNode() && rNode.EndOfSectionIndex() >= nEnd )
100                     || ( rNode.IsEndNode() && rNode.StartOfSectionNode()->GetIndex() < nStart ) )
101                     --rDelCount;
102                 rLastIdx--;
103             }
104         }
105     }
106 
107     static void lcl_SetCpyPos( const SwPosition& rOrigPos,
108                         const SwPosition& rOrigStt,
109                         const SwPosition& rCpyStt,
110                         SwPosition& rChgPos,
111                         sal_uLong nDelCount )
112     {
113         sal_uLong nNdOff = rOrigPos.nNode.GetIndex();
114         nNdOff -= rOrigStt.nNode.GetIndex();
115         nNdOff -= nDelCount;
116         xub_StrLen nCntntPos = rOrigPos.nContent.GetIndex();
117 
118         // --> OD, AMA 2008-07-07 #b6713815#
119         // Always adjust <nNode> at to be changed <SwPosition> instance <rChgPos>
120         rChgPos.nNode = nNdOff + rCpyStt.nNode.GetIndex();
121         if( !nNdOff )
122         // <--
123         {
124             // dann nur den Content anpassen
125             if( nCntntPos > rOrigStt.nContent.GetIndex() )
126                 nCntntPos = nCntntPos - rOrigStt.nContent.GetIndex();
127             else
128                 nCntntPos = 0;
129             nCntntPos = nCntntPos + rCpyStt.nContent.GetIndex();
130         }
131         rChgPos.nContent.Assign( rChgPos.nNode.GetNode().GetCntntNode(), nCntntPos );
132     }
133 
134     // TODO: use SaveBookmark (from _DelBookmarks)
135     static void lcl_CopyBookmarks(const SwPaM& rPam, SwPaM& rCpyPam)
136     {
137         const SwDoc* pSrcDoc = rPam.GetDoc();
138         SwDoc* pDestDoc =  rCpyPam.GetDoc();
139         const IDocumentMarkAccess* const pSrcMarkAccess = pSrcDoc->getIDocumentMarkAccess();
140         ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
141 
142         const SwPosition &rStt = *rPam.Start(), &rEnd = *rPam.End();
143         SwPosition* pCpyStt = rCpyPam.Start();
144 
145         typedef ::std::vector< const ::sw::mark::IMark* > mark_vector_t;
146         mark_vector_t vMarksToCopy;
147         for(IDocumentMarkAccess::const_iterator_t ppMark = pSrcMarkAccess->getMarksBegin();
148             ppMark != pSrcMarkAccess->getMarksEnd();
149             ppMark++)
150         {
151             const ::sw::mark::IMark* const pMark = ppMark->get();
152             const SwPosition& rMarkStart = pMark->GetMarkStart();
153             const SwPosition& rMarkEnd = pMark->GetMarkEnd();
154             // only include marks that are in the range and not touching
155             // both start and end
156             bool bIsNotOnBoundary = pMark->IsExpanded()
157                 ? (rMarkStart != rStt || rMarkEnd != rEnd)  // rMarkStart != rMarkEnd
158                 : (rMarkStart != rStt && rMarkEnd != rEnd); // rMarkStart == rMarkEnd
159             if(rMarkStart >= rStt && rMarkEnd <= rEnd && bIsNotOnBoundary)
160             {
161                 vMarksToCopy.push_back(pMark);
162             }
163         }
164         // We have to count the "non-copied" nodes..
165         SwNodeIndex aCorrIdx(rStt.nNode);
166         sal_uLong nDelCount = 0;
167         for(mark_vector_t::const_iterator ppMark = vMarksToCopy.begin();
168             ppMark != vMarksToCopy.end();
169             ++ppMark)
170         {
171             const ::sw::mark::IMark* const pMark = *ppMark;
172             SwPaM aTmpPam(*pCpyStt);
173             lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetMarkPos().nNode.GetIndex(), nDelCount);
174             lcl_SetCpyPos( pMark->GetMarkPos(), rStt, *pCpyStt, *aTmpPam.GetPoint(), nDelCount);
175             if(pMark->IsExpanded())
176             {
177                 aTmpPam.SetMark();
178                 lcl_NonCopyCount(rPam, aCorrIdx, pMark->GetOtherMarkPos().nNode.GetIndex(), nDelCount);
179                 lcl_SetCpyPos(pMark->GetOtherMarkPos(), rStt, *pCpyStt, *aTmpPam.GetMark(), nDelCount);
180             }
181 
182             ::sw::mark::IMark* const pNewMark = pDestDoc->getIDocumentMarkAccess()->makeMark(
183                 aTmpPam,
184                 pMark->GetName(),
185                 IDocumentMarkAccess::GetType(*pMark));
186             // Explicitly try to get exactly the same name as in the source
187             // because NavigatorReminders, DdeBookmarks etc. ignore the proposed name
188             pDestDoc->getIDocumentMarkAccess()->renameMark(pNewMark, pMark->GetName());
189             ::sw::mark::IBookmark* const pNewBookmark =
190                 dynamic_cast< ::sw::mark::IBookmark* const >(pNewMark);
191             if(pNewBookmark) /* copying additional attributes for bookmarks */
192             {
193                 const ::sw::mark::IBookmark* const pOldBookmark = dynamic_cast< const ::sw::mark::IBookmark* >(pMark);
194                 pNewBookmark->SetKeyCode(pOldBookmark->GetKeyCode());
195                 pNewBookmark->SetShortName(pOldBookmark->GetShortName());
196             }
197             ::sfx2::Metadatable const*const pMetadatable(
198                     dynamic_cast< ::sfx2::Metadatable const* >(pMark));
199             ::sfx2::Metadatable      *const pNewMetadatable(
200                     dynamic_cast< ::sfx2::Metadatable      * >(pNewMark));
201             if (pMetadatable && pNewMetadatable)
202             {
203                 pNewMetadatable->RegisterAsCopyOf(*pMetadatable);
204             }
205         }
206     }
207 }
208 
209 // Struktur fuer das Mappen von alten und neuen Frame-Formaten an den
210 // Boxen und Lines einer Tabelle
211 
212 struct _MapTblFrmFmt
213 {
214 	const SwFrmFmt *pOld, *pNew;
215 	_MapTblFrmFmt( const SwFrmFmt *pOldFmt, const SwFrmFmt*pNewFmt )
216 		: pOld( pOldFmt ), pNew( pNewFmt )
217 	{}
218 };
219 
220 SV_DECL_VARARR( _MapTblFrmFmts, _MapTblFrmFmt, 0, 10 )
221 SV_IMPL_VARARR( _MapTblFrmFmts, _MapTblFrmFmt );
222 
223 SwCntntNode* SwTxtNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
224 {
225 	// the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
226 	// node with the collection and hard attributes. Normally ist the same
227 	// node, but if insert a glossary without formatting, then the Attrnode
228 	// is the prev node of the destionation position in dest. document.
229 	SwTxtNode* pCpyTxtNd = (SwTxtNode*)this;
230 	SwTxtNode* pCpyAttrNd = pCpyTxtNd;
231 
232 	// kopiere die Formate in das andere Dokument:
233 	SwTxtFmtColl* pColl = 0;
234 	if( pDoc->IsInsOnlyTextGlossary() )
235 	{
236 		SwNodeIndex aIdx( rIdx, -1 );
237 		if( aIdx.GetNode().IsTxtNode() )
238 		{
239 			pCpyAttrNd = aIdx.GetNode().GetTxtNode();
240 			pColl = &pCpyAttrNd->GetTxtColl()->GetNextTxtFmtColl();
241 		}
242 	}
243 	if( !pColl )
244 		pColl = pDoc->CopyTxtColl( *GetTxtColl() );
245 
246 	SwTxtNode* pTxtNd = pDoc->GetNodes().MakeTxtNode( rIdx, pColl );
247 
248     // METADATA: register copy
249     pTxtNd->RegisterAsCopyOf(*pCpyTxtNd);
250 
251 	// kopiere Attribute/Text
252     if( !pCpyAttrNd->HasSwAttrSet() )
253 		// wurde ein AttrSet fuer die Numerierung angelegt, so loesche diesen!
254 		pTxtNd->ResetAllAttr();
255 
256 	// if Copy-Textnode unequal to Copy-Attrnode, then copy first
257 	// the attributes into the new Node.
258 	if( pCpyAttrNd != pCpyTxtNd )
259 	{
260 		pCpyAttrNd->CopyAttr( pTxtNd, 0, 0 );
261         if( pCpyAttrNd->HasSwAttrSet() )
262 		{
263 			SwAttrSet aSet( *pCpyAttrNd->GetpSwAttrSet() );
264 			aSet.ClearItem( RES_PAGEDESC );
265 			aSet.ClearItem( RES_BREAK );
266 			aSet.CopyToModify( *pTxtNd );
267 		}
268 	}
269 
270 		// ??? reicht das ??? was ist mit PostIts/Feldern/FeldTypen ???
271     // --> OD 2008-11-18 #i96213# - force copy of all attributes
272     pCpyTxtNd->CopyText( pTxtNd, SwIndex( pCpyTxtNd ),
273         pCpyTxtNd->GetTxt().Len(), true );
274     // <--
275 
276 //FEATURE::CONDCOLL
277 	if( RES_CONDTXTFMTCOLL == pColl->Which() )
278 		pTxtNd->ChkCondColl();
279 //FEATURE::CONDCOLL
280 
281 	return pTxtNd;
282 }
283 
284 
285 sal_Bool lcl_SrchNew( const _MapTblFrmFmt& rMap, void * pPara )
286 {
287 	if( rMap.pOld != *(const SwFrmFmt**)pPara )
288 		return sal_True;
289 	*((const SwFrmFmt**)pPara) = rMap.pNew;
290 	return sal_False;		// abbrechen, Pointer gefunden
291 }
292 
293 
294 struct _CopyTable
295 {
296 	SwDoc* pDoc;
297 	sal_uLong nOldTblSttIdx;
298 	_MapTblFrmFmts& rMapArr;
299 	SwTableLine* pInsLine;
300 	SwTableBox* pInsBox;
301 	SwTableNode *pTblNd;
302 	const SwTable *pOldTable;
303 
304 	_CopyTable( SwDoc* pDc, _MapTblFrmFmts& rArr, sal_uLong nOldStt,
305 				SwTableNode& rTblNd, const SwTable* pOldTbl )
306 		: pDoc(pDc), nOldTblSttIdx(nOldStt), rMapArr(rArr),
307         pInsLine(0), pInsBox(0), pTblNd(&rTblNd), pOldTable( pOldTbl )
308 	{}
309 };
310 
311 sal_Bool lcl_CopyTblBox( const SwTableBox*& rpBox, void* pPara );
312 
313 sal_Bool lcl_CopyTblLine( const SwTableLine*& rpLine, void* pPara );
314 
315 sal_Bool lcl_CopyTblBox( const SwTableBox*& rpBox, void* pPara )
316 {
317 	_CopyTable* pCT = (_CopyTable*)pPara;
318 
319 	SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)rpBox->GetFrmFmt();
320 	pCT->rMapArr.ForEach( lcl_SrchNew, &pBoxFmt );
321 	if( pBoxFmt == rpBox->GetFrmFmt() )	// ein neues anlegen ??
322 	{
323 		const SfxPoolItem* pItem;
324 		if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMULA, sal_False,
325 			&pItem ) && ((SwTblBoxFormula*)pItem)->IsIntrnlName() )
326 		{
327 			((SwTblBoxFormula*)pItem)->PtrToBoxNm( pCT->pOldTable );
328 		}
329 
330 		pBoxFmt = pCT->pDoc->MakeTableBoxFmt();
331 		pBoxFmt->CopyAttrs( *rpBox->GetFrmFmt() );
332 
333 		if( rpBox->GetSttIdx() )
334 		{
335 			SvNumberFormatter* pN = pCT->pDoc->GetNumberFormatter( sal_False );
336 			if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == pBoxFmt->
337 				GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
338 			{
339 				sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
340 				sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
341 				if( nNewIdx != nOldIdx )
342                     pBoxFmt->SetFmtAttr( SwTblBoxNumFormat( nNewIdx ));
343 
344 			}
345 		}
346 
347 		pCT->rMapArr.Insert( _MapTblFrmFmt( rpBox->GetFrmFmt(), pBoxFmt ),
348 								pCT->rMapArr.Count() );
349 	}
350 
351 	sal_uInt16 nLines = rpBox->GetTabLines().Count();
352 	SwTableBox* pNewBox;
353 	if( nLines )
354 		pNewBox = new SwTableBox( pBoxFmt, nLines, pCT->pInsLine );
355 	else
356 	{
357 		//Modified for i119955,2012.6.13
358 		//Avoid overflow problem...
359 		int nIn = rpBox->GetSttIdx() - pCT->nOldTblSttIdx;
360 		if ( nIn > 0 )
361 		{
362 		//End
363 		SwNodeIndex aNewIdx( *pCT->pTblNd,
364 							rpBox->GetSttIdx() - pCT->nOldTblSttIdx );
365 		ASSERT( aNewIdx.GetNode().IsStartNode(), "Index nicht auf einem StartNode" );
366 		pNewBox = new SwTableBox( pBoxFmt, aNewIdx, pCT->pInsLine );
367         pNewBox->setRowSpan( rpBox->getRowSpan() );
368 		//Modified for i119955,2012.6.13
369 		}else
370 		{
371 			return sal_False;
372 		}
373 		//End
374 	}
375 
376 	pCT->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox,
377 					pCT->pInsLine->GetTabBoxes().Count() );
378 
379 	if( nLines )
380 	{
381 		_CopyTable aPara( *pCT );
382 		aPara.pInsBox = pNewBox;
383 		((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_CopyTblLine, &aPara );
384 	}
385 	else if( pNewBox->IsInHeadline( &pCT->pTblNd->GetTable() ))
386 		// in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen
387 		pNewBox->GetSttNd()->CheckSectionCondColl();
388 	return sal_True;
389 }
390 
391 sal_Bool lcl_CopyTblLine( const SwTableLine*& rpLine, void* pPara )
392 {
393 	_CopyTable* pCT = (_CopyTable*)pPara;
394 	SwTableLineFmt* pLineFmt = (SwTableLineFmt*)rpLine->GetFrmFmt();
395 	pCT->rMapArr.ForEach( lcl_SrchNew, &pLineFmt );
396 	if( pLineFmt == rpLine->GetFrmFmt() )	// ein neues anlegen ??
397 	{
398 		pLineFmt = pCT->pDoc->MakeTableLineFmt();
399 		pLineFmt->CopyAttrs( *rpLine->GetFrmFmt() );
400 		pCT->rMapArr.Insert( _MapTblFrmFmt( rpLine->GetFrmFmt(), pLineFmt ),
401 								pCT->rMapArr.Count());
402 	}
403 	SwTableLine* pNewLine = new SwTableLine( pLineFmt,
404 							rpLine->GetTabBoxes().Count(), pCT->pInsBox );
405 	// die neue Zeile in die Tabelle eintragen
406 	if( pCT->pInsBox )
407 	{
408 		pCT->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine,
409 				pCT->pInsBox->GetTabLines().Count() );
410 	}
411 	else
412 	{
413 		pCT->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
414 				pCT->pTblNd->GetTable().GetTabLines().Count() );
415 	}
416 	pCT->pInsLine = pNewLine;
417 	((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_CopyTblBox, pCT );
418 	return sal_True;
419 }
420 
421 SwTableNode* SwTableNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
422 {
423 	// in welchen Array steht ich denn Nodes, UndoNodes ??
424 	SwNodes& rNds = (SwNodes&)GetNodes();
425 
426 	{
427 		// nicht in Fussnoten kopieren !!
428 /*
429 !! Mal ohne Frames
430 		SwCntntNode* pCNd = pDoc->GetNodes()[ rIdx ]->GetCntntNode();
431 		SwFrm* pFrm;
432 		if( (pCNd && 0 != ( pFrm = pCNd->GetFrm()))
433 				? pFrm->FindFtnFrm()
434 				: rIdx < pDoc->GetNodes().EndOfInserts &&
435 					pDoc->GetNodes()[pDoc->GetNodes().EndOfInserts]->StartOfSection()
436 					< rIdx )
437 */
438 		if( rIdx < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
439 			rIdx >= pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
440 			return 0;
441 	}
442 
443 	// das TableFrmFmt kopieren
444 	String sTblName( GetTable().GetFrmFmt()->GetName() );
445 	if( !pDoc->IsCopyIsMove() )
446 	{
447 		const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
448 		for( sal_uInt16 n = rTblFmts.Count(); n; )
449 			if( rTblFmts[ --n ]->GetName() == sTblName )
450 			{
451 				sTblName = pDoc->GetUniqueTblName();
452 				break;
453 			}
454 	}
455 
456 	SwFrmFmt* pTblFmt = pDoc->MakeTblFrmFmt( sTblName, pDoc->GetDfltFrmFmt() );
457 	pTblFmt->CopyAttrs( *GetTable().GetFrmFmt() );
458 	SwTableNode* pTblNd = new SwTableNode( rIdx );
459 	SwEndNode* pEndNd = new SwEndNode( rIdx, *pTblNd );
460 	SwNodeIndex aInsPos( *pEndNd );
461 
462 	SwTable& rTbl = (SwTable&)pTblNd->GetTable();
463     rTbl.RegisterToFormat( *pTblFmt );
464 
465     rTbl.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
466 	rTbl.SetTblChgMode( GetTable().GetTblChgMode() );
467 	rTbl.SetTableModel( GetTable().IsNewModel() );
468 
469 	SwDDEFieldType* pDDEType = 0;
470 	if( IS_TYPE( SwDDETable, &GetTable() ))
471 	{
472 		// es wird eine DDE-Tabelle kopiert
473 		// ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ?
474 		pDDEType = ((SwDDETable&)GetTable()).GetDDEFldType();
475 		if( pDDEType->IsDeleted() )
476 			pDoc->InsDeletedFldType( *pDDEType );
477 		else
478 			pDDEType = (SwDDEFieldType*)pDoc->InsertFldType( *pDDEType );
479 		ASSERT( pDDEType, "unbekannter FieldType" );
480 
481 		// tauschen am Node den Tabellen-Pointer aus
482 		SwDDETable* pNewTable = new SwDDETable( pTblNd->GetTable(), pDDEType );
483 		pTblNd->SetNewTable( pNewTable, sal_False );
484 	}
485 	// dann kopiere erstmal den Inhalt der Tabelle, die Zuordnung der
486 	// Boxen/Lines und das anlegen der Frames erfolgt spaeter
487 	SwNodeRange aRg( *this, +1, *EndOfSectionNode() );	// (wo stehe in denn nun ??)
488 
489     // If there is a table in this table, the table format for the outer table
490     // does not seem to be used, because the table does not have any contents yet
491     // (see IsUsed). Therefore the inner table gets the same name as the outer table.
492     // We have to make sure that the table node of the SwTable is accessible, even
493     // without any content in aSortCntBoxes. #i26629#
494     pTblNd->GetTable().SetTableNode( pTblNd );
495     rNds._Copy( aRg, aInsPos, sal_False );
496     pTblNd->GetTable().SetTableNode( 0 );
497 
498 	// Sonderbehandlung fuer eine einzelne Box
499 	if( 1 == GetTable().GetTabSortBoxes().Count() )
500 	{
501 		aRg.aStart.Assign( *pTblNd, 1 );
502 		aRg.aEnd.Assign( *pTblNd->EndOfSectionNode() );
503 		pDoc->GetNodes().SectionDown( &aRg, SwTableBoxStartNode );
504 	}
505 
506 	// loesche alle Frames vom kopierten Bereich, diese werden beim
507 	// erzeugen des TableFrames angelegt !
508 	pTblNd->DelFrms();
509 
510 	_MapTblFrmFmts aMapArr;
511 	_CopyTable aPara( pDoc, aMapArr, GetIndex(), *pTblNd, &GetTable() );
512 
513 	((SwTable&)GetTable()).GetTabLines().ForEach( &lcl_CopyTblLine, &aPara );
514 
515     if( pDDEType )
516 		pDDEType->IncRefCnt();
517 
518     CHECK_TABLE( GetTable() );
519 	return pTblNd;
520 }
521 
522 void SwTxtNode::CopyCollFmt( SwTxtNode& rDestNd )
523 {
524 	// kopiere die Formate in das andere Dokument:
525 
526 	// Sonderbehandlung fuer PageBreak/PageDesc/ColBrk
527 	SwDoc* pDestDoc = rDestNd.GetDoc();
528 	SwAttrSet aPgBrkSet( pDestDoc->GetAttrPool(), aBreakSetRange );
529     const SwAttrSet* pSet;
530 
531     if( 0 != ( pSet = rDestNd.GetpSwAttrSet() ) )
532 	{
533 		// Sonderbehandlung fuer unsere Break-Attribute
534 		const SfxPoolItem* pAttr;
535 		if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pAttr ) )
536 			aPgBrkSet.Put( *pAttr );
537 
538 		if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, sal_False, &pAttr ) )
539 			aPgBrkSet.Put( *pAttr );
540 	}
541 
542 	rDestNd.ChgFmtColl( pDestDoc->CopyTxtColl( *GetTxtColl() ));
543     if( 0 != ( pSet = GetpSwAttrSet() ) )
544 		pSet->CopyToModify( rDestNd );
545 
546 	if( aPgBrkSet.Count() )
547         rDestNd.SetAttr( aPgBrkSet );
548 }
549 
550 
551 //  ----- Copy-Methode vom SwDoc ------
552 
553 	// verhinder das Kopieren in Fly's, die im Bereich verankert sind.
554 sal_Bool lcl_ChkFlyFly( SwDoc* pDoc, sal_uLong nSttNd, sal_uLong nEndNd,
555 						sal_uLong nInsNd )
556 {
557 	const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
558 
559 	for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
560 	{
561         SwFrmFmt const*const  pFmt = rFrmFmtTbl[n];
562         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
563         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
564         if (pAPos &&
565             ((FLY_AS_CHAR == pAnchor->GetAnchorId()) ||
566              (FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
567              (FLY_AT_FLY  == pAnchor->GetAnchorId()) ||
568              (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
569 			nSttNd <= pAPos->nNode.GetIndex() &&
570 			pAPos->nNode.GetIndex() < nEndNd )
571 		{
572 			const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
573 			SwStartNode* pSNd;
574 			if( !rCntnt.GetCntntIdx() ||
575 				0 == ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ))
576 				continue;
577 
578 			if( pSNd->GetIndex() < nInsNd &&
579 				nInsNd < pSNd->EndOfSectionIndex() )
580 				return sal_True;		// nicht kopieren !!
581 
582 			if( lcl_ChkFlyFly( pDoc, pSNd->GetIndex(),
583 						pSNd->EndOfSectionIndex(), nInsNd ) )
584 				return sal_True;		// nicht kopieren !!
585 		}
586 	}
587 
588 	return sal_False;
589 }
590 
591 void lcl_DeleteRedlines( const SwPaM& rPam, SwPaM& rCpyPam )
592 {
593 	const SwDoc* pSrcDoc = rPam.GetDoc();
594 	const SwRedlineTbl& rTbl = pSrcDoc->GetRedlineTbl();
595 	if( rTbl.Count() )
596 	{
597 		SwDoc* pDestDoc = rCpyPam.GetDoc();
598 		SwPosition* pCpyStt = rCpyPam.Start(), *pCpyEnd = rCpyPam.End();
599 		SwPaM* pDelPam = 0;
600 		const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
601         // We have to count the "non-copied" nodes
602         sal_uLong nDelCount = 0;
603         SwNodeIndex aCorrIdx( pStt->nNode );
604 
605 		sal_uInt16 n = 0;
606 		pSrcDoc->GetRedline( *pStt, &n );
607 		for( ; n < rTbl.Count(); ++n )
608 		{
609 			const SwRedline* pRedl = rTbl[ n ];
610 			if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() && pRedl->IsVisible() )
611 			{
612 				const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
613 
614 				SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
615 				switch( eCmpPos )
616 				{
617 				case POS_COLLIDE_END:
618 				case POS_BEFORE:				// Pos1 liegt vor Pos2
619 					break;
620 
621 				case POS_COLLIDE_START:
622 				case POS_BEHIND:				// Pos1 liegt hinter Pos2
623 					n = rTbl.Count();
624 					break;
625 
626 				default:
627 					{
628 						pDelPam = new SwPaM( *pCpyStt, pDelPam );
629 						if( *pStt < *pRStt )
630                         {
631                             lcl_NonCopyCount( rPam, aCorrIdx, pRStt->nNode.GetIndex(), nDelCount );
632 							lcl_SetCpyPos( *pRStt, *pStt, *pCpyStt,
633 											*pDelPam->GetPoint(), nDelCount );
634                         }
635 						pDelPam->SetMark();
636 
637 						if( *pEnd < *pREnd )
638 							*pDelPam->GetPoint() = *pCpyEnd;
639 						else
640                         {
641                             lcl_NonCopyCount( rPam, aCorrIdx, pREnd->nNode.GetIndex(), nDelCount );
642 							lcl_SetCpyPos( *pREnd, *pStt, *pCpyStt,
643 											*pDelPam->GetPoint(), nDelCount );
644                         }
645 					}
646 				}
647 			}
648 		}
649 
650 		if( pDelPam )
651 		{
652 			RedlineMode_t eOld = pDestDoc->GetRedlineMode();
653 			pDestDoc->SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
654 
655             ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
656 
657 			do {
658 				pDestDoc->DeleteAndJoin( *(SwPaM*)pDelPam->GetNext() );
659 				if( pDelPam->GetNext() == pDelPam )
660 					break;
661 				delete pDelPam->GetNext();
662 			} while( sal_True );
663 			delete pDelPam;
664 
665 			pDestDoc->SetRedlineMode_intern( eOld );
666 		}
667 	}
668 }
669 
670 void lcl_DeleteRedlines( const SwNodeRange& rRg, SwNodeRange& rCpyRg )
671 {
672 	SwDoc* pSrcDoc = rRg.aStart.GetNode().GetDoc();
673 	if( pSrcDoc->GetRedlineTbl().Count() )
674 	{
675 		SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
676 		SwPaM aCpyTmp( rCpyRg.aStart, rCpyRg.aEnd );
677 		lcl_DeleteRedlines( aRgTmp, aCpyTmp );
678 	}
679 }
680 
681 // Kopieren eines Bereiches im oder in ein anderes Dokument !
682 
683 bool
684 SwDoc::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
685 {
686 	const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
687 
688 	SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
689     bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
690 
691 	// kein Copy abfangen.
692 	if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) )
693         return false;
694 
695 	// verhinder das Kopieren in Fly's, die im Bereich verankert sind.
696 	if( pDoc == this )
697 	{
698 		// Start-/EndNode noch korrigieren
699 		sal_uLong nStt = pStt->nNode.GetIndex(),
700 				nEnd = pEnd->nNode.GetIndex(),
701 				nDiff = nEnd - nStt +1;
702 		SwNode* pNd = GetNodes()[ nStt ];
703 		if( pNd->IsCntntNode() && pStt->nContent.GetIndex() )
704 			++nStt, --nDiff;
705 		if( (pNd = GetNodes()[ nEnd ])->IsCntntNode() &&
706 			((SwCntntNode*)pNd)->Len() != pEnd->nContent.GetIndex() )
707 			--nEnd, --nDiff;
708 		if( nDiff &&
709 			lcl_ChkFlyFly( pDoc, nStt, nEnd, rPos.nNode.GetIndex() ) )
710         {
711             return false;
712         }
713 	}
714 
715 	SwPaM* pRedlineRange = 0;
716 	if( pDoc->IsRedlineOn() ||
717 		(!pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() ) )
718 		pRedlineRange = new SwPaM( rPos );
719 
720 	RedlineMode_t eOld = pDoc->GetRedlineMode();
721 
722     bool bRet = false;
723 
724 	if( pDoc != this )
725     {   // ordinary copy
726         bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
727     }
728 	// Copy in sich selbst (ueber mehrere Nodes wird hier gesondert
729 	// behandelt; in einem TextNode wird normal behandelt)
730 	else if( ! ( *pStt <= rPos && rPos < *pEnd &&
731 			( pStt->nNode != pEnd->nNode ||
732 			  !pStt->nNode.GetNode().IsTxtNode() )) )
733     {   // ordinary copy
734         bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
735     }
736 	else
737 	{
738 		ASSERT( this == pDoc, " falscher Copy-Zweig!" );
739         ASSERT(false, "mst: i thought this could be dead code;"
740                 "please tell me what you did to get here!");
741 		pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
742 
743 		// dann kopiere den Bereich im unteren DokumentBereich,
744 		// (mit Start/End-Nodes geklammert) und verschiebe diese
745 		// dann an die gewuenschte Stelle.
746 
747         SwUndoCpyDoc* pUndo = 0;
748 		SwPaM aPam( rPos );			// UndoBereich sichern
749         if (pDoc->GetIDocumentUndoRedo().DoesUndo())
750         {
751             pDoc->GetIDocumentUndoRedo().ClearRedo();
752 			pUndo = new SwUndoCpyDoc( aPam );
753 		}
754 
755         {
756             ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
757             SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection(
758                                 SwNodeIndex( GetNodes().GetEndOfAutotext() ));
759             aPam.GetPoint()->nNode = *pSttNd->EndOfSectionNode();
760             // copy without Frames
761             pDoc->CopyImpl( rPam, *aPam.GetPoint(), false, bCopyAll, 0 );
762 
763             aPam.GetPoint()->nNode = pDoc->GetNodes().GetEndOfAutotext();
764             aPam.SetMark();
765             SwCntntNode* pNode =
766                 pDoc->GetNodes().GoPrevious( &aPam.GetMark()->nNode );
767             pNode->MakeEndIndex( &aPam.GetMark()->nContent );
768 
769             aPam.GetPoint()->nNode = *aPam.GetNode()->StartOfSectionNode();
770             pNode = pDoc->GetNodes().GoNext( &aPam.GetPoint()->nNode );
771             pNode->MakeStartIndex( &aPam.GetPoint()->nContent );
772             // move to desired position
773             pDoc->MoveRange( aPam, rPos, DOC_MOVEDEFAULT );
774 
775             pNode = aPam.GetCntntNode();
776             *aPam.GetPoint() = rPos;        // Cursor umsetzen fuers Undo !
777             aPam.SetMark();                 // auch den Mark umsetzen !!
778             aPam.DeleteMark();              // aber keinen Bereich makieren !!
779             pDoc->DeleteSection( pNode );           // Bereich wieder loeschen
780         }
781 
782         // if Undo is enabled, store the insertion range
783         if (pDoc->GetIDocumentUndoRedo().DoesUndo())
784         {
785 			pUndo->SetInsertRange( aPam );
786             pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
787         }
788 
789 		if( pRedlineRange )
790 		{
791 			pRedlineRange->SetMark();
792 			*pRedlineRange->GetPoint() = *aPam.GetPoint();
793 			*pRedlineRange->GetMark() = *aPam.GetMark();
794 		}
795 
796 		pDoc->SetModified();
797         bRet = true;
798     }
799 
800 	pDoc->SetRedlineMode_intern( eOld );
801 	if( pRedlineRange )
802 	{
803 		if( pDoc->IsRedlineOn() )
804 			pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlineRange ), true);
805 		else
806 			pDoc->SplitRedline( *pRedlineRange );
807 		delete pRedlineRange;
808 	}
809 
810 	return bRet;
811 }
812 
813 // Kopieren eines Bereiches im oder in ein anderes Dokument !
814 // Die Position darf nicht im Bereich liegen !!
815 
816 bool lcl_MarksWholeNode(const SwPaM & rPam)
817 {
818     bool bResult = false;
819     const SwPosition* pStt = rPam.Start();
820     const SwPosition* pEnd = rPam.End();
821 
822     if (NULL != pStt && NULL != pEnd)
823     {
824         const SwTxtNode* pSttNd = pStt->nNode.GetNode().GetTxtNode();
825         const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
826 
827         if (NULL != pSttNd && NULL != pEndNd &&
828             pStt->nContent.GetIndex() == 0 &&
829             pEnd->nContent.GetIndex() == pEndNd->Len())
830         {
831             bResult = true;
832         }
833     }
834 
835     return bResult;
836 }
837 
838 // --> OD 2009-08-25 #i86492#
839 bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
840 {
841     bool bRet = false;
842 
843     const SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
844     const SwTxtNode* pEndTxtNd = rPam.End()->nNode.GetNode().GetTxtNode();
845     if ( pTxtNd && pTxtNd->IsInList() &&
846          pEndTxtNd && pEndTxtNd->IsInList() )
847     {
848         bRet = true;
849         SwNodeIndex aIdx(rPam.Start()->nNode);
850 
851         do
852         {
853             aIdx++;
854             pTxtNd = aIdx.GetNode().GetTxtNode();
855 
856             if ( !pTxtNd || !pTxtNd->IsInList() )
857             {
858                 bRet = false;
859                 break;
860             }
861         } while ( pTxtNd && pTxtNd != pEndTxtNd );
862     }
863 
864 
865     return bRet;
866 }
867 // <--
868 
869 bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
870         const bool bMakeNewFrms, const bool bCopyAll,
871         SwPaM *const pCpyRange ) const
872 {
873 	SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
874     const bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
875 
876     SwPosition* pStt = rPam.Start();
877     SwPosition* pEnd = rPam.End();
878 
879 	// kein Copy abfangen.
880 	if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) ||
881 		//JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
882 		//JP 15.11.2001: don't test inclusive the end, ever exclusive
883 		( pDoc == this && *pStt <= rPos && rPos < *pEnd ))
884     {
885         return false;
886     }
887 
888     const bool bEndEqualIns = pDoc == this && rPos == *pEnd;
889 
890 	// falls Undo eingeschaltet, erzeuge das UndoCopy-Objekt
891     SwUndoCpyDoc* pUndo = 0;
892 	SwPaM aCpyPam( rPos );
893 
894 	SwTblNumFmtMerge aTNFM( *this, *pDoc );
895 
896     if (pDoc->GetIDocumentUndoRedo().DoesUndo())
897     {
898         pUndo = new SwUndoCpyDoc( aCpyPam );
899         pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
900     }
901 
902 	RedlineMode_t eOld = pDoc->GetRedlineMode();
903 	pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
904 
905 
906 	// bewege den Pam von der Insert-Position ein zurueck, dadurch wird
907 	// die Position nicht "verschoben"
908 	aCpyPam.SetMark();
909 	sal_Bool bCanMoveBack = aCpyPam.Move( fnMoveBackward, fnGoCntnt );
910 	if( !bCanMoveBack )
911 		aCpyPam.GetPoint()->nNode--;
912 
913 	SwNodeRange aRg( pStt->nNode, pEnd->nNode );
914 	SwNodeIndex aInsPos( rPos.nNode );
915     const bool bOneNode = pStt->nNode == pEnd->nNode;
916     SwTxtNode* pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
917     SwTxtNode* pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
918     SwTxtNode* pDestTxtNd = aInsPos.GetNode().GetTxtNode();
919     bool bCopyCollFmt = !pDoc->IsInsOnlyTextGlossary() &&
920                         ( ( pDestTxtNd && !pDestTxtNd->GetTxt().Len() ) ||
921                           ( !bOneNode && !rPos.nContent.GetIndex() ) );
922     bool bCopyBookmarks = true;
923     sal_Bool bStartIsTxtNode = 0 != pSttTxtNd;
924 
925     // #i104585# copy outline num rule to clipboard (for ASCII filter)
926     if (pDoc->IsClipBoard() && GetOutlineNumRule())
927     {
928         pDoc->SetOutlineNumRule(*GetOutlineNumRule());
929     }
930 
931     // --> OD 2009-08-25 #i86492#
932     // Correct the search for a previous list:
933     // First search for non-outline numbering list. Then search for non-outline
934     // bullet list.
935     // Keep also the <ListId> value for possible propagation.
936     String aListIdToPropagate;
937     const SwNumRule* pNumRuleToPropagate =
938         pDoc->SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, true );
939     if ( !pNumRuleToPropagate )
940     {
941         pNumRuleToPropagate =
942             pDoc->SearchNumRule( rPos, false, false, false, 0, aListIdToPropagate, true );
943     }
944     // <--
945     // --> OD 2009-08-25 #i86492#
946     // Do not propagate previous found list, if
947     // - destination is an empty paragraph which is not in a list and
948     // - source contains at least one paragraph which is not in a list
949     if ( pNumRuleToPropagate &&
950          pDestTxtNd && !pDestTxtNd->GetTxt().Len() && !pDestTxtNd->IsInList() &&
951          !lcl_ContainsOnlyParagraphsInList( rPam ) )
952     {
953         pNumRuleToPropagate = 0;
954     }
955     // <--
956 
957 	// Block, damit aus diesem gesprungen werden kann !!
958 	do {
959         if( pSttTxtNd )
960 		{
961 			// den Anfang nicht komplett kopieren ?
962 			if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
963 			{
964 				SwIndex aDestIdx( rPos.nContent );
965 				sal_Bool bCopyOk = sal_False;
966                 if( !pDestTxtNd )
967 				{
968 					if( pStt->nContent.GetIndex() || bOneNode )
969                         pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
970 							pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
971 					else
972 					{
973                         pDestTxtNd = static_cast<SwTxtNode*>(pSttTxtNd->MakeCopy( pDoc, aInsPos ));
974 						bCopyOk = sal_True;
975 					}
976                     aDestIdx.Assign( pDestTxtNd, 0 );
977                     bCopyCollFmt = true;
978 				}
979 				else if( !bOneNode || bColumnSel )
980 				{
981 					xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
982                     {
983                         ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
984                         pDoc->SplitNode( rPos, false );
985                     }
986 
987 					if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
988 					{
989 						// nach dem SplitNode, den CpyPam wieder richtig aufspannen
990 						aCpyPam.Move( fnMoveBackward, fnGoCntnt );
991 						aCpyPam.Move( fnMoveBackward, fnGoCntnt );
992 					}
993 
994                     pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
995                     aDestIdx.Assign( pDestTxtNd, pDestTxtNd->GetTxt().Len() );
996 
997 					// korrigiere den Bereich wieder !!
998 					if( bEndEqualIns )
999 					{
1000 						sal_Bool bChg = pEnd != rPam.GetPoint();
1001 						if( bChg )
1002 							rPam.Exchange();
1003 						rPam.Move( fnMoveBackward, fnGoCntnt );
1004 						if( bChg )
1005 							rPam.Exchange();
1006 
1007 						aRg.aEnd = pEnd->nNode;
1008                         pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
1009 					}
1010 					else if( rPos == *pEnd )		// Wurde das Ende auch verschoben
1011 					{
1012 						pEnd->nNode--;
1013                         pEnd->nContent.Assign( pDestTxtNd, nCntntEnd );
1014 						aRg.aEnd = pEnd->nNode;
1015                         pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
1016 					}
1017 				}
1018 
1019 				/* #107213#: Safe numrule item at destination. */
1020                 // --> OD 2009-08-25 #i86492#
1021                 // Safe also <ListId> item of destination.
1022                 int aNumRuleState = SFX_ITEM_UNKNOWN;
1023 				SwNumRuleItem aNumRuleItem;
1024                 int aListIdState = SFX_ITEM_UNKNOWN;
1025                 SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
1026                 {
1027                     const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
1028                     if (pAttrSet != NULL)
1029                     {
1030                         const SfxPoolItem * pItem = NULL;
1031                         aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
1032                         if (SFX_ITEM_SET == aNumRuleState)
1033                             aNumRuleItem = *((SwNumRuleItem *) pItem);
1034 
1035                         aListIdState =
1036                             pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
1037                         if (SFX_ITEM_SET == aListIdState)
1038                         {
1039                             aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1040                         }
1041                     }
1042                 }
1043                 // <--
1044 				/* #107213# */
1045 
1046 				if( !bCopyOk )
1047 				{
1048                     const xub_StrLen nCpyLen = ( (bOneNode)
1049                                            ? pEnd->nContent.GetIndex()
1050                                            : pSttTxtNd->GetTxt().Len() )
1051                                          - pStt->nContent.GetIndex();
1052                     pSttTxtNd->CopyText( pDestTxtNd, aDestIdx,
1053                                             pStt->nContent, nCpyLen );
1054 					if( bEndEqualIns )
1055 						pEnd->nContent -= nCpyLen;
1056 				}
1057 
1058 				if( bOneNode )
1059 				{
1060 					if( bCopyCollFmt )
1061 					{
1062                         pSttTxtNd->CopyCollFmt( *pDestTxtNd );
1063 
1064                         /* #107213# If only a part of one paragraph is copied
1065                            restore the numrule at the destination. */
1066                         // --> OD 2009-08-25 #i86492#
1067                         // restore also <ListId> item
1068                         if ( !lcl_MarksWholeNode(rPam) )
1069                         {
1070                             if (SFX_ITEM_SET == aNumRuleState)
1071                             {
1072                                 pDestTxtNd->SetAttr(aNumRuleItem);
1073                             }
1074                             else
1075                             {
1076                                 pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1077                             }
1078                             if (SFX_ITEM_SET == aListIdState)
1079                             {
1080                                 pDestTxtNd->SetAttr(aListIdItem);
1081                             }
1082                             else
1083                             {
1084                                 pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1085                             }
1086                         }
1087                     }
1088 
1089 					break;
1090 				}
1091 
1092 				aRg.aStart++;
1093 			}
1094 		}
1095         else if( pDestTxtNd )
1096 		{
1097             // Problems with insertion of table selections into "normal" text solved.
1098             // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
1099             // the undo operation will try to merge this node after removing the table.
1100             // If we didn't split a textnode, the PaM should start at the inserted table node
1101             if( rPos.nContent.GetIndex() == pDestTxtNd->Len() )
1102 			{    // Insertion at the last position of a textnode (empty or not)
1103 				aInsPos++; // The table will be inserted behind the text node
1104 			}
1105 			else if( rPos.nContent.GetIndex() )
1106 			{   // Insertion in the middle of a text node, it has to be split
1107                 // (and joined from undo)
1108                 bStartIsTxtNode = sal_True;
1109 				// splitte den TextNode, bei dem Eingefuegt wird.
1110 
1111 				xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
1112                 {
1113                     ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
1114                     pDoc->SplitNode( rPos, false );
1115                 }
1116 
1117 				if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
1118 				{
1119 					// nach dem SplitNode, den CpyPam wieder richtig aufspannen
1120 					aCpyPam.Move( fnMoveBackward, fnGoCntnt );
1121 					aCpyPam.Move( fnMoveBackward, fnGoCntnt );
1122 				}
1123 
1124 				// korrigiere den Bereich wieder !!
1125 				if( bEndEqualIns )
1126 					aRg.aEnd--;
1127 				else if( rPos == *pEnd )		// Wurde das Ende auch verschoben
1128 				{
1129 					rPos.nNode-=2;
1130 					rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1131 											nCntntEnd );
1132 					rPos.nNode++;
1133 					aRg.aEnd--;
1134 				}
1135 			}
1136             else if( bCanMoveBack )
1137             {   //Insertion at the first position of a text node. It will not be splitted, the table
1138                 // will be inserted before the text node.
1139                 // See below, before the SetInsertRange funciton of the undo object will be called,
1140                 // the CpyPam would be moved to the next content position. This has to be avoided
1141                 // We want to be moved to the table node itself thus we have to set bCanMoveBack
1142                 // and to manipulate aCpyPam.
1143                 bCanMoveBack = false;
1144                 aCpyPam.GetPoint()->nNode--;
1145             }
1146 		}
1147 
1148         pDestTxtNd = aInsPos.GetNode().GetTxtNode();
1149         if( pEndTxtNd )
1150 		{
1151 			SwIndex aDestIdx( rPos.nContent );
1152             if( !pDestTxtNd )
1153 			{
1154                 pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
1155 							pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
1156                 aDestIdx.Assign( pDestTxtNd, 0  );
1157 				aInsPos--;
1158 
1159                 // #112756# #98130# if we have to insert an extra text node
1160                 // at the destination, this node will be our new destination
1161                 // (text) node, and thus we set bStartisTxtNode to true. This
1162                 // will ensure that this node will be deleted during Undo
1163                 // using JoinNext.
1164                 DBG_ASSERT( !bStartIsTxtNode, "Oops, undo may be instable now." );
1165                 bStartIsTxtNode = sal_True;
1166 			}
1167 
1168 			/* #107213# Save numrule at destination */
1169             // --> OD 2009-08-25 #i86492#
1170             // Safe also <ListId> item of destination.
1171             int aNumRuleState = SFX_ITEM_UNKNOWN;
1172             SwNumRuleItem aNumRuleItem;
1173             int aListIdState = SFX_ITEM_UNKNOWN;
1174             SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
1175             {
1176                 const SfxItemSet* pAttrSet = pDestTxtNd->GetpSwAttrSet();
1177                 if (pAttrSet != NULL)
1178                 {
1179                     const SfxPoolItem * pItem = NULL;
1180 
1181                     aNumRuleState =
1182                         pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
1183                     if (SFX_ITEM_SET == aNumRuleState)
1184                         aNumRuleItem = *((SwNumRuleItem *) pItem);
1185 
1186                     aListIdState =
1187                         pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
1188                     if (SFX_ITEM_SET == aListIdState)
1189                         aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1190                 }
1191             }
1192             // <--
1193 			/* #107213# */
1194 
1195             const bool bEmptyDestNd = 0 == pDestTxtNd->GetTxt().Len();
1196             pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
1197 							pEnd->nContent.GetIndex() );
1198 
1199 			// auch alle FormatVorlagen kopieren
1200 			if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
1201 			{
1202                 pEndTxtNd->CopyCollFmt( *pDestTxtNd );
1203 
1204                 if ( bOneNode )
1205 				{
1206 					/* #107213# If only a part of one paragraph is copied
1207                        restore the numrule at the destination. */
1208                     // --> OD 2009-08-25 #i86492#
1209                     // restore also <ListId> item
1210                     if ( !lcl_MarksWholeNode(rPam) )
1211                     {
1212                         if (SFX_ITEM_SET == aNumRuleState)
1213                         {
1214                             pDestTxtNd->SetAttr(aNumRuleItem);
1215                         }
1216                         else
1217                         {
1218                             pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1219                         }
1220                         if (SFX_ITEM_SET == aListIdState)
1221                         {
1222                             pDestTxtNd->SetAttr(aListIdItem);
1223                         }
1224                         else
1225                         {
1226                             pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1227                         }
1228                     }
1229 				}
1230 			}
1231 		}
1232 
1233 		if( bCopyAll || aRg.aStart != aRg.aEnd )
1234 		{
1235 			SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
1236             if( pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
1237 			{
1238                 aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
1239 				if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_BREAK, sal_False ) )
1240                     pDestTxtNd->ResetAttr( RES_BREAK );
1241 				if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_PAGEDESC, sal_False ) )
1242                     pDestTxtNd->ResetAttr( RES_PAGEDESC );
1243 			}
1244 
1245 			if( aInsPos == pEnd->nNode )
1246 			{
1247 				SwNodeIndex aSaveIdx( aInsPos, -1 );
1248                 CopyWithFlyInFly( aRg, 0,aInsPos, bMakeNewFrms, sal_False );
1249 				aSaveIdx++;
1250 				pEnd->nNode = aSaveIdx;
1251 				pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
1252 			}
1253 			else
1254                 CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, bMakeNewFrms, sal_False );
1255 
1256             bCopyBookmarks = false;
1257 
1258 			// harte Umbrueche wieder in den ersten Node setzen
1259             if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
1260 					aCpyPam.GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode() ) )
1261 			{
1262                 pDestTxtNd->SetAttr( aBrkSet );
1263 			}
1264 		}
1265 	} while( sal_False );
1266 
1267 	// Position ummelden ( falls verschoben / im anderen Node )
1268 	rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1269 							rPos.nContent.GetIndex() );
1270 
1271 	if( rPos.nNode != aInsPos )
1272 	{
1273 		aCpyPam.GetMark()->nNode = aInsPos;
1274 		aCpyPam.GetMark()->nContent.Assign( aCpyPam.GetCntntNode(sal_False), 0 );
1275 		rPos = *aCpyPam.GetMark();
1276 	}
1277 	else
1278 		*aCpyPam.GetMark() = rPos;
1279 
1280 	aCpyPam.Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
1281 	aCpyPam.Exchange();
1282 
1283 	// dann kopiere noch alle Bookmarks
1284     if( bCopyBookmarks && getIDocumentMarkAccess()->getMarksCount() )
1285 		lcl_CopyBookmarks( rPam, aCpyPam );
1286 
1287 	if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
1288 		lcl_DeleteRedlines( rPam, aCpyPam );
1289 
1290 	// falls Undo eingeschaltet ist, so speicher den eingefuegten Bereich
1291     if (pDoc->GetIDocumentUndoRedo().DoesUndo())
1292     {
1293 		pUndo->SetInsertRange( aCpyPam, sal_True, bStartIsTxtNode );
1294     }
1295 
1296 	if( pCpyRange )
1297 	{
1298 		pCpyRange->SetMark();
1299 		*pCpyRange->GetPoint() = *aCpyPam.GetPoint();
1300 		*pCpyRange->GetMark() = *aCpyPam.GetMark();
1301 	}
1302 
1303     if ( pNumRuleToPropagate )
1304     {
1305         // --> OD 2009-08-25 #i86492#
1306         // use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
1307 //        pDoc->ReplaceNumRule(aCpyPam, *pNumRuleToPropagate);
1308         pDoc->SetNumRule( aCpyPam, *pNumRuleToPropagate, false,
1309                           aListIdToPropagate, sal_True, true );
1310     }
1311 
1312 	pDoc->SetRedlineMode_intern( eOld );
1313 	pDoc->SetModified();
1314 
1315     return true;
1316 }
1317 
1318 
1319 //  ----- Copy-Methode vom SwDoc - "kopiere Fly's in Fly's" ------
1320 
1321 void SwDoc::CopyWithFlyInFly( const SwNodeRange& rRg, const xub_StrLen nEndContentIndex,
1322 							const SwNodeIndex& rInsPos, sal_Bool bMakeNewFrms,
1323 							sal_Bool bDelRedlines, sal_Bool bCopyFlyAtFly ) const
1324 {
1325 	SwDoc* pDest = rInsPos.GetNode().GetDoc();
1326 
1327 	_SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
1328 
1329 	SwNodeIndex aSavePos( rInsPos, -1 );
1330 	sal_Bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
1331 	GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, sal_True );
1332 	aSavePos++;
1333 	if( bEndIsEqualEndPos )
1334 		((SwNodeIndex&)rRg.aEnd) = aSavePos;
1335 
1336 	aRedlRest.Restore();
1337 
1338 #ifdef DBG_UTIL
1339 	{
1340 		//JP 17.06.99: Bug 66973 - check count only if the selection is in
1341 		//				the same (or no) section. Becaus not full selected
1342 		//				section are not copied.
1343 		const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
1344 		SwNodeIndex aTmpI( rRg.aEnd, -1 );
1345 		const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
1346 		if( pSSectNd == pESectNd &&
1347 			!rRg.aStart.GetNode().IsSectionNode() &&
1348 			!aTmpI.GetNode().IsEndNode() )
1349 		{
1350 			ASSERT( rInsPos.GetIndex() - aSavePos.GetIndex() ==
1351 					rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
1352 					"Es wurden zu wenig Nodes kopiert!" )
1353 		}
1354 	}
1355 #endif
1356 
1357     {
1358         ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
1359         CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
1360     }
1361 
1362 	SwNodeRange aCpyRange( aSavePos, rInsPos );
1363 
1364 	// dann kopiere noch alle Bookmarks
1365     if( getIDocumentMarkAccess()->getMarksCount() )
1366 	{
1367 		SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
1368 		SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
1369 
1370 		lcl_CopyBookmarks( aRgTmp, aCpyTmp );
1371 	}
1372 
1373 	if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->GetRedlineMode() ))
1374 		lcl_DeleteRedlines( rRg, aCpyRange );
1375 
1376 	pDest->GetNodes()._DelDummyNodes( aCpyRange );
1377 }
1378 
1379 void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
1380 {
1381 	SwFmtChain aSrc( pSrc->GetChain() );
1382 	if ( !aSrc.GetNext() )
1383 	{
1384 		aSrc.SetNext( pDest );
1385         pSrc->SetFmtAttr( aSrc );
1386 	}
1387 	SwFmtChain aDest( pDest->GetChain() );
1388 	if ( !aDest.GetPrev() )
1389 	{
1390 		aDest.SetPrev( pSrc );
1391         pDest->SetFmtAttr( aDest );
1392 	}
1393 }
1394 
1395 void SwDoc::CopyFlyInFlyImpl( const SwNodeRange& rRg,
1396         const xub_StrLen nEndContentIndex, const SwNodeIndex& rStartIdx,
1397         const bool bCopyFlyAtFly ) const
1398 {
1399 	// Bug 22727: suche erst mal alle Flys zusammen, sortiere sie entsprechend
1400 	//			  ihrer Ordnungsnummer und kopiere sie erst dann. Damit wird
1401 	//			  die Ordnungsnummer (wird nur im DrawModel verwaltet)
1402 	//			  beibehalten.
1403     SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
1404 	_ZSortFlys aArr;
1405 	sal_uInt16 nArrLen = GetSpzFrmFmts()->Count();
1406 
1407     for ( sal_uInt16 n = 0; n < nArrLen; ++n )
1408     {
1409         SwFrmFmt const*const pFmt = (*GetSpzFrmFmts())[n];
1410         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
1411         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
1412         bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
1413         if ( pAPos &&
1414              ( bAtCntnt ||
1415               (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
1416               (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
1417 			 (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
1418 					? rRg.aStart <= pAPos->nNode.GetIndex() + 1
1419 					: ( IsRedlineMove()
1420 							? rRg.aStart < pAPos->nNode
1421 							: rRg.aStart <= pAPos->nNode )) &&
1422 			 pAPos->nNode <= rRg.aEnd )
1423 		{
1424 			//frames at the last source node are not always copied:
1425             //- if the node is empty and is the last node of the document or a table cell
1426             //  or a text frame then tey have to be copied
1427             //- if the content index in this node is > 0 then paragph and frame bound objects are copied
1428             //- to-character bound objects are copied if their index is <= nEndContentIndex
1429             bool bAdd = false;
1430             if( pAPos->nNode < rRg.aEnd )
1431                 bAdd = true;
1432             if( !bAdd )
1433             {
1434                 bool bEmptyNode = false;
1435                 bool bLastNode = false;
1436                 // is the node empty?
1437                 const SwNodes& rNodes = pAPos->nNode.GetNodes();
1438                 SwTxtNode* pTxtNode;
1439                 if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
1440                 {
1441                     bEmptyNode = !pTxtNode->GetTxt().Len();
1442                     if( bEmptyNode )
1443                     {
1444                         //last node information is only necessary to know for the last TextNode
1445                         SwNodeIndex aTmp( pAPos->nNode );
1446                         ++aTmp;//goto next node
1447                         while (aTmp.GetNode().IsEndNode())
1448                         {
1449                             if( aTmp == rNodes.GetEndOfContent().GetIndex() )
1450                             {
1451                                 bLastNode = true;
1452                                 break;
1453                             }
1454                             ++aTmp;
1455                         }
1456                     }
1457                 }
1458                 bAdd = bLastNode && bEmptyNode;
1459                 if( !bAdd )
1460                 {
1461                     if( bAtCntnt )
1462                         bAdd = nEndContentIndex > 0;
1463                     else
1464                         bAdd = pAPos->nContent <= nEndContentIndex;
1465                 }
1466             }
1467             if( bAdd )
1468                 aArr.Insert( _ZSortFly( pFmt, pAnchor, nArrLen + aArr.Count() ));
1469 		}
1470 	}
1471 
1472 	//Alle kopierten (also die neu erzeugten) Rahmen in ein weiteres Array
1473 	//stopfen. Dort sizten sie passend zu den Originalen, damit hinterher
1474 	//die Chains entsprechend aufgebaut werden koennen.
1475 	SvPtrarr aNewArr( 10, 10 );
1476 
1477     for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
1478     {
1479 		const _ZSortFly& rZSortFly = aArr[ n ];
1480 
1481         // --> OD 2006-01-04 #i59964#
1482         // correct determination of new anchor position
1483         SwFmtAnchor aAnchor( *rZSortFly.GetAnchor() );
1484         SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
1485         // for at-paragraph and at-character anchored objects the new anchor
1486         // position can *not* be determined by the difference of the current
1487         // anchor position to the start of the copied range, because not
1488         // complete selected sections in the copied range aren't copied - see
1489         // method <SwNodes::_CopyNodes(..)>.
1490         // Thus, the new anchor position in the destination document is found
1491         // by counting the text nodes.
1492         if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
1493             (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
1494         {
1495             // First, determine number of anchor text node in the copied range.
1496             // Note: The anchor text node *have* to be inside the copied range.
1497             sal_uLong nAnchorTxtNdNumInRange( 0L );
1498             bool bAnchorTxtNdFound( false );
1499             SwNodeIndex aIdx( rRg.aStart );
1500             while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
1501             {
1502                 if ( aIdx.GetNode().IsTxtNode() )
1503                 {
1504                     ++nAnchorTxtNdNumInRange;
1505                     bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
1506                 }
1507 
1508                 ++aIdx;
1509             }
1510             if ( !bAnchorTxtNdFound )
1511             {
1512                 // This case can *not* happen, but to be robust take the first
1513                 // text node in the destination document.
1514                 ASSERT( false,
1515                         "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
1516                 nAnchorTxtNdNumInRange = 1;
1517             }
1518             // Second, search corresponding text node in destination document
1519             // by counting forward from start insert position <rStartIdx> the
1520             // determined number of text nodes.
1521             aIdx = rStartIdx;
1522             SwNodeIndex aAnchorNdIdx( rStartIdx );
1523             const SwNode& aEndOfContentNd =
1524                                     aIdx.GetNode().GetNodes().GetEndOfContent();
1525             while ( nAnchorTxtNdNumInRange > 0 &&
1526                     &(aIdx.GetNode()) != &aEndOfContentNd )
1527             {
1528                 if ( aIdx.GetNode().IsTxtNode() )
1529                 {
1530                     --nAnchorTxtNdNumInRange;
1531                     aAnchorNdIdx = aIdx;
1532                 }
1533 
1534                 ++aIdx;
1535             }
1536             if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1537             {
1538                 // This case can *not* happen, but to be robust take the first
1539                 // text node in the destination document.
1540                 ASSERT( false,
1541                         "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
1542                 aAnchorNdIdx = rStartIdx;
1543                 while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1544                 {
1545                     ++aAnchorNdIdx;
1546                 }
1547             }
1548             // apply found anchor text node as new anchor position
1549             pNewPos->nNode = aAnchorNdIdx;
1550         }
1551         else
1552         {
1553             long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
1554             SwNodeIndex aIdx( rStartIdx, nOffset );
1555             pNewPos->nNode = aIdx;
1556         }
1557         // <--
1558 		// die am Zeichen Flys wieder ans das vorgegebene Zeichen setzen
1559         if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
1560              pNewPos->nNode.GetNode().IsTxtNode() )
1561         {
1562             pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
1563 										pNewPos->nContent.GetIndex() );
1564         }
1565 		else
1566         {
1567 			pNewPos->nContent.Assign( 0, 0 );
1568         }
1569 
1570 		// ueberpruefe Rekursion: Inhalt in "seinen eigenen" Frame
1571 		// kopieren. Dann nicht kopieren
1572 		sal_Bool bMakeCpy = sal_True;
1573 		if( pDest == this )
1574 		{
1575 			const SwFmtCntnt& rCntnt = rZSortFly.GetFmt()->GetCntnt();
1576 			const SwStartNode* pSNd;
1577 			if( rCntnt.GetCntntIdx() &&
1578 				0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
1579                 pSNd->GetIndex() < rStartIdx.GetIndex() &&
1580                 rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
1581 			{
1582 				bMakeCpy = sal_False;
1583 				aArr.Remove( n, 1 );
1584 				--n;
1585 			}
1586 		}
1587 
1588 		// Format kopieren und den neuen Anker setzen
1589 		if( bMakeCpy )
1590 			aNewArr.Insert( pDest->CopyLayoutFmt( *rZSortFly.GetFmt(),
1591                         aAnchor, false, true ), aNewArr.Count() );
1592 	}
1593 
1594 	//Alle chains, die im Original vorhanden sind, soweit wie moeglich wieder
1595 	//aufbauen.
1596 	ASSERT( aArr.Count() == aNewArr.Count(), "Missing new Flys" );
1597 	if ( aArr.Count() == aNewArr.Count() )
1598 	{
1599         for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
1600 		{
1601 			const SwFrmFmt *pFmt = aArr[n].GetFmt();
1602 			const SwFmtChain &rChain = pFmt->GetChain();
1603 			int nCnt = 0 != rChain.GetPrev();
1604 			nCnt += rChain.GetNext() ? 1: 0;
1605 			for ( sal_uInt16 k = 0; nCnt && k < aArr.Count(); ++k )
1606 			{
1607 				const _ZSortFly &rTmp = aArr[k];
1608 				const SwFrmFmt *pTmp = rTmp.GetFmt();
1609 				if ( rChain.GetPrev() == pTmp )
1610 				{
1611 					::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[k],
1612 									 (SwFlyFrmFmt*)aNewArr[n] );
1613 					--nCnt;
1614 				}
1615 				else if ( rChain.GetNext() == pTmp )
1616 				{
1617 					::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[n],
1618 									 (SwFlyFrmFmt*)aNewArr[k] );
1619 					--nCnt;
1620 				}
1621 			}
1622 		}
1623 	}
1624 }
1625 
1626 
1627 
1628 
1629