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