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( 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; 221 _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 229 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 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 310 _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 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 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 427 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 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. 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 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 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 690 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 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# 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 875 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 1327 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 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 1408 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