xref: /trunk/main/sw/source/core/docnode/ndcopy.cxx (revision efeef26f)
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 		SwNodeIndex aNewIdx( *pCT->pTblNd,
358 							rpBox->GetSttIdx() - pCT->nOldTblSttIdx );
359 		ASSERT( aNewIdx.GetNode().IsStartNode(), "Index nicht auf einem StartNode" );
360 		pNewBox = new SwTableBox( pBoxFmt, aNewIdx, pCT->pInsLine );
361         pNewBox->setRowSpan( rpBox->getRowSpan() );
362 	}
363 
364 	pCT->pInsLine->GetTabBoxes().C40_INSERT( SwTableBox, pNewBox,
365 					pCT->pInsLine->GetTabBoxes().Count() );
366 
367 	if( nLines )
368 	{
369 		_CopyTable aPara( *pCT );
370 		aPara.pInsBox = pNewBox;
371 		((SwTableBox*)rpBox)->GetTabLines().ForEach( &lcl_CopyTblLine, &aPara );
372 	}
373 	else if( pNewBox->IsInHeadline( &pCT->pTblNd->GetTable() ))
374 		// in der HeadLine sind die Absaetze mit BedingtenVorlage anzupassen
375 		pNewBox->GetSttNd()->CheckSectionCondColl();
376 	return sal_True;
377 }
378 
379 sal_Bool lcl_CopyTblLine( const SwTableLine*& rpLine, void* pPara )
380 {
381 	_CopyTable* pCT = (_CopyTable*)pPara;
382 	SwTableLineFmt* pLineFmt = (SwTableLineFmt*)rpLine->GetFrmFmt();
383 	pCT->rMapArr.ForEach( lcl_SrchNew, &pLineFmt );
384 	if( pLineFmt == rpLine->GetFrmFmt() )	// ein neues anlegen ??
385 	{
386 		pLineFmt = pCT->pDoc->MakeTableLineFmt();
387 		pLineFmt->CopyAttrs( *rpLine->GetFrmFmt() );
388 		pCT->rMapArr.Insert( _MapTblFrmFmt( rpLine->GetFrmFmt(), pLineFmt ),
389 								pCT->rMapArr.Count());
390 	}
391 	SwTableLine* pNewLine = new SwTableLine( pLineFmt,
392 							rpLine->GetTabBoxes().Count(), pCT->pInsBox );
393 	// die neue Zeile in die Tabelle eintragen
394 	if( pCT->pInsBox )
395 	{
396 		pCT->pInsBox->GetTabLines().C40_INSERT( SwTableLine, pNewLine,
397 				pCT->pInsBox->GetTabLines().Count() );
398 	}
399 	else
400 	{
401 		pCT->pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pNewLine,
402 				pCT->pTblNd->GetTable().GetTabLines().Count() );
403 	}
404 	pCT->pInsLine = pNewLine;
405 	((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &lcl_CopyTblBox, pCT );
406 	return sal_True;
407 }
408 
409 SwTableNode* SwTableNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
410 {
411 	// in welchen Array steht ich denn Nodes, UndoNodes ??
412 	SwNodes& rNds = (SwNodes&)GetNodes();
413 
414 	{
415 		// nicht in Fussnoten kopieren !!
416 /*
417 !! Mal ohne Frames
418 		SwCntntNode* pCNd = pDoc->GetNodes()[ rIdx ]->GetCntntNode();
419 		SwFrm* pFrm;
420 		if( (pCNd && 0 != ( pFrm = pCNd->GetFrm()))
421 				? pFrm->FindFtnFrm()
422 				: rIdx < pDoc->GetNodes().EndOfInserts &&
423 					pDoc->GetNodes()[pDoc->GetNodes().EndOfInserts]->StartOfSection()
424 					< rIdx )
425 */
426 		if( rIdx < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
427 			rIdx >= pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
428 			return 0;
429 	}
430 
431 	// das TableFrmFmt kopieren
432 	String sTblName( GetTable().GetFrmFmt()->GetName() );
433 	if( !pDoc->IsCopyIsMove() )
434 	{
435 		const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
436 		for( sal_uInt16 n = rTblFmts.Count(); n; )
437 			if( rTblFmts[ --n ]->GetName() == sTblName )
438 			{
439 				sTblName = pDoc->GetUniqueTblName();
440 				break;
441 			}
442 	}
443 
444 	SwFrmFmt* pTblFmt = pDoc->MakeTblFrmFmt( sTblName, pDoc->GetDfltFrmFmt() );
445 	pTblFmt->CopyAttrs( *GetTable().GetFrmFmt() );
446 	SwTableNode* pTblNd = new SwTableNode( rIdx );
447 	SwEndNode* pEndNd = new SwEndNode( rIdx, *pTblNd );
448 	SwNodeIndex aInsPos( *pEndNd );
449 
450 	SwTable& rTbl = (SwTable&)pTblNd->GetTable();
451     rTbl.RegisterToFormat( *pTblFmt );
452 
453     rTbl.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
454 	rTbl.SetTblChgMode( GetTable().GetTblChgMode() );
455 	rTbl.SetTableModel( GetTable().IsNewModel() );
456 
457 	SwDDEFieldType* pDDEType = 0;
458 	if( IS_TYPE( SwDDETable, &GetTable() ))
459 	{
460 		// es wird eine DDE-Tabelle kopiert
461 		// ist im neuen Dokument ueberhaupt der FeldTyp vorhanden ?
462 		pDDEType = ((SwDDETable&)GetTable()).GetDDEFldType();
463 		if( pDDEType->IsDeleted() )
464 			pDoc->InsDeletedFldType( *pDDEType );
465 		else
466 			pDDEType = (SwDDEFieldType*)pDoc->InsertFldType( *pDDEType );
467 		ASSERT( pDDEType, "unbekannter FieldType" );
468 
469 		// tauschen am Node den Tabellen-Pointer aus
470 		SwDDETable* pNewTable = new SwDDETable( pTblNd->GetTable(), pDDEType );
471 		pTblNd->SetNewTable( pNewTable, sal_False );
472 	}
473 	// dann kopiere erstmal den Inhalt der Tabelle, die Zuordnung der
474 	// Boxen/Lines und das anlegen der Frames erfolgt spaeter
475 	SwNodeRange aRg( *this, +1, *EndOfSectionNode() );	// (wo stehe in denn nun ??)
476 
477     // If there is a table in this table, the table format for the outer table
478     // does not seem to be used, because the table does not have any contents yet
479     // (see IsUsed). Therefore the inner table gets the same name as the outer table.
480     // We have to make sure that the table node of the SwTable is accessible, even
481     // without any content in aSortCntBoxes. #i26629#
482     pTblNd->GetTable().SetTableNode( pTblNd );
483     rNds._Copy( aRg, aInsPos, sal_False );
484     pTblNd->GetTable().SetTableNode( 0 );
485 
486 	// Sonderbehandlung fuer eine einzelne Box
487 	if( 1 == GetTable().GetTabSortBoxes().Count() )
488 	{
489 		aRg.aStart.Assign( *pTblNd, 1 );
490 		aRg.aEnd.Assign( *pTblNd->EndOfSectionNode() );
491 		pDoc->GetNodes().SectionDown( &aRg, SwTableBoxStartNode );
492 	}
493 
494 	// loesche alle Frames vom kopierten Bereich, diese werden beim
495 	// erzeugen des TableFrames angelegt !
496 	pTblNd->DelFrms();
497 
498 	_MapTblFrmFmts aMapArr;
499 	_CopyTable aPara( pDoc, aMapArr, GetIndex(), *pTblNd, &GetTable() );
500 
501 	((SwTable&)GetTable()).GetTabLines().ForEach( &lcl_CopyTblLine, &aPara );
502 
503     if( pDDEType )
504 		pDDEType->IncRefCnt();
505 
506     CHECK_TABLE( GetTable() );
507 	return pTblNd;
508 }
509 
510 void SwTxtNode::CopyCollFmt( SwTxtNode& rDestNd )
511 {
512 	// kopiere die Formate in das andere Dokument:
513 
514 	// Sonderbehandlung fuer PageBreak/PageDesc/ColBrk
515 	SwDoc* pDestDoc = rDestNd.GetDoc();
516 	SwAttrSet aPgBrkSet( pDestDoc->GetAttrPool(), aBreakSetRange );
517     const SwAttrSet* pSet;
518 
519     if( 0 != ( pSet = rDestNd.GetpSwAttrSet() ) )
520 	{
521 		// Sonderbehandlung fuer unsere Break-Attribute
522 		const SfxPoolItem* pAttr;
523 		if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pAttr ) )
524 			aPgBrkSet.Put( *pAttr );
525 
526 		if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, sal_False, &pAttr ) )
527 			aPgBrkSet.Put( *pAttr );
528 	}
529 
530 	rDestNd.ChgFmtColl( pDestDoc->CopyTxtColl( *GetTxtColl() ));
531     if( 0 != ( pSet = GetpSwAttrSet() ) )
532 		pSet->CopyToModify( rDestNd );
533 
534 	if( aPgBrkSet.Count() )
535         rDestNd.SetAttr( aPgBrkSet );
536 }
537 
538 
539 //  ----- Copy-Methode vom SwDoc ------
540 
541 	// verhinder das Kopieren in Fly's, die im Bereich verankert sind.
542 sal_Bool lcl_ChkFlyFly( SwDoc* pDoc, sal_uLong nSttNd, sal_uLong nEndNd,
543 						sal_uLong nInsNd )
544 {
545 	const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
546 
547 	for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
548 	{
549         SwFrmFmt const*const  pFmt = rFrmFmtTbl[n];
550         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
551         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
552         if (pAPos &&
553             ((FLY_AS_CHAR == pAnchor->GetAnchorId()) ||
554              (FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
555              (FLY_AT_FLY  == pAnchor->GetAnchorId()) ||
556              (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
557 			nSttNd <= pAPos->nNode.GetIndex() &&
558 			pAPos->nNode.GetIndex() < nEndNd )
559 		{
560 			const SwFmtCntnt& rCntnt = pFmt->GetCntnt();
561 			SwStartNode* pSNd;
562 			if( !rCntnt.GetCntntIdx() ||
563 				0 == ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ))
564 				continue;
565 
566 			if( pSNd->GetIndex() < nInsNd &&
567 				nInsNd < pSNd->EndOfSectionIndex() )
568 				return sal_True;		// nicht kopieren !!
569 
570 			if( lcl_ChkFlyFly( pDoc, pSNd->GetIndex(),
571 						pSNd->EndOfSectionIndex(), nInsNd ) )
572 				return sal_True;		// nicht kopieren !!
573 		}
574 	}
575 
576 	return sal_False;
577 }
578 
579 void lcl_DeleteRedlines( const SwPaM& rPam, SwPaM& rCpyPam )
580 {
581 	const SwDoc* pSrcDoc = rPam.GetDoc();
582 	const SwRedlineTbl& rTbl = pSrcDoc->GetRedlineTbl();
583 	if( rTbl.Count() )
584 	{
585 		SwDoc* pDestDoc = rCpyPam.GetDoc();
586 		SwPosition* pCpyStt = rCpyPam.Start(), *pCpyEnd = rCpyPam.End();
587 		SwPaM* pDelPam = 0;
588 		const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
589         // We have to count the "non-copied" nodes
590         sal_uLong nDelCount = 0;
591         SwNodeIndex aCorrIdx( pStt->nNode );
592 
593 		sal_uInt16 n = 0;
594 		pSrcDoc->GetRedline( *pStt, &n );
595 		for( ; n < rTbl.Count(); ++n )
596 		{
597 			const SwRedline* pRedl = rTbl[ n ];
598 			if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetType() && pRedl->IsVisible() )
599 			{
600 				const SwPosition *pRStt = pRedl->Start(), *pREnd = pRedl->End();
601 
602 				SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd );
603 				switch( eCmpPos )
604 				{
605 				case POS_COLLIDE_END:
606 				case POS_BEFORE:				// Pos1 liegt vor Pos2
607 					break;
608 
609 				case POS_COLLIDE_START:
610 				case POS_BEHIND:				// Pos1 liegt hinter Pos2
611 					n = rTbl.Count();
612 					break;
613 
614 				default:
615 					{
616 						pDelPam = new SwPaM( *pCpyStt, pDelPam );
617 						if( *pStt < *pRStt )
618                         {
619                             lcl_NonCopyCount( rPam, aCorrIdx, pRStt->nNode.GetIndex(), nDelCount );
620 							lcl_SetCpyPos( *pRStt, *pStt, *pCpyStt,
621 											*pDelPam->GetPoint(), nDelCount );
622                         }
623 						pDelPam->SetMark();
624 
625 						if( *pEnd < *pREnd )
626 							*pDelPam->GetPoint() = *pCpyEnd;
627 						else
628                         {
629                             lcl_NonCopyCount( rPam, aCorrIdx, pREnd->nNode.GetIndex(), nDelCount );
630 							lcl_SetCpyPos( *pREnd, *pStt, *pCpyStt,
631 											*pDelPam->GetPoint(), nDelCount );
632                         }
633 					}
634 				}
635 			}
636 		}
637 
638 		if( pDelPam )
639 		{
640 			RedlineMode_t eOld = pDestDoc->GetRedlineMode();
641 			pDestDoc->SetRedlineMode_intern( (RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
642 
643             ::sw::UndoGuard const undoGuard(pDestDoc->GetIDocumentUndoRedo());
644 
645 			do {
646 				pDestDoc->DeleteAndJoin( *(SwPaM*)pDelPam->GetNext() );
647 				if( pDelPam->GetNext() == pDelPam )
648 					break;
649 				delete pDelPam->GetNext();
650 			} while( sal_True );
651 			delete pDelPam;
652 
653 			pDestDoc->SetRedlineMode_intern( eOld );
654 		}
655 	}
656 }
657 
658 void lcl_DeleteRedlines( const SwNodeRange& rRg, SwNodeRange& rCpyRg )
659 {
660 	SwDoc* pSrcDoc = rRg.aStart.GetNode().GetDoc();
661 	if( pSrcDoc->GetRedlineTbl().Count() )
662 	{
663 		SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
664 		SwPaM aCpyTmp( rCpyRg.aStart, rCpyRg.aEnd );
665 		lcl_DeleteRedlines( aRgTmp, aCpyTmp );
666 	}
667 }
668 
669 // Kopieren eines Bereiches im oder in ein anderes Dokument !
670 
671 bool
672 SwDoc::CopyRange( SwPaM& rPam, SwPosition& rPos, const bool bCopyAll ) const
673 {
674 	const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
675 
676 	SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
677     bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
678 
679 	// kein Copy abfangen.
680 	if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) )
681         return false;
682 
683 	// verhinder das Kopieren in Fly's, die im Bereich verankert sind.
684 	if( pDoc == this )
685 	{
686 		// Start-/EndNode noch korrigieren
687 		sal_uLong nStt = pStt->nNode.GetIndex(),
688 				nEnd = pEnd->nNode.GetIndex(),
689 				nDiff = nEnd - nStt +1;
690 		SwNode* pNd = GetNodes()[ nStt ];
691 		if( pNd->IsCntntNode() && pStt->nContent.GetIndex() )
692 			++nStt, --nDiff;
693 		if( (pNd = GetNodes()[ nEnd ])->IsCntntNode() &&
694 			((SwCntntNode*)pNd)->Len() != pEnd->nContent.GetIndex() )
695 			--nEnd, --nDiff;
696 		if( nDiff &&
697 			lcl_ChkFlyFly( pDoc, nStt, nEnd, rPos.nNode.GetIndex() ) )
698         {
699             return false;
700         }
701 	}
702 
703 	SwPaM* pRedlineRange = 0;
704 	if( pDoc->IsRedlineOn() ||
705 		(!pDoc->IsIgnoreRedline() && pDoc->GetRedlineTbl().Count() ) )
706 		pRedlineRange = new SwPaM( rPos );
707 
708 	RedlineMode_t eOld = pDoc->GetRedlineMode();
709 
710     bool bRet = false;
711 
712 	if( pDoc != this )
713     {   // ordinary copy
714         bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
715     }
716 	// Copy in sich selbst (ueber mehrere Nodes wird hier gesondert
717 	// behandelt; in einem TextNode wird normal behandelt)
718 	else if( ! ( *pStt <= rPos && rPos < *pEnd &&
719 			( pStt->nNode != pEnd->nNode ||
720 			  !pStt->nNode.GetNode().IsTxtNode() )) )
721     {   // ordinary copy
722         bRet = CopyImpl( rPam, rPos, true, bCopyAll, pRedlineRange );
723     }
724 	else
725 	{
726 		ASSERT( this == pDoc, " falscher Copy-Zweig!" );
727         ASSERT(false, "mst: i thought this could be dead code;"
728                 "please tell me what you did to get here!");
729 		pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
730 
731 		// dann kopiere den Bereich im unteren DokumentBereich,
732 		// (mit Start/End-Nodes geklammert) und verschiebe diese
733 		// dann an die gewuenschte Stelle.
734 
735         SwUndoCpyDoc* pUndo = 0;
736 		SwPaM aPam( rPos );			// UndoBereich sichern
737         if (pDoc->GetIDocumentUndoRedo().DoesUndo())
738         {
739             pDoc->GetIDocumentUndoRedo().ClearRedo();
740 			pUndo = new SwUndoCpyDoc( aPam );
741 		}
742 
743         {
744             ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
745             SwStartNode* pSttNd = pDoc->GetNodes().MakeEmptySection(
746                                 SwNodeIndex( GetNodes().GetEndOfAutotext() ));
747             aPam.GetPoint()->nNode = *pSttNd->EndOfSectionNode();
748             // copy without Frames
749             pDoc->CopyImpl( rPam, *aPam.GetPoint(), false, bCopyAll, 0 );
750 
751             aPam.GetPoint()->nNode = pDoc->GetNodes().GetEndOfAutotext();
752             aPam.SetMark();
753             SwCntntNode* pNode =
754                 pDoc->GetNodes().GoPrevious( &aPam.GetMark()->nNode );
755             pNode->MakeEndIndex( &aPam.GetMark()->nContent );
756 
757             aPam.GetPoint()->nNode = *aPam.GetNode()->StartOfSectionNode();
758             pNode = pDoc->GetNodes().GoNext( &aPam.GetPoint()->nNode );
759             pNode->MakeStartIndex( &aPam.GetPoint()->nContent );
760             // move to desired position
761             pDoc->MoveRange( aPam, rPos, DOC_MOVEDEFAULT );
762 
763             pNode = aPam.GetCntntNode();
764             *aPam.GetPoint() = rPos;        // Cursor umsetzen fuers Undo !
765             aPam.SetMark();                 // auch den Mark umsetzen !!
766             aPam.DeleteMark();              // aber keinen Bereich makieren !!
767             pDoc->DeleteSection( pNode );           // Bereich wieder loeschen
768         }
769 
770         // if Undo is enabled, store the insertion range
771         if (pDoc->GetIDocumentUndoRedo().DoesUndo())
772         {
773 			pUndo->SetInsertRange( aPam );
774             pDoc->GetIDocumentUndoRedo().AppendUndo(pUndo);
775         }
776 
777 		if( pRedlineRange )
778 		{
779 			pRedlineRange->SetMark();
780 			*pRedlineRange->GetPoint() = *aPam.GetPoint();
781 			*pRedlineRange->GetMark() = *aPam.GetMark();
782 		}
783 
784 		pDoc->SetModified();
785         bRet = true;
786     }
787 
788 	pDoc->SetRedlineMode_intern( eOld );
789 	if( pRedlineRange )
790 	{
791 		if( pDoc->IsRedlineOn() )
792 			pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, *pRedlineRange ), true);
793 		else
794 			pDoc->SplitRedline( *pRedlineRange );
795 		delete pRedlineRange;
796 	}
797 
798 	return bRet;
799 }
800 
801 // Kopieren eines Bereiches im oder in ein anderes Dokument !
802 // Die Position darf nicht im Bereich liegen !!
803 
804 bool lcl_MarksWholeNode(const SwPaM & rPam)
805 {
806     bool bResult = false;
807     const SwPosition* pStt = rPam.Start();
808     const SwPosition* pEnd = rPam.End();
809 
810     if (NULL != pStt && NULL != pEnd)
811     {
812         const SwTxtNode* pSttNd = pStt->nNode.GetNode().GetTxtNode();
813         const SwTxtNode* pEndNd = pEnd->nNode.GetNode().GetTxtNode();
814 
815         if (NULL != pSttNd && NULL != pEndNd &&
816             pStt->nContent.GetIndex() == 0 &&
817             pEnd->nContent.GetIndex() == pEndNd->Len())
818         {
819             bResult = true;
820         }
821     }
822 
823     return bResult;
824 }
825 
826 // --> OD 2009-08-25 #i86492#
827 bool lcl_ContainsOnlyParagraphsInList( const SwPaM& rPam )
828 {
829     bool bRet = false;
830 
831     const SwTxtNode* pTxtNd = rPam.Start()->nNode.GetNode().GetTxtNode();
832     const SwTxtNode* pEndTxtNd = rPam.End()->nNode.GetNode().GetTxtNode();
833     if ( pTxtNd && pTxtNd->IsInList() &&
834          pEndTxtNd && pEndTxtNd->IsInList() )
835     {
836         bRet = true;
837         SwNodeIndex aIdx(rPam.Start()->nNode);
838 
839         do
840         {
841             aIdx++;
842             pTxtNd = aIdx.GetNode().GetTxtNode();
843 
844             if ( !pTxtNd || !pTxtNd->IsInList() )
845             {
846                 bRet = false;
847                 break;
848             }
849         } while ( pTxtNd && pTxtNd != pEndTxtNd );
850     }
851 
852 
853     return bRet;
854 }
855 // <--
856 
857 bool SwDoc::CopyImpl( SwPaM& rPam, SwPosition& rPos,
858         const bool bMakeNewFrms, const bool bCopyAll,
859         SwPaM *const pCpyRange ) const
860 {
861 	SwDoc* pDoc = rPos.nNode.GetNode().GetDoc();
862     const bool bColumnSel = pDoc->IsClipBoard() && pDoc->IsColumnSelection();
863 
864     SwPosition* pStt = rPam.Start();
865     SwPosition* pEnd = rPam.End();
866 
867 	// kein Copy abfangen.
868 	if( !rPam.HasMark() || ( *pStt >= *pEnd && !bColumnSel ) ||
869 		//JP 29.6.2001: 88963 - dont copy if inspos is in region of start to end
870 		//JP 15.11.2001: don't test inclusive the end, ever exclusive
871 		( pDoc == this && *pStt <= rPos && rPos < *pEnd ))
872     {
873         return false;
874     }
875 
876     const bool bEndEqualIns = pDoc == this && rPos == *pEnd;
877 
878 	// falls Undo eingeschaltet, erzeuge das UndoCopy-Objekt
879     SwUndoCpyDoc* pUndo = 0;
880 	SwPaM aCpyPam( rPos );
881 
882 	SwTblNumFmtMerge aTNFM( *this, *pDoc );
883 
884     if (pDoc->GetIDocumentUndoRedo().DoesUndo())
885     {
886         pUndo = new SwUndoCpyDoc( aCpyPam );
887         pDoc->GetIDocumentUndoRedo().AppendUndo( pUndo );
888     }
889 
890 	RedlineMode_t eOld = pDoc->GetRedlineMode();
891 	pDoc->SetRedlineMode_intern((RedlineMode_t)(eOld | nsRedlineMode_t::REDLINE_IGNORE));
892 
893 
894 	// bewege den Pam von der Insert-Position ein zurueck, dadurch wird
895 	// die Position nicht "verschoben"
896 	aCpyPam.SetMark();
897 	sal_Bool bCanMoveBack = aCpyPam.Move( fnMoveBackward, fnGoCntnt );
898 	if( !bCanMoveBack )
899 		aCpyPam.GetPoint()->nNode--;
900 
901 	SwNodeRange aRg( pStt->nNode, pEnd->nNode );
902 	SwNodeIndex aInsPos( rPos.nNode );
903     const bool bOneNode = pStt->nNode == pEnd->nNode;
904     SwTxtNode* pSttTxtNd = pStt->nNode.GetNode().GetTxtNode();
905     SwTxtNode* pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
906     SwTxtNode* pDestTxtNd = aInsPos.GetNode().GetTxtNode();
907     bool bCopyCollFmt = !pDoc->IsInsOnlyTextGlossary() &&
908                         ( ( pDestTxtNd && !pDestTxtNd->GetTxt().Len() ) ||
909                           ( !bOneNode && !rPos.nContent.GetIndex() ) );
910     bool bCopyBookmarks = true;
911     sal_Bool bStartIsTxtNode = 0 != pSttTxtNd;
912 
913     // #i104585# copy outline num rule to clipboard (for ASCII filter)
914     if (pDoc->IsClipBoard() && GetOutlineNumRule())
915     {
916         pDoc->SetOutlineNumRule(*GetOutlineNumRule());
917     }
918 
919     // --> OD 2009-08-25 #i86492#
920     // Correct the search for a previous list:
921     // First search for non-outline numbering list. Then search for non-outline
922     // bullet list.
923     // Keep also the <ListId> value for possible propagation.
924     String aListIdToPropagate;
925     const SwNumRule* pNumRuleToPropagate =
926         pDoc->SearchNumRule( rPos, false, true, false, 0, aListIdToPropagate, true );
927     if ( !pNumRuleToPropagate )
928     {
929         pNumRuleToPropagate =
930             pDoc->SearchNumRule( rPos, false, false, false, 0, aListIdToPropagate, true );
931     }
932     // <--
933     // --> OD 2009-08-25 #i86492#
934     // Do not propagate previous found list, if
935     // - destination is an empty paragraph which is not in a list and
936     // - source contains at least one paragraph which is not in a list
937     if ( pNumRuleToPropagate &&
938          pDestTxtNd && !pDestTxtNd->GetTxt().Len() && !pDestTxtNd->IsInList() &&
939          !lcl_ContainsOnlyParagraphsInList( rPam ) )
940     {
941         pNumRuleToPropagate = 0;
942     }
943     // <--
944 
945 	// Block, damit aus diesem gesprungen werden kann !!
946 	do {
947         if( pSttTxtNd )
948 		{
949 			// den Anfang nicht komplett kopieren ?
950 			if( !bCopyCollFmt || bColumnSel || pStt->nContent.GetIndex() )
951 			{
952 				SwIndex aDestIdx( rPos.nContent );
953 				sal_Bool bCopyOk = sal_False;
954                 if( !pDestTxtNd )
955 				{
956 					if( pStt->nContent.GetIndex() || bOneNode )
957                         pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
958 							pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
959 					else
960 					{
961                         pDestTxtNd = static_cast<SwTxtNode*>(pSttTxtNd->MakeCopy( pDoc, aInsPos ));
962 						bCopyOk = sal_True;
963 					}
964                     aDestIdx.Assign( pDestTxtNd, 0 );
965                     bCopyCollFmt = true;
966 				}
967 				else if( !bOneNode || bColumnSel )
968 				{
969 					xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
970                     {
971                         ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
972                         pDoc->SplitNode( rPos, false );
973                     }
974 
975 					if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
976 					{
977 						// nach dem SplitNode, den CpyPam wieder richtig aufspannen
978 						aCpyPam.Move( fnMoveBackward, fnGoCntnt );
979 						aCpyPam.Move( fnMoveBackward, fnGoCntnt );
980 					}
981 
982                     pDestTxtNd = pDoc->GetNodes()[ aInsPos.GetIndex()-1 ]->GetTxtNode();
983                     aDestIdx.Assign( pDestTxtNd, pDestTxtNd->GetTxt().Len() );
984 
985 					// korrigiere den Bereich wieder !!
986 					if( bEndEqualIns )
987 					{
988 						sal_Bool bChg = pEnd != rPam.GetPoint();
989 						if( bChg )
990 							rPam.Exchange();
991 						rPam.Move( fnMoveBackward, fnGoCntnt );
992 						if( bChg )
993 							rPam.Exchange();
994 
995 						aRg.aEnd = pEnd->nNode;
996                         pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
997 					}
998 					else if( rPos == *pEnd )		// Wurde das Ende auch verschoben
999 					{
1000 						pEnd->nNode--;
1001                         pEnd->nContent.Assign( pDestTxtNd, nCntntEnd );
1002 						aRg.aEnd = pEnd->nNode;
1003                         pEndTxtNd = pEnd->nNode.GetNode().GetTxtNode();
1004 					}
1005 				}
1006 
1007 				/* #107213#: Safe numrule item at destination. */
1008                 // --> OD 2009-08-25 #i86492#
1009                 // Safe also <ListId> item of destination.
1010                 int aNumRuleState = SFX_ITEM_UNKNOWN;
1011 				SwNumRuleItem aNumRuleItem;
1012                 int aListIdState = SFX_ITEM_UNKNOWN;
1013                 SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
1014                 {
1015                     const SfxItemSet * pAttrSet = pDestTxtNd->GetpSwAttrSet();
1016                     if (pAttrSet != NULL)
1017                     {
1018                         const SfxPoolItem * pItem = NULL;
1019                         aNumRuleState = pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
1020                         if (SFX_ITEM_SET == aNumRuleState)
1021                             aNumRuleItem = *((SwNumRuleItem *) pItem);
1022 
1023                         aListIdState =
1024                             pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
1025                         if (SFX_ITEM_SET == aListIdState)
1026                         {
1027                             aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1028                         }
1029                     }
1030                 }
1031                 // <--
1032 				/* #107213# */
1033 
1034 				if( !bCopyOk )
1035 				{
1036                     const xub_StrLen nCpyLen = ( (bOneNode)
1037                                            ? pEnd->nContent.GetIndex()
1038                                            : pSttTxtNd->GetTxt().Len() )
1039                                          - pStt->nContent.GetIndex();
1040                     pSttTxtNd->CopyText( pDestTxtNd, aDestIdx,
1041                                             pStt->nContent, nCpyLen );
1042 					if( bEndEqualIns )
1043 						pEnd->nContent -= nCpyLen;
1044 				}
1045 
1046 				if( bOneNode )
1047 				{
1048 					if( bCopyCollFmt )
1049 					{
1050                         pSttTxtNd->CopyCollFmt( *pDestTxtNd );
1051 
1052                         /* #107213# If only a part of one paragraph is copied
1053                            restore the numrule at the destination. */
1054                         // --> OD 2009-08-25 #i86492#
1055                         // restore also <ListId> item
1056                         if ( !lcl_MarksWholeNode(rPam) )
1057                         {
1058                             if (SFX_ITEM_SET == aNumRuleState)
1059                             {
1060                                 pDestTxtNd->SetAttr(aNumRuleItem);
1061                             }
1062                             else
1063                             {
1064                                 pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1065                             }
1066                             if (SFX_ITEM_SET == aListIdState)
1067                             {
1068                                 pDestTxtNd->SetAttr(aListIdItem);
1069                             }
1070                             else
1071                             {
1072                                 pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1073                             }
1074                         }
1075                     }
1076 
1077 					break;
1078 				}
1079 
1080 				aRg.aStart++;
1081 			}
1082 		}
1083         else if( pDestTxtNd )
1084 		{
1085             // Problems with insertion of table selections into "normal" text solved.
1086             // We have to set the correct PaM for Undo, if this PaM starts in a textnode,
1087             // the undo operation will try to merge this node after removing the table.
1088             // If we didn't split a textnode, the PaM should start at the inserted table node
1089             if( rPos.nContent.GetIndex() == pDestTxtNd->Len() )
1090 			{    // Insertion at the last position of a textnode (empty or not)
1091 				aInsPos++; // The table will be inserted behind the text node
1092 			}
1093 			else if( rPos.nContent.GetIndex() )
1094 			{   // Insertion in the middle of a text node, it has to be split
1095                 // (and joined from undo)
1096                 bStartIsTxtNode = sal_True;
1097 				// splitte den TextNode, bei dem Eingefuegt wird.
1098 
1099 				xub_StrLen nCntntEnd = pEnd->nContent.GetIndex();
1100                 {
1101                     ::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
1102                     pDoc->SplitNode( rPos, false );
1103                 }
1104 
1105 				if( bCanMoveBack && rPos == *aCpyPam.GetPoint() )
1106 				{
1107 					// nach dem SplitNode, den CpyPam wieder richtig aufspannen
1108 					aCpyPam.Move( fnMoveBackward, fnGoCntnt );
1109 					aCpyPam.Move( fnMoveBackward, fnGoCntnt );
1110 				}
1111 
1112 				// korrigiere den Bereich wieder !!
1113 				if( bEndEqualIns )
1114 					aRg.aEnd--;
1115 				else if( rPos == *pEnd )		// Wurde das Ende auch verschoben
1116 				{
1117 					rPos.nNode-=2;
1118 					rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1119 											nCntntEnd );
1120 					rPos.nNode++;
1121 					aRg.aEnd--;
1122 				}
1123 			}
1124             else if( bCanMoveBack )
1125             {   //Insertion at the first position of a text node. It will not be splitted, the table
1126                 // will be inserted before the text node.
1127                 // See below, before the SetInsertRange funciton of the undo object will be called,
1128                 // the CpyPam would be moved to the next content position. This has to be avoided
1129                 // We want to be moved to the table node itself thus we have to set bCanMoveBack
1130                 // and to manipulate aCpyPam.
1131                 bCanMoveBack = false;
1132                 aCpyPam.GetPoint()->nNode--;
1133             }
1134 		}
1135 
1136         pDestTxtNd = aInsPos.GetNode().GetTxtNode();
1137         if( pEndTxtNd )
1138 		{
1139 			SwIndex aDestIdx( rPos.nContent );
1140             if( !pDestTxtNd )
1141 			{
1142                 pDestTxtNd = pDoc->GetNodes().MakeTxtNode( aInsPos,
1143 							pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD));
1144                 aDestIdx.Assign( pDestTxtNd, 0  );
1145 				aInsPos--;
1146 
1147                 // #112756# #98130# if we have to insert an extra text node
1148                 // at the destination, this node will be our new destination
1149                 // (text) node, and thus we set bStartisTxtNode to true. This
1150                 // will ensure that this node will be deleted during Undo
1151                 // using JoinNext.
1152                 DBG_ASSERT( !bStartIsTxtNode, "Oops, undo may be instable now." );
1153                 bStartIsTxtNode = sal_True;
1154 			}
1155 
1156 			/* #107213# Save numrule at destination */
1157             // --> OD 2009-08-25 #i86492#
1158             // Safe also <ListId> item of destination.
1159             int aNumRuleState = SFX_ITEM_UNKNOWN;
1160             SwNumRuleItem aNumRuleItem;
1161             int aListIdState = SFX_ITEM_UNKNOWN;
1162             SfxStringItem aListIdItem( RES_PARATR_LIST_ID, String() );
1163             {
1164                 const SfxItemSet* pAttrSet = pDestTxtNd->GetpSwAttrSet();
1165                 if (pAttrSet != NULL)
1166                 {
1167                     const SfxPoolItem * pItem = NULL;
1168 
1169                     aNumRuleState =
1170                         pAttrSet->GetItemState(RES_PARATR_NUMRULE, sal_False, &pItem);
1171                     if (SFX_ITEM_SET == aNumRuleState)
1172                         aNumRuleItem = *((SwNumRuleItem *) pItem);
1173 
1174                     aListIdState =
1175                         pAttrSet->GetItemState(RES_PARATR_LIST_ID, sal_False, &pItem);
1176                     if (SFX_ITEM_SET == aListIdState)
1177                         aListIdItem.SetValue( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1178                 }
1179             }
1180             // <--
1181 			/* #107213# */
1182 
1183             const bool bEmptyDestNd = 0 == pDestTxtNd->GetTxt().Len();
1184             pEndTxtNd->CopyText( pDestTxtNd, aDestIdx, SwIndex( pEndTxtNd ),
1185 							pEnd->nContent.GetIndex() );
1186 
1187 			// auch alle FormatVorlagen kopieren
1188 			if( bCopyCollFmt && ( bOneNode || bEmptyDestNd ))
1189 			{
1190                 pEndTxtNd->CopyCollFmt( *pDestTxtNd );
1191 
1192                 if ( bOneNode )
1193 				{
1194 					/* #107213# If only a part of one paragraph is copied
1195                        restore the numrule at the destination. */
1196                     // --> OD 2009-08-25 #i86492#
1197                     // restore also <ListId> item
1198                     if ( !lcl_MarksWholeNode(rPam) )
1199                     {
1200                         if (SFX_ITEM_SET == aNumRuleState)
1201                         {
1202                             pDestTxtNd->SetAttr(aNumRuleItem);
1203                         }
1204                         else
1205                         {
1206                             pDestTxtNd->ResetAttr(RES_PARATR_NUMRULE);
1207                         }
1208                         if (SFX_ITEM_SET == aListIdState)
1209                         {
1210                             pDestTxtNd->SetAttr(aListIdItem);
1211                         }
1212                         else
1213                         {
1214                             pDestTxtNd->ResetAttr(RES_PARATR_LIST_ID);
1215                         }
1216                     }
1217 				}
1218 			}
1219 		}
1220 
1221 		if( bCopyAll || aRg.aStart != aRg.aEnd )
1222 		{
1223 			SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
1224             if( pSttTxtNd && bCopyCollFmt && pDestTxtNd->HasSwAttrSet() )
1225 			{
1226                 aBrkSet.Put( *pDestTxtNd->GetpSwAttrSet() );
1227 				if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_BREAK, sal_False ) )
1228                     pDestTxtNd->ResetAttr( RES_BREAK );
1229 				if( SFX_ITEM_SET == aBrkSet.GetItemState( RES_PAGEDESC, sal_False ) )
1230                     pDestTxtNd->ResetAttr( RES_PAGEDESC );
1231 			}
1232 
1233 			if( aInsPos == pEnd->nNode )
1234 			{
1235 				SwNodeIndex aSaveIdx( aInsPos, -1 );
1236                 CopyWithFlyInFly( aRg, 0,aInsPos, bMakeNewFrms, sal_False );
1237 				aSaveIdx++;
1238 				pEnd->nNode = aSaveIdx;
1239 				pEnd->nContent.Assign( aSaveIdx.GetNode().GetTxtNode(), 0 );
1240 			}
1241 			else
1242                 CopyWithFlyInFly( aRg, pEnd->nContent.GetIndex(), aInsPos, bMakeNewFrms, sal_False );
1243 
1244             bCopyBookmarks = false;
1245 
1246 			// harte Umbrueche wieder in den ersten Node setzen
1247             if( aBrkSet.Count() && 0 != ( pDestTxtNd = pDoc->GetNodes()[
1248 					aCpyPam.GetPoint()->nNode.GetIndex()+1 ]->GetTxtNode() ) )
1249 			{
1250                 pDestTxtNd->SetAttr( aBrkSet );
1251 			}
1252 		}
1253 	} while( sal_False );
1254 
1255 	// Position ummelden ( falls verschoben / im anderen Node )
1256 	rPos.nContent.Assign( rPos.nNode.GetNode().GetCntntNode(),
1257 							rPos.nContent.GetIndex() );
1258 
1259 	if( rPos.nNode != aInsPos )
1260 	{
1261 		aCpyPam.GetMark()->nNode = aInsPos;
1262 		aCpyPam.GetMark()->nContent.Assign( aCpyPam.GetCntntNode(sal_False), 0 );
1263 		rPos = *aCpyPam.GetMark();
1264 	}
1265 	else
1266 		*aCpyPam.GetMark() = rPos;
1267 
1268 	aCpyPam.Move( fnMoveForward, bCanMoveBack ? fnGoCntnt : fnGoNode );
1269 	aCpyPam.Exchange();
1270 
1271 	// dann kopiere noch alle Bookmarks
1272     if( bCopyBookmarks && getIDocumentMarkAccess()->getMarksCount() )
1273 		lcl_CopyBookmarks( rPam, aCpyPam );
1274 
1275 	if( nsRedlineMode_t::REDLINE_DELETE_REDLINES & eOld )
1276 		lcl_DeleteRedlines( rPam, aCpyPam );
1277 
1278 	// falls Undo eingeschaltet ist, so speicher den eingefuegten Bereich
1279     if (pDoc->GetIDocumentUndoRedo().DoesUndo())
1280     {
1281 		pUndo->SetInsertRange( aCpyPam, sal_True, bStartIsTxtNode );
1282     }
1283 
1284 	if( pCpyRange )
1285 	{
1286 		pCpyRange->SetMark();
1287 		*pCpyRange->GetPoint() = *aCpyPam.GetPoint();
1288 		*pCpyRange->GetMark() = *aCpyPam.GetMark();
1289 	}
1290 
1291     if ( pNumRuleToPropagate )
1292     {
1293         // --> OD 2009-08-25 #i86492#
1294         // use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
1295 //        pDoc->ReplaceNumRule(aCpyPam, *pNumRuleToPropagate);
1296         pDoc->SetNumRule( aCpyPam, *pNumRuleToPropagate, false,
1297                           aListIdToPropagate, sal_True, true );
1298     }
1299 
1300 	pDoc->SetRedlineMode_intern( eOld );
1301 	pDoc->SetModified();
1302 
1303     return true;
1304 }
1305 
1306 
1307 //  ----- Copy-Methode vom SwDoc - "kopiere Fly's in Fly's" ------
1308 
1309 void SwDoc::CopyWithFlyInFly( const SwNodeRange& rRg, const xub_StrLen nEndContentIndex,
1310 							const SwNodeIndex& rInsPos, sal_Bool bMakeNewFrms,
1311 							sal_Bool bDelRedlines, sal_Bool bCopyFlyAtFly ) const
1312 {
1313 	SwDoc* pDest = rInsPos.GetNode().GetDoc();
1314 
1315 	_SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
1316 
1317 	SwNodeIndex aSavePos( rInsPos, -1 );
1318 	sal_Bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
1319 	GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, sal_True );
1320 	aSavePos++;
1321 	if( bEndIsEqualEndPos )
1322 		((SwNodeIndex&)rRg.aEnd) = aSavePos;
1323 
1324 	aRedlRest.Restore();
1325 
1326 #ifdef DBG_UTIL
1327 	{
1328 		//JP 17.06.99: Bug 66973 - check count only if the selection is in
1329 		//				the same (or no) section. Becaus not full selected
1330 		//				section are not copied.
1331 		const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
1332 		SwNodeIndex aTmpI( rRg.aEnd, -1 );
1333 		const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
1334 		if( pSSectNd == pESectNd &&
1335 			!rRg.aStart.GetNode().IsSectionNode() &&
1336 			!aTmpI.GetNode().IsEndNode() )
1337 		{
1338 			ASSERT( rInsPos.GetIndex() - aSavePos.GetIndex() ==
1339 					rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
1340 					"Es wurden zu wenig Nodes kopiert!" )
1341 		}
1342 	}
1343 #endif
1344 
1345     {
1346         ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
1347         CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
1348     }
1349 
1350 	SwNodeRange aCpyRange( aSavePos, rInsPos );
1351 
1352 	// dann kopiere noch alle Bookmarks
1353     if( getIDocumentMarkAccess()->getMarksCount() )
1354 	{
1355 		SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
1356 		SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
1357 
1358 		lcl_CopyBookmarks( aRgTmp, aCpyTmp );
1359 	}
1360 
1361 	if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->GetRedlineMode() ))
1362 		lcl_DeleteRedlines( rRg, aCpyRange );
1363 
1364 	pDest->GetNodes()._DelDummyNodes( aCpyRange );
1365 }
1366 
1367 void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
1368 {
1369 	SwFmtChain aSrc( pSrc->GetChain() );
1370 	if ( !aSrc.GetNext() )
1371 	{
1372 		aSrc.SetNext( pDest );
1373         pSrc->SetFmtAttr( aSrc );
1374 	}
1375 	SwFmtChain aDest( pDest->GetChain() );
1376 	if ( !aDest.GetPrev() )
1377 	{
1378 		aDest.SetPrev( pSrc );
1379         pDest->SetFmtAttr( aDest );
1380 	}
1381 }
1382 
1383 void SwDoc::CopyFlyInFlyImpl( const SwNodeRange& rRg,
1384         const xub_StrLen nEndContentIndex, const SwNodeIndex& rStartIdx,
1385         const bool bCopyFlyAtFly ) const
1386 {
1387 	// Bug 22727: suche erst mal alle Flys zusammen, sortiere sie entsprechend
1388 	//			  ihrer Ordnungsnummer und kopiere sie erst dann. Damit wird
1389 	//			  die Ordnungsnummer (wird nur im DrawModel verwaltet)
1390 	//			  beibehalten.
1391     SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
1392 	_ZSortFlys aArr;
1393 	sal_uInt16 nArrLen = GetSpzFrmFmts()->Count();
1394 
1395     for ( sal_uInt16 n = 0; n < nArrLen; ++n )
1396     {
1397         SwFrmFmt const*const pFmt = (*GetSpzFrmFmts())[n];
1398         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
1399         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
1400         bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
1401         if ( pAPos &&
1402              ( bAtCntnt ||
1403               (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
1404               (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
1405 			 (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
1406 					? rRg.aStart <= pAPos->nNode.GetIndex() + 1
1407 					: ( IsRedlineMove()
1408 							? rRg.aStart < pAPos->nNode
1409 							: rRg.aStart <= pAPos->nNode )) &&
1410 			 pAPos->nNode <= rRg.aEnd )
1411 		{
1412 			//frames at the last source node are not always copied:
1413             //- if the node is empty and is the last node of the document or a table cell
1414             //  or a text frame then tey have to be copied
1415             //- if the content index in this node is > 0 then paragph and frame bound objects are copied
1416             //- to-character bound objects are copied if their index is <= nEndContentIndex
1417             bool bAdd = false;
1418             if( pAPos->nNode < rRg.aEnd )
1419                 bAdd = true;
1420             if( !bAdd )
1421             {
1422                 bool bEmptyNode = false;
1423                 bool bLastNode = false;
1424                 // is the node empty?
1425                 const SwNodes& rNodes = pAPos->nNode.GetNodes();
1426                 SwTxtNode* pTxtNode;
1427                 if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
1428                 {
1429                     bEmptyNode = !pTxtNode->GetTxt().Len();
1430                     if( bEmptyNode )
1431                     {
1432                         //last node information is only necessary to know for the last TextNode
1433                         SwNodeIndex aTmp( pAPos->nNode );
1434                         ++aTmp;//goto next node
1435                         while (aTmp.GetNode().IsEndNode())
1436                         {
1437                             if( aTmp == rNodes.GetEndOfContent().GetIndex() )
1438                             {
1439                                 bLastNode = true;
1440                                 break;
1441                             }
1442                             ++aTmp;
1443                         }
1444                     }
1445                 }
1446                 bAdd = bLastNode && bEmptyNode;
1447                 if( !bAdd )
1448                 {
1449                     if( bAtCntnt )
1450                         bAdd = nEndContentIndex > 0;
1451                     else
1452                         bAdd = pAPos->nContent <= nEndContentIndex;
1453                 }
1454             }
1455             if( bAdd )
1456                 aArr.Insert( _ZSortFly( pFmt, pAnchor, nArrLen + aArr.Count() ));
1457 		}
1458 	}
1459 
1460 	//Alle kopierten (also die neu erzeugten) Rahmen in ein weiteres Array
1461 	//stopfen. Dort sizten sie passend zu den Originalen, damit hinterher
1462 	//die Chains entsprechend aufgebaut werden koennen.
1463 	SvPtrarr aNewArr( 10, 10 );
1464 
1465     for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
1466     {
1467 		const _ZSortFly& rZSortFly = aArr[ n ];
1468 
1469         // --> OD 2006-01-04 #i59964#
1470         // correct determination of new anchor position
1471         SwFmtAnchor aAnchor( *rZSortFly.GetAnchor() );
1472         SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
1473         // for at-paragraph and at-character anchored objects the new anchor
1474         // position can *not* be determined by the difference of the current
1475         // anchor position to the start of the copied range, because not
1476         // complete selected sections in the copied range aren't copied - see
1477         // method <SwNodes::_CopyNodes(..)>.
1478         // Thus, the new anchor position in the destination document is found
1479         // by counting the text nodes.
1480         if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
1481             (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
1482         {
1483             // First, determine number of anchor text node in the copied range.
1484             // Note: The anchor text node *have* to be inside the copied range.
1485             sal_uLong nAnchorTxtNdNumInRange( 0L );
1486             bool bAnchorTxtNdFound( false );
1487             SwNodeIndex aIdx( rRg.aStart );
1488             while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
1489             {
1490                 if ( aIdx.GetNode().IsTxtNode() )
1491                 {
1492                     ++nAnchorTxtNdNumInRange;
1493                     bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
1494                 }
1495 
1496                 ++aIdx;
1497             }
1498             if ( !bAnchorTxtNdFound )
1499             {
1500                 // This case can *not* happen, but to be robust take the first
1501                 // text node in the destination document.
1502                 ASSERT( false,
1503                         "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
1504                 nAnchorTxtNdNumInRange = 1;
1505             }
1506             // Second, search corresponding text node in destination document
1507             // by counting forward from start insert position <rStartIdx> the
1508             // determined number of text nodes.
1509             aIdx = rStartIdx;
1510             SwNodeIndex aAnchorNdIdx( rStartIdx );
1511             const SwNode& aEndOfContentNd =
1512                                     aIdx.GetNode().GetNodes().GetEndOfContent();
1513             while ( nAnchorTxtNdNumInRange > 0 &&
1514                     &(aIdx.GetNode()) != &aEndOfContentNd )
1515             {
1516                 if ( aIdx.GetNode().IsTxtNode() )
1517                 {
1518                     --nAnchorTxtNdNumInRange;
1519                     aAnchorNdIdx = aIdx;
1520                 }
1521 
1522                 ++aIdx;
1523             }
1524             if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1525             {
1526                 // This case can *not* happen, but to be robust take the first
1527                 // text node in the destination document.
1528                 ASSERT( false,
1529                         "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
1530                 aAnchorNdIdx = rStartIdx;
1531                 while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1532                 {
1533                     ++aAnchorNdIdx;
1534                 }
1535             }
1536             // apply found anchor text node as new anchor position
1537             pNewPos->nNode = aAnchorNdIdx;
1538         }
1539         else
1540         {
1541             long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
1542             SwNodeIndex aIdx( rStartIdx, nOffset );
1543             pNewPos->nNode = aIdx;
1544         }
1545         // <--
1546 		// die am Zeichen Flys wieder ans das vorgegebene Zeichen setzen
1547         if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
1548              pNewPos->nNode.GetNode().IsTxtNode() )
1549         {
1550             pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
1551 										pNewPos->nContent.GetIndex() );
1552         }
1553 		else
1554         {
1555 			pNewPos->nContent.Assign( 0, 0 );
1556         }
1557 
1558 		// ueberpruefe Rekursion: Inhalt in "seinen eigenen" Frame
1559 		// kopieren. Dann nicht kopieren
1560 		sal_Bool bMakeCpy = sal_True;
1561 		if( pDest == this )
1562 		{
1563 			const SwFmtCntnt& rCntnt = rZSortFly.GetFmt()->GetCntnt();
1564 			const SwStartNode* pSNd;
1565 			if( rCntnt.GetCntntIdx() &&
1566 				0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
1567                 pSNd->GetIndex() < rStartIdx.GetIndex() &&
1568                 rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
1569 			{
1570 				bMakeCpy = sal_False;
1571 				aArr.Remove( n, 1 );
1572 				--n;
1573 			}
1574 		}
1575 
1576 		// Format kopieren und den neuen Anker setzen
1577 		if( bMakeCpy )
1578 			aNewArr.Insert( pDest->CopyLayoutFmt( *rZSortFly.GetFmt(),
1579                         aAnchor, false, true ), aNewArr.Count() );
1580 	}
1581 
1582 	//Alle chains, die im Original vorhanden sind, soweit wie moeglich wieder
1583 	//aufbauen.
1584 	ASSERT( aArr.Count() == aNewArr.Count(), "Missing new Flys" );
1585 	if ( aArr.Count() == aNewArr.Count() )
1586 	{
1587         for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
1588 		{
1589 			const SwFrmFmt *pFmt = aArr[n].GetFmt();
1590 			const SwFmtChain &rChain = pFmt->GetChain();
1591 			int nCnt = 0 != rChain.GetPrev();
1592 			nCnt += rChain.GetNext() ? 1: 0;
1593 			for ( sal_uInt16 k = 0; nCnt && k < aArr.Count(); ++k )
1594 			{
1595 				const _ZSortFly &rTmp = aArr[k];
1596 				const SwFrmFmt *pTmp = rTmp.GetFmt();
1597 				if ( rChain.GetPrev() == pTmp )
1598 				{
1599 					::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[k],
1600 									 (SwFlyFrmFmt*)aNewArr[n] );
1601 					--nCnt;
1602 				}
1603 				else if ( rChain.GetNext() == pTmp )
1604 				{
1605 					::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[n],
1606 									 (SwFlyFrmFmt*)aNewArr[k] );
1607 					--nCnt;
1608 				}
1609 			}
1610 		}
1611 	}
1612 }
1613 
1614 
1615 
1616 
1617