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