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