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 )
1310 {
1311 // --> OD 2009-08-25 #i86492#
1312 // use <SwDoc::SetNumRule(..)>, because it also handles the <ListId>
1313 // pDoc->ReplaceNumRule(aCpyPam, *pNumRuleToPropagate);
1314 pDoc->SetNumRule( aCpyPam, *pNumRuleToPropagate, false,
1315 aListIdToPropagate, sal_True, true );
1316 }
1317
1318 pDoc->SetRedlineMode_intern( eOld );
1319 pDoc->SetModified();
1320
1321 return true;
1322 }
1323
1324
1325 // ----- Copy-Methode vom SwDoc - "kopiere Fly's in Fly's" ------
1326
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) const1327 void SwDoc::CopyWithFlyInFly(
1328 const SwNodeRange& rRg,
1329 const xub_StrLen nEndContentIndex,
1330 const SwNodeIndex& rInsPos,
1331 const SwPaM* pCopiedPaM,
1332 const sal_Bool bMakeNewFrms,
1333 const sal_Bool bDelRedlines,
1334 const sal_Bool bCopyFlyAtFly ) const
1335 {
1336 SwDoc* pDest = rInsPos.GetNode().GetDoc();
1337
1338 _SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
1339
1340 SwNodeIndex aSavePos( rInsPos, -1 );
1341 sal_Bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
1342 GetNodes()._CopyNodes( rRg, rInsPos, bMakeNewFrms, sal_True );
1343 aSavePos++;
1344 if( bEndIsEqualEndPos )
1345 ((SwNodeIndex&)rRg.aEnd) = aSavePos;
1346
1347 aRedlRest.Restore();
1348
1349 #ifdef DBG_UTIL
1350 {
1351 //JP 17.06.99: Bug 66973 - check count only if the selection is in
1352 // the same (or no) section. Becaus not full selected
1353 // section are not copied.
1354 const SwSectionNode* pSSectNd = rRg.aStart.GetNode().FindSectionNode();
1355 SwNodeIndex aTmpI( rRg.aEnd, -1 );
1356 const SwSectionNode* pESectNd = aTmpI.GetNode().FindSectionNode();
1357 if( pSSectNd == pESectNd &&
1358 !rRg.aStart.GetNode().IsSectionNode() &&
1359 !aTmpI.GetNode().IsEndNode() )
1360 {
1361 ASSERT( rInsPos.GetIndex() - aSavePos.GetIndex() ==
1362 rRg.aEnd.GetIndex() - rRg.aStart.GetIndex(),
1363 "Es wurden zu wenig Nodes kopiert!" )
1364 }
1365 }
1366 #endif
1367
1368 {
1369 ::sw::UndoGuard const undoGuard(pDest->GetIDocumentUndoRedo());
1370 CopyFlyInFlyImpl( rRg, nEndContentIndex, aSavePos, bCopyFlyAtFly );
1371 }
1372
1373 SwNodeRange aCpyRange( aSavePos, rInsPos );
1374
1375 // dann kopiere noch alle Bookmarks
1376 if( getIDocumentMarkAccess()->getAllMarksCount() )
1377 {
1378 SwPaM aRgTmp( rRg.aStart, rRg.aEnd );
1379 SwPaM aCpyTmp( aCpyRange.aStart, aCpyRange.aEnd );
1380
1381 lcl_CopyBookmarks(
1382 pCopiedPaM != NULL ? *pCopiedPaM : aRgTmp,
1383 aCpyTmp );
1384 }
1385
1386 if( bDelRedlines && ( nsRedlineMode_t::REDLINE_DELETE_REDLINES & pDest->GetRedlineMode() ))
1387 lcl_DeleteRedlines( rRg, aCpyRange );
1388
1389 pDest->GetNodes()._DelDummyNodes( aCpyRange );
1390 }
1391
lcl_ChainFmts(SwFlyFrmFmt * pSrc,SwFlyFrmFmt * pDest)1392 void lcl_ChainFmts( SwFlyFrmFmt *pSrc, SwFlyFrmFmt *pDest )
1393 {
1394 SwFmtChain aSrc( pSrc->GetChain() );
1395 if ( !aSrc.GetNext() )
1396 {
1397 aSrc.SetNext( pDest );
1398 pSrc->SetFmtAttr( aSrc );
1399 }
1400 SwFmtChain aDest( pDest->GetChain() );
1401 if ( !aDest.GetPrev() )
1402 {
1403 aDest.SetPrev( pSrc );
1404 pDest->SetFmtAttr( aDest );
1405 }
1406 }
1407
CopyFlyInFlyImpl(const SwNodeRange & rRg,const xub_StrLen nEndContentIndex,const SwNodeIndex & rStartIdx,const bool bCopyFlyAtFly) const1408 void SwDoc::CopyFlyInFlyImpl(
1409 const SwNodeRange& rRg,
1410 const xub_StrLen nEndContentIndex,
1411 const SwNodeIndex& rStartIdx,
1412 const bool bCopyFlyAtFly ) const
1413 {
1414 // Bug 22727: suche erst mal alle Flys zusammen, sortiere sie entsprechend
1415 // ihrer Ordnungsnummer und kopiere sie erst dann. Damit wird
1416 // die Ordnungsnummer (wird nur im DrawModel verwaltet)
1417 // beibehalten.
1418 SwDoc *const pDest = rStartIdx.GetNode().GetDoc();
1419 _ZSortFlys aArr;
1420 sal_uInt16 nArrLen = GetSpzFrmFmts()->Count();
1421
1422 for ( sal_uInt16 n = 0; n < nArrLen; ++n )
1423 {
1424 SwFrmFmt const*const pFmt = (*GetSpzFrmFmts())[n];
1425 SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
1426 SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
1427 bool bAtCntnt = (pAnchor->GetAnchorId() == FLY_AT_PARA);
1428 if ( pAPos &&
1429 ( bAtCntnt ||
1430 (pAnchor->GetAnchorId() == FLY_AT_FLY) ||
1431 (pAnchor->GetAnchorId() == FLY_AT_CHAR)) &&
1432 (( bCopyFlyAtFly && FLY_AT_FLY == pAnchor->GetAnchorId() )
1433 ? rRg.aStart <= pAPos->nNode.GetIndex() + 1
1434 : ( IsRedlineMove()
1435 ? rRg.aStart < pAPos->nNode
1436 : rRg.aStart <= pAPos->nNode )) &&
1437 pAPos->nNode <= rRg.aEnd )
1438 {
1439 //frames at the last source node are not always copied:
1440 //- if the node is empty and is the last node of the document or a table cell
1441 // or a text frame then tey have to be copied
1442 //- if the content index in this node is > 0 then paragph and frame bound objects are copied
1443 //- to-character bound objects are copied if their index is <= nEndContentIndex
1444 bool bAdd = false;
1445 if( pAPos->nNode < rRg.aEnd )
1446 bAdd = true;
1447 if( !bAdd )
1448 {
1449 bool bEmptyNode = false;
1450 bool bLastNode = false;
1451 // is the node empty?
1452 const SwNodes& rNodes = pAPos->nNode.GetNodes();
1453 SwTxtNode* pTxtNode;
1454 if( 0 != ( pTxtNode = pAPos->nNode.GetNode().GetTxtNode() ))
1455 {
1456 bEmptyNode = !pTxtNode->GetTxt().Len();
1457 if( bEmptyNode )
1458 {
1459 //last node information is only necessary to know for the last TextNode
1460 SwNodeIndex aTmp( pAPos->nNode );
1461 ++aTmp;//goto next node
1462 while (aTmp.GetNode().IsEndNode())
1463 {
1464 if( aTmp == rNodes.GetEndOfContent().GetIndex() )
1465 {
1466 bLastNode = true;
1467 break;
1468 }
1469 ++aTmp;
1470 }
1471 }
1472 }
1473 bAdd = bLastNode && bEmptyNode;
1474 if( !bAdd )
1475 {
1476 if( bAtCntnt )
1477 bAdd = nEndContentIndex > 0;
1478 else
1479 bAdd = pAPos->nContent <= nEndContentIndex;
1480 }
1481 }
1482 if( bAdd )
1483 aArr.Insert( _ZSortFly( pFmt, pAnchor, nArrLen + aArr.Count() ));
1484 }
1485 }
1486
1487 //Alle kopierten (also die neu erzeugten) Rahmen in ein weiteres Array
1488 //stopfen. Dort sizten sie passend zu den Originalen, damit hinterher
1489 //die Chains entsprechend aufgebaut werden koennen.
1490 SvPtrarr aNewArr( 10, 10 );
1491
1492 for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
1493 {
1494 const _ZSortFly& rZSortFly = aArr[ n ];
1495
1496 // --> OD 2006-01-04 #i59964#
1497 // correct determination of new anchor position
1498 SwFmtAnchor aAnchor( *rZSortFly.GetAnchor() );
1499 SwPosition* pNewPos = (SwPosition*)aAnchor.GetCntntAnchor();
1500 // for at-paragraph and at-character anchored objects the new anchor
1501 // position can *not* be determined by the difference of the current
1502 // anchor position to the start of the copied range, because not
1503 // complete selected sections in the copied range aren't copied - see
1504 // method <SwNodes::_CopyNodes(..)>.
1505 // Thus, the new anchor position in the destination document is found
1506 // by counting the text nodes.
1507 if ((aAnchor.GetAnchorId() == FLY_AT_PARA) ||
1508 (aAnchor.GetAnchorId() == FLY_AT_CHAR) )
1509 {
1510 // First, determine number of anchor text node in the copied range.
1511 // Note: The anchor text node *have* to be inside the copied range.
1512 sal_uLong nAnchorTxtNdNumInRange( 0L );
1513 bool bAnchorTxtNdFound( false );
1514 SwNodeIndex aIdx( rRg.aStart );
1515 while ( !bAnchorTxtNdFound && aIdx <= rRg.aEnd )
1516 {
1517 if ( aIdx.GetNode().IsTxtNode() )
1518 {
1519 ++nAnchorTxtNdNumInRange;
1520 bAnchorTxtNdFound = aAnchor.GetCntntAnchor()->nNode == aIdx;
1521 }
1522
1523 ++aIdx;
1524 }
1525 if ( !bAnchorTxtNdFound )
1526 {
1527 // This case can *not* happen, but to be robust take the first
1528 // text node in the destination document.
1529 ASSERT( false,
1530 "<SwDoc::_CopyFlyInFly(..)> - anchor text node in copied range not found" );
1531 nAnchorTxtNdNumInRange = 1;
1532 }
1533 // Second, search corresponding text node in destination document
1534 // by counting forward from start insert position <rStartIdx> the
1535 // determined number of text nodes.
1536 aIdx = rStartIdx;
1537 SwNodeIndex aAnchorNdIdx( rStartIdx );
1538 const SwNode& aEndOfContentNd =
1539 aIdx.GetNode().GetNodes().GetEndOfContent();
1540 while ( nAnchorTxtNdNumInRange > 0 &&
1541 &(aIdx.GetNode()) != &aEndOfContentNd )
1542 {
1543 if ( aIdx.GetNode().IsTxtNode() )
1544 {
1545 --nAnchorTxtNdNumInRange;
1546 aAnchorNdIdx = aIdx;
1547 }
1548
1549 ++aIdx;
1550 }
1551 if ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1552 {
1553 // This case can *not* happen, but to be robust take the first
1554 // text node in the destination document.
1555 ASSERT( false,
1556 "<SwDoc::_CopyFlyInFly(..)> - found anchor node index isn't a text node" );
1557 aAnchorNdIdx = rStartIdx;
1558 while ( !aAnchorNdIdx.GetNode().IsTxtNode() )
1559 {
1560 ++aAnchorNdIdx;
1561 }
1562 }
1563 // apply found anchor text node as new anchor position
1564 pNewPos->nNode = aAnchorNdIdx;
1565 }
1566 else
1567 {
1568 long nOffset = pNewPos->nNode.GetIndex() - rRg.aStart.GetIndex();
1569 SwNodeIndex aIdx( rStartIdx, nOffset );
1570 pNewPos->nNode = aIdx;
1571 }
1572 // <--
1573 // die am Zeichen Flys wieder ans das vorgegebene Zeichen setzen
1574 if ((FLY_AT_CHAR == aAnchor.GetAnchorId()) &&
1575 pNewPos->nNode.GetNode().IsTxtNode() )
1576 {
1577 pNewPos->nContent.Assign( (SwTxtNode*)&pNewPos->nNode.GetNode(),
1578 pNewPos->nContent.GetIndex() );
1579 }
1580 else
1581 {
1582 pNewPos->nContent.Assign( 0, 0 );
1583 }
1584
1585 // ueberpruefe Rekursion: Inhalt in "seinen eigenen" Frame
1586 // kopieren. Dann nicht kopieren
1587 sal_Bool bMakeCpy = sal_True;
1588 if( pDest == this )
1589 {
1590 const SwFmtCntnt& rCntnt = rZSortFly.GetFmt()->GetCntnt();
1591 const SwStartNode* pSNd;
1592 if( rCntnt.GetCntntIdx() &&
1593 0 != ( pSNd = rCntnt.GetCntntIdx()->GetNode().GetStartNode() ) &&
1594 pSNd->GetIndex() < rStartIdx.GetIndex() &&
1595 rStartIdx.GetIndex() < pSNd->EndOfSectionIndex() )
1596 {
1597 bMakeCpy = sal_False;
1598 aArr.Remove( n, 1 );
1599 --n;
1600 }
1601 }
1602
1603 // Format kopieren und den neuen Anker setzen
1604 if( bMakeCpy )
1605 aNewArr.Insert( pDest->CopyLayoutFmt( *rZSortFly.GetFmt(),
1606 aAnchor, false, true ), aNewArr.Count() );
1607 }
1608
1609 //Alle chains, die im Original vorhanden sind, soweit wie moeglich wieder
1610 //aufbauen.
1611 ASSERT( aArr.Count() == aNewArr.Count(), "Missing new Flys" );
1612 if ( aArr.Count() == aNewArr.Count() )
1613 {
1614 for ( sal_uInt16 n = 0; n < aArr.Count(); ++n )
1615 {
1616 const SwFrmFmt *pFmt = aArr[n].GetFmt();
1617 const SwFmtChain &rChain = pFmt->GetChain();
1618 int nCnt = 0 != rChain.GetPrev();
1619 nCnt += rChain.GetNext() ? 1: 0;
1620 for ( sal_uInt16 k = 0; nCnt && k < aArr.Count(); ++k )
1621 {
1622 const _ZSortFly &rTmp = aArr[k];
1623 const SwFrmFmt *pTmp = rTmp.GetFmt();
1624 if ( rChain.GetPrev() == pTmp )
1625 {
1626 ::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[k],
1627 (SwFlyFrmFmt*)aNewArr[n] );
1628 --nCnt;
1629 }
1630 else if ( rChain.GetNext() == pTmp )
1631 {
1632 ::lcl_ChainFmts( (SwFlyFrmFmt*)aNewArr[n],
1633 (SwFlyFrmFmt*)aNewArr[k] );
1634 --nCnt;
1635 }
1636 }
1637 }
1638 }
1639 }
1640
1641
1642
1643
1644