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 <svl/itemiter.hxx> 32 33 #include <hintids.hxx> 34 #include <hints.hxx> 35 #include <fmtflcnt.hxx> 36 #include <fmtanchr.hxx> 37 #include <fmtcntnt.hxx> 38 #include <txtflcnt.hxx> 39 #include <frmfmt.hxx> 40 #include <flyfrm.hxx> 41 #include <UndoCore.hxx> 42 #include <UndoDraw.hxx> 43 #include <rolbck.hxx> // fuer die Attribut History 44 #include <doc.hxx> 45 #include <docary.hxx> 46 #include <rootfrm.hxx> 47 #include <swundo.hxx> // fuer die UndoIds 48 #include <pam.hxx> 49 #include <ndtxt.hxx> 50 // OD 26.06.2003 #108784# 51 #include <dcontact.hxx> 52 #include <ndole.hxx> 53 54 55 //--------------------------------------------------------------------- 56 // SwUndoLayBase ///////////////////////////////////////////////////////// 57 58 SwUndoFlyBase::SwUndoFlyBase( SwFrmFmt* pFormat, SwUndoId nUndoId ) 59 : SwUndo( nUndoId ), pFrmFmt( pFormat ) 60 { 61 } 62 63 SwUndoFlyBase::~SwUndoFlyBase() 64 { 65 if( bDelFmt ) // loeschen waehrend eines Undo's ?? 66 delete pFrmFmt; 67 } 68 69 void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrm) 70 { 71 SwDoc *const pDoc = & rContext.GetDoc(); 72 73 // ins Array wieder eintragen 74 SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts(); 75 rFlyFmts.Insert( pFrmFmt, rFlyFmts.Count() ); 76 77 // OD 26.06.2003 #108784# - insert 'master' drawing object into drawing page 78 if ( RES_DRAWFRMFMT == pFrmFmt->Which() ) 79 { 80 SwDrawContact* pDrawContact = 81 static_cast<SwDrawContact*>(pFrmFmt->FindContactObj()); 82 if ( pDrawContact ) 83 { 84 pDrawContact->InsertMasterIntoDrawPage(); 85 // --> OD 2005-01-31 #i40845# - follow-up of #i35635# 86 // move object to visible layer 87 pDrawContact->MoveObjToVisibleLayer( pDrawContact->GetMaster() ); 88 // <-- 89 } 90 } 91 92 SwFmtAnchor aAnchor( (RndStdIds)nRndId ); 93 94 if (FLY_AT_PAGE == nRndId) 95 { 96 aAnchor.SetPageNum( (sal_uInt16)nNdPgPos ); 97 } 98 else 99 { 100 SwPosition aNewPos(pDoc->GetNodes().GetEndOfContent()); 101 aNewPos.nNode = nNdPgPos; 102 if ((FLY_AS_CHAR == nRndId) || (FLY_AT_CHAR == nRndId)) 103 { 104 aNewPos.nContent.Assign( aNewPos.nNode.GetNode().GetCntntNode(), 105 nCntPos ); 106 } 107 aAnchor.SetAnchor( &aNewPos ); 108 } 109 110 pFrmFmt->SetFmtAttr( aAnchor ); // Anker neu setzen 111 112 if( RES_DRAWFRMFMT != pFrmFmt->Which() ) 113 { 114 // Content holen und -Attribut neu setzen 115 SwNodeIndex aIdx( pDoc->GetNodes() ); 116 RestoreSection( pDoc, &aIdx, SwFlyStartNode ); 117 pFrmFmt->SetFmtAttr( SwFmtCntnt( aIdx.GetNode().GetStartNode() )); 118 } 119 120 //JP 18.12.98: Bug 60505 - InCntntAttribut erst setzen, wenn der Inhalt 121 // vorhanden ist! Sonst wuerde das Layout den Fly vorher 122 // formatieren, aber keine Inhalt finden; so geschene bei 123 // Grafiken aus dem Internet 124 if (FLY_AS_CHAR == nRndId) 125 { 126 // es muss mindestens das Attribut im TextNode stehen 127 SwCntntNode* pCNd = aAnchor.GetCntntAnchor()->nNode.GetNode().GetCntntNode(); 128 ASSERT( pCNd->IsTxtNode(), "no Text Node at position." ); 129 SwFmtFlyCnt aFmt( pFrmFmt ); 130 static_cast<SwTxtNode*>(pCNd)->InsertItem( aFmt, nCntPos, nCntPos ); 131 } 132 133 pFrmFmt->MakeFrms(); 134 135 if( bShowSelFrm ) 136 { 137 rContext.SetSelections(pFrmFmt, 0); 138 } 139 140 if( GetHistory() ) 141 GetHistory()->Rollback( pDoc ); 142 143 switch( nRndId ) 144 { 145 case FLY_AS_CHAR: 146 case FLY_AT_CHAR: 147 { 148 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor(); 149 nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex(); 150 nCntPos = rAnchor.GetCntntAnchor()->nContent.GetIndex(); 151 } 152 break; 153 case FLY_AT_PARA: 154 case FLY_AT_FLY: 155 { 156 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor(); 157 nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex(); 158 } 159 break; 160 case FLY_AT_PAGE: 161 break; 162 } 163 bDelFmt = sal_False; 164 } 165 166 void SwUndoFlyBase::DelFly( SwDoc* pDoc ) 167 { 168 bDelFmt = sal_True; // im DTOR das Format loeschen 169 pFrmFmt->DelFrms(); // Frms vernichten. 170 171 // alle Uno-Objecte sollten sich jetzt abmelden 172 { 173 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrmFmt ); 174 pFrmFmt->ModifyNotification( &aMsgHint, &aMsgHint ); 175 } 176 177 if ( RES_DRAWFRMFMT != pFrmFmt->Which() ) 178 { 179 // gibt es ueberhaupt Inhalt, dann sicher diesen 180 const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); 181 ASSERT( rCntnt.GetCntntIdx(), "Fly ohne Inhalt" ); 182 183 SaveSection( pDoc, *rCntnt.GetCntntIdx() ); 184 ((SwFmtCntnt&)rCntnt).SetNewCntntIdx( (const SwNodeIndex*)0 ); 185 } 186 // OD 02.07.2003 #108784# - remove 'master' drawing object from drawing page 187 else if ( RES_DRAWFRMFMT == pFrmFmt->Which() ) 188 { 189 SwDrawContact* pDrawContact = 190 static_cast<SwDrawContact*>(pFrmFmt->FindContactObj()); 191 if ( pDrawContact ) 192 { 193 pDrawContact->RemoveMasterFromDrawPage(); 194 } 195 } 196 197 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor(); 198 const SwPosition* pPos = rAnchor.GetCntntAnchor(); 199 // die Positionen im Nodes-Array haben sich verschoben 200 nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId()); 201 if (FLY_AS_CHAR == nRndId) 202 { 203 nNdPgPos = pPos->nNode.GetIndex(); 204 nCntPos = pPos->nContent.GetIndex(); 205 SwTxtNode *const pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 206 OSL_ENSURE(pTxtNd, "no Textnode"); 207 SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>( 208 pTxtNd->GetTxtAttrForCharAt( nCntPos, RES_TXTATR_FLYCNT ) ); 209 // Attribut steht noch im TextNode, loeschen 210 if( pAttr && pAttr->GetFlyCnt().GetFrmFmt() == pFrmFmt ) 211 { 212 // Pointer auf 0, nicht loeschen 213 ((SwFmtFlyCnt&)pAttr->GetFlyCnt()).SetFlyFmt(); 214 SwIndex aIdx( pPos->nContent ); 215 pTxtNd->EraseText( aIdx, 1 ); 216 } 217 } 218 else if (FLY_AT_CHAR == nRndId) 219 { 220 nNdPgPos = pPos->nNode.GetIndex(); 221 nCntPos = pPos->nContent.GetIndex(); 222 } 223 else if ((FLY_AT_PARA == nRndId) || (FLY_AT_FLY == nRndId)) 224 { 225 nNdPgPos = pPos->nNode.GetIndex(); 226 } 227 else 228 { 229 nNdPgPos = rAnchor.GetPageNum(); 230 } 231 232 pFrmFmt->ResetFmtAttr( RES_ANCHOR ); // Anchor loeschen 233 234 235 // aus dem Array austragen 236 SwSpzFrmFmts& rFlyFmts = *(SwSpzFrmFmts*)pDoc->GetSpzFrmFmts(); 237 rFlyFmts.Remove( rFlyFmts.GetPos( pFrmFmt )); 238 } 239 240 // SwUndoInsLayFmt /////////////////////////////////////////////////////// 241 242 SwUndoInsLayFmt::SwUndoInsLayFmt( SwFrmFmt* pFormat, sal_uLong nNodeIdx, xub_StrLen nCntIdx ) 243 : SwUndoFlyBase( pFormat, RES_DRAWFRMFMT == pFormat->Which() ? 244 UNDO_INSDRAWFMT : UNDO_INSLAYFMT ), 245 mnCrsrSaveIndexPara( nNodeIdx ), mnCrsrSaveIndexPos( nCntIdx ) 246 { 247 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor(); 248 nRndId = static_cast<sal_uInt16>(rAnchor.GetAnchorId()); 249 bDelFmt = sal_False; 250 switch( nRndId ) 251 { 252 case FLY_AT_PAGE: 253 nNdPgPos = rAnchor.GetPageNum(); 254 break; 255 case FLY_AT_PARA: 256 case FLY_AT_FLY: 257 nNdPgPos = rAnchor.GetCntntAnchor()->nNode.GetIndex(); 258 break; 259 case FLY_AS_CHAR: 260 case FLY_AT_CHAR: 261 { 262 const SwPosition* pPos = rAnchor.GetCntntAnchor(); 263 nCntPos = pPos->nContent.GetIndex(); 264 nNdPgPos = pPos->nNode.GetIndex(); 265 } 266 break; 267 default: 268 ASSERT( sal_False, "Was denn fuer ein FlyFrame?" ); 269 } 270 } 271 272 SwUndoInsLayFmt::~SwUndoInsLayFmt() 273 { 274 } 275 276 void SwUndoInsLayFmt::UndoImpl(::sw::UndoRedoContext & rContext) 277 { 278 SwDoc & rDoc(rContext.GetDoc()); 279 const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); 280 if( rCntnt.GetCntntIdx() ) // kein Inhalt 281 { 282 bool bRemoveIdx = true; 283 if( mnCrsrSaveIndexPara > 0 ) 284 { 285 SwTxtNode *const pNode = 286 rDoc.GetNodes()[mnCrsrSaveIndexPara]->GetTxtNode(); 287 if( pNode ) 288 { 289 SwNodeIndex aIdx( rDoc.GetNodes(), 290 rCntnt.GetCntntIdx()->GetIndex() ); 291 SwNodeIndex aEndIdx( rDoc.GetNodes(), 292 aIdx.GetNode().EndOfSectionIndex() ); 293 SwIndex aIndex( pNode, mnCrsrSaveIndexPos ); 294 SwPosition aPos( *pNode, aIndex ); 295 rDoc.CorrAbs( aIdx, aEndIdx, aPos, sal_True ); 296 bRemoveIdx = false; 297 } 298 } 299 if( bRemoveIdx ) 300 { 301 RemoveIdxFromSection( rDoc, rCntnt.GetCntntIdx()->GetIndex() ); 302 } 303 } 304 DelFly(& rDoc); 305 } 306 307 void SwUndoInsLayFmt::RedoImpl(::sw::UndoRedoContext & rContext) 308 { 309 InsFly(rContext); 310 } 311 312 void SwUndoInsLayFmt::RepeatImpl(::sw::RepeatContext & rContext) 313 { 314 SwDoc *const pDoc = & rContext.GetDoc(); 315 // erfrage und setze den Anker neu 316 SwFmtAnchor aAnchor( pFrmFmt->GetAnchor() ); 317 if ((FLY_AT_PARA == aAnchor.GetAnchorId()) || 318 (FLY_AT_CHAR == aAnchor.GetAnchorId()) || 319 (FLY_AS_CHAR == aAnchor.GetAnchorId())) 320 { 321 SwPosition aPos( *rContext.GetRepeatPaM().GetPoint() ); 322 if (FLY_AT_PARA == aAnchor.GetAnchorId()) 323 { 324 aPos.nContent.Assign( 0, 0 ); 325 } 326 aAnchor.SetAnchor( &aPos ); 327 } 328 else if( FLY_AT_FLY == aAnchor.GetAnchorId() ) 329 { 330 SwStartNode const*const pSttNd = 331 rContext.GetRepeatPaM().GetNode()->FindFlyStartNode(); 332 if( pSttNd ) 333 { 334 SwPosition aPos( *pSttNd ); 335 aAnchor.SetAnchor( &aPos ); 336 } 337 else 338 { 339 return ; 340 } 341 } 342 else if (FLY_AT_PAGE == aAnchor.GetAnchorId()) 343 { 344 aAnchor.SetPageNum( pDoc->GetCurrentLayout()->GetCurrPage( &rContext.GetRepeatPaM() )); 345 } 346 else { 347 ASSERT( sal_False, "was fuer ein Anker ist es denn nun?" ); 348 } 349 350 SwFrmFmt* pFlyFmt = pDoc->CopyLayoutFmt( *pFrmFmt, aAnchor, true, true ); 351 (void) pFlyFmt; 352 //FIXME nobody ever did anything with this selection: 353 // rContext.SetSelections(pFlyFmt, 0); 354 } 355 356 // #111827# 357 String SwUndoInsLayFmt::GetComment() const 358 { 359 String aResult; 360 361 // HACK: disable caching: 362 // the SfxUndoManager calls GetComment() too early: the pFrmFmt does not 363 // have a SwDrawContact yet, so it will fall back to SwUndo::GetComment(), 364 // which sets pComment to a wrong value. 365 // if (! pComment) 366 if (true) 367 { 368 /* 369 If frame format is present and has an SdrObject use the undo 370 comment of the SdrObject. Otherwise use the default comment. 371 */ 372 373 bool bDone = false; 374 if (pFrmFmt) 375 { 376 const SdrObject * pSdrObj = pFrmFmt->FindSdrObject(); 377 if ( pSdrObj ) 378 { 379 aResult = SdrUndoNewObj::GetComment( *pSdrObj ); 380 bDone = true; 381 } 382 } 383 384 if (! bDone) 385 aResult = SwUndo::GetComment(); 386 } 387 else 388 aResult = *pComment; 389 390 return aResult; 391 } 392 393 // SwUndoDelLayFmt /////////////////////////////////////////////////////// 394 395 static SwUndoId 396 lcl_GetSwUndoId(SwFrmFmt *const pFrmFmt) 397 { 398 if (RES_DRAWFRMFMT != pFrmFmt->Which()) 399 { 400 const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); 401 OSL_ENSURE( rCntnt.GetCntntIdx(), "Fly without content" ); 402 403 SwNodeIndex firstNode(*rCntnt.GetCntntIdx(), 1); 404 SwNoTxtNode *const pNoTxtNode(firstNode.GetNode().GetNoTxtNode()); 405 if (pNoTxtNode && pNoTxtNode->IsGrfNode()) 406 { 407 return UNDO_DELGRF; 408 } 409 else if (pNoTxtNode && pNoTxtNode->IsOLENode()) 410 { 411 // surprisingly not UNDO_DELOLE, which does not seem to work 412 return UNDO_DELETE; 413 } 414 } 415 return UNDO_DELLAYFMT; 416 } 417 418 SwUndoDelLayFmt::SwUndoDelLayFmt( SwFrmFmt* pFormat ) 419 : SwUndoFlyBase( pFormat, lcl_GetSwUndoId(pFormat) ) 420 , bShowSelFrm( sal_True ) 421 { 422 SwDoc* pDoc = pFormat->GetDoc(); 423 DelFly( pDoc ); 424 } 425 426 SwRewriter SwUndoDelLayFmt::GetRewriter() const 427 { 428 SwRewriter aRewriter; 429 430 SwDoc * pDoc = pFrmFmt->GetDoc(); 431 432 if (pDoc) 433 { 434 SwNodeIndex* pIdx = GetMvSttIdx(); 435 if( 1 == GetMvNodeCnt() && pIdx) 436 { 437 SwNode *const pNd = & pIdx->GetNode(); 438 439 if ( pNd->IsNoTxtNode() && pNd->IsOLENode()) 440 { 441 SwOLENode * pOLENd = pNd->GetOLENode(); 442 443 aRewriter.AddRule(UNDO_ARG1, pOLENd->GetDescription()); 444 } 445 } 446 } 447 448 return aRewriter; 449 } 450 451 void SwUndoDelLayFmt::UndoImpl(::sw::UndoRedoContext & rContext) 452 { 453 InsFly( rContext, bShowSelFrm ); 454 } 455 456 void SwUndoDelLayFmt::RedoImpl(::sw::UndoRedoContext & rContext) 457 { 458 SwDoc & rDoc(rContext.GetDoc()); 459 const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); 460 if( rCntnt.GetCntntIdx() ) // kein Inhalt 461 { 462 RemoveIdxFromSection(rDoc, rCntnt.GetCntntIdx()->GetIndex()); 463 } 464 465 DelFly(& rDoc); 466 } 467 468 void SwUndoDelLayFmt::RedoForRollback() 469 { 470 const SwFmtCntnt& rCntnt = pFrmFmt->GetCntnt(); 471 if( rCntnt.GetCntntIdx() ) // kein Inhalt 472 RemoveIdxFromSection( *pFrmFmt->GetDoc(), 473 rCntnt.GetCntntIdx()->GetIndex() ); 474 475 DelFly( pFrmFmt->GetDoc() ); 476 } 477 478 // SwUndoSetFlyFmt /////////////////////////////////////////////////////// 479 480 SwUndoSetFlyFmt::SwUndoSetFlyFmt( SwFrmFmt& rFlyFmt, SwFrmFmt& rNewFrmFmt ) 481 : SwUndo( UNDO_SETFLYFRMFMT ), SwClient( &rFlyFmt ), pFrmFmt( &rFlyFmt ), 482 pOldFmt( (SwFrmFmt*)rFlyFmt.DerivedFrom() ), pNewFmt( &rNewFrmFmt ), 483 pItemSet( new SfxItemSet( *rFlyFmt.GetAttrSet().GetPool(), 484 rFlyFmt.GetAttrSet().GetRanges() )), 485 nOldNode( 0 ), nNewNode( 0 ), 486 nOldCntnt( 0 ), nNewCntnt( 0 ), 487 nOldAnchorTyp( 0 ), nNewAnchorTyp( 0 ), bAnchorChgd( sal_False ) 488 { 489 } 490 491 SwRewriter SwUndoSetFlyFmt::GetRewriter() const 492 { 493 SwRewriter aRewriter; 494 495 if (pNewFmt) 496 aRewriter.AddRule(UNDO_ARG1, pNewFmt->GetName()); 497 498 return aRewriter; 499 } 500 501 502 SwUndoSetFlyFmt::~SwUndoSetFlyFmt() 503 { 504 delete pItemSet; 505 } 506 507 void SwUndoSetFlyFmt::DeRegisterFromFormat( SwFmt& rFmt ) 508 { 509 rFmt.Remove(this); 510 } 511 512 void SwUndoSetFlyFmt::GetAnchor( SwFmtAnchor& rAnchor, 513 sal_uLong nNode, xub_StrLen nCntnt ) 514 { 515 RndStdIds nAnchorTyp = rAnchor.GetAnchorId(); 516 if (FLY_AT_PAGE != nAnchorTyp) 517 { 518 SwNode* pNd = pFrmFmt->GetDoc()->GetNodes()[ nNode ]; 519 520 if( FLY_AT_FLY == nAnchorTyp 521 ? ( !pNd->IsStartNode() || SwFlyStartNode != 522 ((SwStartNode*)pNd)->GetStartNodeType() ) 523 : !pNd->IsTxtNode() ) 524 { 525 pNd = 0; // invalid position 526 } 527 else 528 { 529 SwPosition aPos( *pNd ); 530 if ((FLY_AS_CHAR == nAnchorTyp) || 531 (FLY_AT_CHAR == nAnchorTyp)) 532 { 533 if ( nCntnt > static_cast<SwTxtNode*>(pNd)->GetTxt().Len() ) 534 { 535 pNd = 0; // invalid position 536 } 537 else 538 { 539 aPos.nContent.Assign(static_cast<SwTxtNode*>(pNd), nCntnt); 540 } 541 } 542 if ( pNd ) 543 { 544 rAnchor.SetAnchor( &aPos ); 545 } 546 } 547 548 if( !pNd ) 549 { 550 // ungueltige Position - setze auf 1. Seite 551 rAnchor.SetType( FLY_AT_PAGE ); 552 rAnchor.SetPageNum( 1 ); 553 } 554 } 555 else 556 rAnchor.SetPageNum( nCntnt ); 557 } 558 559 void SwUndoSetFlyFmt::UndoImpl(::sw::UndoRedoContext & rContext) 560 { 561 SwDoc & rDoc = rContext.GetDoc(); 562 563 // ist das neue Format noch vorhanden ?? 564 if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pOldFmt ) ) 565 { 566 if( bAnchorChgd ) 567 pFrmFmt->DelFrms(); 568 569 if( pFrmFmt->DerivedFrom() != pOldFmt ) 570 pFrmFmt->SetDerivedFrom( pOldFmt ); 571 572 SfxItemIter aIter( *pItemSet ); 573 const SfxPoolItem* pItem = aIter.GetCurItem(); 574 while( pItem ) 575 { 576 if( IsInvalidItem( pItem )) 577 pFrmFmt->ResetFmtAttr( pItemSet->GetWhichByPos( 578 aIter.GetCurPos() )); 579 else 580 pFrmFmt->SetFmtAttr( *pItem ); 581 582 if( aIter.IsAtEnd() ) 583 break; 584 pItem = aIter.NextItem(); 585 } 586 587 if( bAnchorChgd ) 588 { 589 const SwFmtAnchor& rOldAnch = pFrmFmt->GetAnchor(); 590 if (FLY_AS_CHAR == rOldAnch.GetAnchorId()) 591 { 592 // Bei InCntnt's wird es spannend: Das TxtAttribut muss 593 // vernichtet werden. Leider reisst dies neben den Frms 594 // auch noch das Format mit in sein Grab. Um dass zu 595 // unterbinden loesen wir vorher die Verbindung zwischen 596 // Attribut und Format. 597 const SwPosition *pPos = rOldAnch.GetCntntAnchor(); 598 SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode(); 599 ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." ); 600 const xub_StrLen nIdx = pPos->nContent.GetIndex(); 601 SwTxtAttr * pHnt = pTxtNode->GetTxtAttrForCharAt( 602 nIdx, RES_TXTATR_FLYCNT ); 603 ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT, 604 "Missing FlyInCnt-Hint." ); 605 ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pFrmFmt, 606 "Wrong TxtFlyCnt-Hint." ); 607 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt(); 608 609 // Die Verbindung ist geloest, jetzt muss noch das Attribut 610 // vernichtet werden. 611 pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx ); 612 } 613 614 // Anker umsetzen 615 SwFmtAnchor aNewAnchor( (RndStdIds) nOldAnchorTyp ); 616 GetAnchor( aNewAnchor, nOldNode, nOldCntnt ); 617 pFrmFmt->SetFmtAttr( aNewAnchor ); 618 619 if (FLY_AS_CHAR == aNewAnchor.GetAnchorId()) 620 { 621 SwPosition* pPos = (SwPosition*)aNewAnchor.GetCntntAnchor(); 622 SwFmtFlyCnt aFmt( pFrmFmt ); 623 pPos->nNode.GetNode().GetTxtNode()->InsertItem( aFmt, 624 nOldCntnt, 0 ); 625 } 626 627 pFrmFmt->MakeFrms(); 628 } 629 rContext.SetSelections(pFrmFmt, 0); 630 } 631 } 632 633 void SwUndoSetFlyFmt::RedoImpl(::sw::UndoRedoContext & rContext) 634 { 635 SwDoc & rDoc = rContext.GetDoc(); 636 637 // ist das neue Format noch vorhanden ?? 638 if( USHRT_MAX != rDoc.GetFrmFmts()->GetPos( (const SwFrmFmtPtr)pNewFmt ) ) 639 { 640 641 if( bAnchorChgd ) 642 { 643 SwFmtAnchor aNewAnchor( (RndStdIds) nNewAnchorTyp ); 644 GetAnchor( aNewAnchor, nNewNode, nNewCntnt ); 645 SfxItemSet aSet( rDoc.GetAttrPool(), aFrmFmtSetRange ); 646 aSet.Put( aNewAnchor ); 647 rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, &aSet ); 648 } 649 else 650 rDoc.SetFrmFmtToFly( *pFrmFmt, *pNewFmt, 0 ); 651 652 rContext.SetSelections(pFrmFmt, 0); 653 } 654 } 655 656 void SwUndoSetFlyFmt::PutAttr( sal_uInt16 nWhich, const SfxPoolItem* pItem ) 657 { 658 if( pItem && pItem != GetDfltAttr( nWhich ) ) 659 { 660 // Sonderbehandlung fuer den Anchor 661 if( RES_ANCHOR == nWhich ) 662 { 663 // nur den 1. Ankerwechsel vermerken 664 ASSERT( !bAnchorChgd, "mehrfacher Ankerwechsel nicht erlaubt!" ); 665 666 bAnchorChgd = sal_True; 667 668 const SwFmtAnchor* pAnchor = (SwFmtAnchor*)pItem; 669 switch( nOldAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) ) 670 { 671 case FLY_AS_CHAR: 672 case FLY_AT_CHAR: 673 nOldCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex(); 674 case FLY_AT_PARA: 675 case FLY_AT_FLY: 676 nOldNode = pAnchor->GetCntntAnchor()->nNode.GetIndex(); 677 break; 678 679 default: 680 nOldCntnt = pAnchor->GetPageNum(); 681 } 682 683 pAnchor = (SwFmtAnchor*)&pFrmFmt->GetAnchor(); 684 switch( nNewAnchorTyp = static_cast<sal_uInt16>(pAnchor->GetAnchorId()) ) 685 { 686 case FLY_AS_CHAR: 687 case FLY_AT_CHAR: 688 nNewCntnt = pAnchor->GetCntntAnchor()->nContent.GetIndex(); 689 case FLY_AT_PARA: 690 case FLY_AT_FLY: 691 nNewNode = pAnchor->GetCntntAnchor()->nNode.GetIndex(); 692 break; 693 694 default: 695 nNewCntnt = pAnchor->GetPageNum(); 696 } 697 } 698 else 699 pItemSet->Put( *pItem ); 700 } 701 else 702 pItemSet->InvalidateItem( nWhich ); 703 } 704 705 void SwUndoSetFlyFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* ) 706 { 707 if( pOld ) 708 { 709 sal_uInt16 nWhich = pOld->Which(); 710 711 if( nWhich < POOLATTR_END ) 712 PutAttr( nWhich, pOld ); 713 else if( RES_ATTRSET_CHG == nWhich ) 714 { 715 SfxItemIter aIter( *((SwAttrSetChg*)pOld)->GetChgSet() ); 716 const SfxPoolItem* pItem = aIter.GetCurItem(); 717 while( pItem ) 718 { 719 PutAttr( pItem->Which(), pItem ); 720 if( aIter.IsAtEnd() ) 721 break; 722 pItem = aIter.NextItem(); 723 } 724 } 725 } 726 } 727 728