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