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