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 <tools/bigint.hxx> 32 #include "pagefrm.hxx" 33 #include "cntfrm.hxx" 34 #include "flyfrm.hxx" 35 #include "txtfrm.hxx" 36 #include <doc.hxx> 37 #include <IDocumentUndoRedo.hxx> 38 #include "viewsh.hxx" 39 #include "viewimp.hxx" 40 #include "pam.hxx" 41 #include "frmfmt.hxx" 42 #include "frmtool.hxx" 43 #include "dflyobj.hxx" 44 #include "hints.hxx" 45 #include "ndtxt.hxx" 46 #include "swundo.hxx" 47 #include "errhdl.hxx" 48 #include <editeng/ulspitem.hxx> 49 #include <editeng/lrspitem.hxx> 50 #include <fmtanchr.hxx> 51 #include <fmtornt.hxx> 52 #include <fmtfsize.hxx> 53 #include <fmtsrnd.hxx> 54 55 #include "tabfrm.hxx" 56 #include "flyfrms.hxx" 57 #include "crstate.hxx" 58 #include "sectfrm.hxx" 59 60 // OD 29.10.2003 #113049# 61 #include <tocntntanchoredobjectposition.hxx> 62 // OD 2004-05-24 #i28701# 63 #include <dcontact.hxx> 64 #include <sortedobjs.hxx> 65 // --> OD 2005-09-29 #125370#,#125957# 66 #include <layouter.hxx> 67 // <-- 68 // --> OD 2005-11-17 #i56300# 69 #include <objectformattertxtfrm.hxx> 70 // <-- 71 // --> OD 2006-03-06 #125892# 72 #include <HandleAnchorNodeChg.hxx> 73 // <-- 74 75 using namespace ::com::sun::star; 76 77 78 /************************************************************************* 79 |* 80 |* SwFlyAtCntFrm::SwFlyAtCntFrm() 81 |* 82 |* Ersterstellung MA 11. Nov. 92 83 |* Letzte Aenderung MA 09. Apr. 99 84 |* 85 |*************************************************************************/ 86 87 SwFlyAtCntFrm::SwFlyAtCntFrm( SwFlyFrmFmt *pFmt, SwFrm* pSib, SwFrm *pAnch ) : 88 SwFlyFreeFrm( pFmt, pSib, pAnch ) 89 { 90 bAtCnt = sal_True; 91 bAutoPosition = (FLY_AT_CHAR == pFmt->GetAnchor().GetAnchorId()); 92 } 93 94 // --> OD 2004-06-29 #i28701# 95 TYPEINIT1(SwFlyAtCntFrm,SwFlyFreeFrm); 96 // <-- 97 /************************************************************************* 98 |* 99 |* SwFlyAtCntFrm::Modify() 100 |* 101 |* Ersterstellung MA 08. Feb. 93 102 |* Letzte Aenderung MA 23. Nov. 94 103 |* 104 |*************************************************************************/ 105 106 void SwFlyAtCntFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew ) 107 { 108 sal_uInt16 nWhich = pNew ? pNew->Which() : 0; 109 const SwFmtAnchor *pAnch = 0; 110 111 if( RES_ATTRSET_CHG == nWhich && SFX_ITEM_SET == 112 ((SwAttrSetChg*)pNew)->GetChgSet()->GetItemState( RES_ANCHOR, sal_False, 113 (const SfxPoolItem**)&pAnch )) 114 ; // Beim GetItemState wird der AnkerPointer gesetzt ! 115 116 else if( RES_ANCHOR == nWhich ) 117 { 118 //Ankerwechsel, ich haenge mich selbst um. 119 //Es darf sich nicht um einen Wechsel des Ankertyps handeln, 120 //dies ist nur ueber die SwFEShell moeglich. 121 pAnch = (const SwFmtAnchor*)pNew; 122 } 123 124 if( pAnch ) 125 { 126 ASSERT( pAnch->GetAnchorId() == GetFmt()->GetAnchor().GetAnchorId(), 127 "Unzulaessiger Wechsel des Ankertyps." ); 128 129 //Abmelden, neuen Anker besorgen und 'dranhaengen. 130 SwRect aOld( GetObjRectWithSpaces() ); 131 SwPageFrm *pOldPage = FindPageFrm(); 132 const SwFrm *pOldAnchor = GetAnchorFrm(); 133 SwCntntFrm *pCntnt = (SwCntntFrm*)GetAnchorFrm(); 134 AnchorFrm()->RemoveFly( this ); 135 136 const sal_Bool bBodyFtn = (pCntnt->IsInDocBody() || pCntnt->IsInFtn()); 137 138 //Den neuen Anker anhand des NodeIdx suchen, am alten und 139 //neuen NodeIdx kann auch erkannt werden, in welche Richtung 140 //gesucht werden muss. 141 const SwNodeIndex aNewIdx( pAnch->GetCntntAnchor()->nNode ); 142 SwNodeIndex aOldIdx( *pCntnt->GetNode() ); 143 144 //fix: Umstellung, ehemals wurde in der do-while-Schleife nach vorn bzw. 145 //nach hinten gesucht; je nachdem wie welcher Index kleiner war. 146 //Das kann aber u.U. zu einer Endlosschleife fuehren. Damit 147 //wenigstens die Schleife unterbunden wird suchen wir nur in eine 148 //Richtung. Wenn der neue Anker nicht gefunden wird koennen wir uns 149 //immer noch vom Node einen Frame besorgen. Die Change, dass dies dann 150 //der richtige ist, ist gut. 151 const bool bNext = aOldIdx < aNewIdx; 152 // --> OD 2006-02-28 #125892# 153 // consider the case that at found anchor frame candidate already a 154 // fly frame of the given fly format is registered. 155 // --> OD 2006-03-15 #133407# - consider, that <pCntnt> is the already 156 // the new anchor frame. 157 bool bFound( aOldIdx == aNewIdx ); 158 // <-- 159 while ( pCntnt && !bFound ) 160 { 161 do 162 { 163 if ( bNext ) 164 pCntnt = pCntnt->GetNextCntntFrm(); 165 else 166 pCntnt = pCntnt->GetPrevCntntFrm(); 167 } while ( pCntnt && 168 !( bBodyFtn == ( pCntnt->IsInDocBody() || 169 pCntnt->IsInFtn() ) ) ); 170 if ( pCntnt ) 171 aOldIdx = *pCntnt->GetNode(); 172 173 // --> OD 2006-02-28 #125892# 174 // check, if at found anchor frame candidate already a fly frame 175 // of the given fly frame format is registered. 176 bFound = aOldIdx == aNewIdx; 177 if ( bFound && pCntnt->GetDrawObjs() ) 178 { 179 SwFrmFmt* pMyFlyFrmFmt( &GetFrmFmt() ); 180 SwSortedObjs &rObjs = *pCntnt->GetDrawObjs(); 181 for( sal_uInt16 i = 0; i < rObjs.Count(); ++i) 182 { 183 SwFlyFrm* pFlyFrm = dynamic_cast<SwFlyFrm*>(rObjs[i]); 184 if ( pFlyFrm && 185 &(pFlyFrm->GetFrmFmt()) == pMyFlyFrmFmt ) 186 { 187 bFound = false; 188 break; 189 } 190 } 191 } 192 // <-- 193 } 194 // <-- 195 if ( !pCntnt ) 196 { 197 SwCntntNode *pNode = aNewIdx.GetNode().GetCntntNode(); 198 pCntnt = pNode->getLayoutFrm( getRootFrm(), &pOldAnchor->Frm().Pos(), 0, sal_False ); 199 ASSERT( pCntnt, "Neuen Anker nicht gefunden" ); 200 } 201 //Flys haengen niemals an einem Follow sondern immer am 202 //Master, den suchen wir uns jetzt. 203 SwCntntFrm* pFlow = pCntnt; 204 while ( pFlow->IsFollow() ) 205 pFlow = pFlow->FindMaster(); 206 pCntnt = pFlow; 207 208 //und schwupp angehaengt das teil... 209 pCntnt->AppendFly( this ); 210 if ( pOldPage && pOldPage != FindPageFrm() ) 211 NotifyBackground( pOldPage, aOld, PREP_FLY_LEAVE ); 212 213 //Fix(3495) 214 _InvalidatePos(); 215 InvalidatePage(); 216 SetNotifyBack(); 217 // --> OD 2004-06-24 #i28701# - reset member <maLastCharRect> and 218 // <mnLastTopOfLine> for to-character anchored objects. 219 ClearCharRectAndTopOfLine(); 220 } 221 else 222 SwFlyFrm::Modify( pOld, pNew ); 223 } 224 225 /************************************************************************* 226 |* 227 |* SwFlyAtCntFrm::MakeAll() 228 |* 229 |* Beschreibung Bei einem Absatzgebunden Fly kann es durchaus sein, 230 |* das der Anker auf die Veraenderung des Flys reagiert. Auf diese 231 |* Reaktion hat der Fly natuerlich auch wieder zu reagieren. 232 |* Leider kann dies zu Oszillationen fuehren z.b. Der Fly will nach 233 |* unten, dadurch kann der Inhalt nach oben, der TxtFrm wird kleiner, 234 |* der Fly muss wieder hoeher woduch der Text wieder nach unten 235 |* verdraengt wird... 236 |* Um derartige Oszillationen zu vermeiden, wird ein kleiner Positions- 237 |* stack aufgebaut. Wenn der Fly ein Position erreicht, die er bereits 238 |* einmal einnahm, so brechen wir den Vorgang ab. Um keine Risiken 239 |* einzugehen, wird der Positionsstack so aufgebaut, dass er fuenf 240 |* Positionen zurueckblickt. 241 |* Wenn der Stack ueberlaeuft, wird ebenfalls abgebrochen. 242 |* Der Abbruch fuer dazu, dass der Fly am Ende eine unguenste Position 243 |* einnimmt. Damit es nicht durch einen wiederholten Aufruf von 244 |* Aussen zu einer 'grossen Oszillation' kommen kann wird im Abbruch- 245 |* fall das Attribut des Rahmens auf automatische Ausrichtung oben 246 |* eingestellt. 247 |* 248 |* Ersterstellung MA 12. Nov. 92 249 |* Letzte Aenderung MA 20. Sep. 96 250 |* 251 |*************************************************************************/ 252 //Wir brauchen ein Paar Hilfsklassen zur Kontrolle der Ozillation und ein paar 253 //Funktionen um die Uebersicht zu gewaehrleisten. 254 // OD 2004-08-25 #i3317# - re-factoring of the position stack 255 class SwOszControl 256 { 257 static const SwFlyFrm *pStk1; 258 static const SwFlyFrm *pStk2; 259 static const SwFlyFrm *pStk3; 260 static const SwFlyFrm *pStk4; 261 static const SwFlyFrm *pStk5; 262 263 const SwFlyFrm *pFly; 264 // --> OD 2004-08-25 #i3317# 265 sal_uInt8 mnPosStackSize; 266 std::vector<Point*> maObjPositions; 267 // <-- 268 269 public: 270 SwOszControl( const SwFlyFrm *pFrm ); 271 ~SwOszControl(); 272 bool ChkOsz(); 273 static sal_Bool IsInProgress( const SwFlyFrm *pFly ); 274 }; 275 const SwFlyFrm *SwOszControl::pStk1 = 0; 276 const SwFlyFrm *SwOszControl::pStk2 = 0; 277 const SwFlyFrm *SwOszControl::pStk3 = 0; 278 const SwFlyFrm *SwOszControl::pStk4 = 0; 279 const SwFlyFrm *SwOszControl::pStk5 = 0; 280 281 SwOszControl::SwOszControl( const SwFlyFrm *pFrm ) 282 : pFly( pFrm ), 283 // --> OD 2004-08-25 #i3317# 284 mnPosStackSize( 20 ) 285 // <-- 286 { 287 if ( !SwOszControl::pStk1 ) 288 SwOszControl::pStk1 = pFly; 289 else if ( !SwOszControl::pStk2 ) 290 SwOszControl::pStk2 = pFly; 291 else if ( !SwOszControl::pStk3 ) 292 SwOszControl::pStk3 = pFly; 293 else if ( !SwOszControl::pStk4 ) 294 SwOszControl::pStk4 = pFly; 295 else if ( !SwOszControl::pStk5 ) 296 SwOszControl::pStk5 = pFly; 297 } 298 299 SwOszControl::~SwOszControl() 300 { 301 if ( SwOszControl::pStk1 == pFly ) 302 SwOszControl::pStk1 = 0; 303 else if ( SwOszControl::pStk2 == pFly ) 304 SwOszControl::pStk2 = 0; 305 else if ( SwOszControl::pStk3 == pFly ) 306 SwOszControl::pStk3 = 0; 307 else if ( SwOszControl::pStk4 == pFly ) 308 SwOszControl::pStk4 = 0; 309 else if ( SwOszControl::pStk5 == pFly ) 310 SwOszControl::pStk5 = 0; 311 // --> OD 2004-08-25 #i3317# 312 while ( !maObjPositions.empty() ) 313 { 314 Point* pPos = maObjPositions.back(); 315 delete pPos; 316 317 maObjPositions.pop_back(); 318 } 319 // <-- 320 } 321 322 sal_Bool SwOszControl::IsInProgress( const SwFlyFrm *pFly ) 323 { 324 if ( SwOszControl::pStk1 && !pFly->IsLowerOf( SwOszControl::pStk1 ) ) 325 return sal_True; 326 if ( SwOszControl::pStk2 && !pFly->IsLowerOf( SwOszControl::pStk2 ) ) 327 return sal_True; 328 if ( SwOszControl::pStk3 && !pFly->IsLowerOf( SwOszControl::pStk3 ) ) 329 return sal_True; 330 if ( SwOszControl::pStk4 && !pFly->IsLowerOf( SwOszControl::pStk4 ) ) 331 return sal_True; 332 if ( SwOszControl::pStk5 && !pFly->IsLowerOf( SwOszControl::pStk5 ) ) 333 return sal_True; 334 return sal_False; 335 } 336 337 bool SwOszControl::ChkOsz() 338 { 339 bool bOscillationDetected = false; 340 341 if ( maObjPositions.size() == mnPosStackSize ) 342 { 343 // position stack is full -> oscillation 344 bOscillationDetected = true; 345 } 346 else 347 { 348 Point* pNewObjPos = new Point( pFly->GetObjRect().Pos() ); 349 for ( std::vector<Point*>::iterator aObjPosIter = maObjPositions.begin(); 350 aObjPosIter != maObjPositions.end(); 351 ++aObjPosIter ) 352 { 353 if ( *(pNewObjPos) == *(*aObjPosIter) ) 354 { 355 // position already occured -> oscillation 356 bOscillationDetected = true; 357 delete pNewObjPos; 358 break; 359 } 360 } 361 if ( !bOscillationDetected ) 362 { 363 maObjPositions.push_back( pNewObjPos ); 364 } 365 } 366 367 return bOscillationDetected; 368 } 369 370 void SwFlyAtCntFrm::MakeAll() 371 { 372 // OD 2004-01-19 #110582# 373 if ( !GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) ) 374 { 375 return; 376 } 377 378 if ( !SwOszControl::IsInProgress( this ) && !IsLocked() && !IsColLocked() ) 379 { 380 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> 381 if( !GetPageFrm() && GetAnchorFrm() && GetAnchorFrm()->IsInFly() ) 382 { 383 SwFlyFrm* pFly = AnchorFrm()->FindFlyFrm(); 384 SwPageFrm *pTmpPage = pFly ? pFly->FindPageFrm() : NULL; 385 if( pTmpPage ) 386 pTmpPage->AppendFlyToPage( this ); 387 } 388 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> 389 if( GetPageFrm() ) 390 { 391 bSetCompletePaintOnInvalidate = sal_True; 392 { 393 SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt(); 394 const SwFmtFrmSize &rFrmSz = GetFmt()->GetFrmSize(); 395 if( rFrmSz.GetHeightPercent() != 0xFF && 396 rFrmSz.GetHeightPercent() >= 100 ) 397 { 398 pFmt->LockModify(); 399 SwFmtSurround aMain( pFmt->GetSurround() ); 400 if ( aMain.GetSurround() == SURROUND_NONE ) 401 { 402 aMain.SetSurround( SURROUND_THROUGHT ); 403 pFmt->SetFmtAttr( aMain ); 404 } 405 pFmt->UnlockModify(); 406 } 407 } 408 409 SwOszControl aOszCntrl( this ); 410 411 // --> OD 2005-02-22 #i43255# 412 // --> OD 2005-06-07 #i50356# - format the anchor frame, which 413 // contains the anchor position. E.g., for at-character anchored 414 // object this can be the follow frame of the anchor frame. 415 const bool bFormatAnchor = 416 !static_cast<const SwTxtFrm*>( GetAnchorFrmContainingAnchPos() )->IsAnyJoinLocked() && 417 !ConsiderObjWrapInfluenceOnObjPos() && 418 !ConsiderObjWrapInfluenceOfOtherObjs(); 419 // <-- 420 421 const SwFrm* pFooter = GetAnchorFrm()->FindFooterOrHeader(); 422 if( pFooter && !pFooter->IsFooterFrm() ) 423 pFooter = NULL; 424 bool bOsz = false; 425 sal_Bool bExtra = Lower() && Lower()->IsColumnFrm(); 426 // --> OD 2004-08-25 #i3317# - boolean, to apply temporarly the 427 // 'straightforward positioning process' for the frame due to its 428 // overlapping with a previous column. 429 bool bConsiderWrapInfluenceDueToOverlapPrevCol( false ); 430 // <-- 431 // --> OD 2004-10-22 #i35911# - boolean, to apply temporarly the 432 // 'straightforward positioning process' for the frame due to fact 433 // that it causes the complete content of its layout environment 434 // to move forward. 435 // --> OD 2005-01-14 #i40444# - extend usage of this boolean: 436 // apply temporarly the 'straightforward positioning process' for 437 // the frame due to the fact that the frame clears the area for 438 // the anchor frame, thus it has to move forward. 439 bool bConsiderWrapInfluenceDueToMovedFwdAnchor( false ); 440 // <-- 441 do { 442 SWRECTFN( this ) 443 Point aOldPos( (Frm().*fnRect->fnGetPos)() ); 444 SwFlyFreeFrm::MakeAll(); 445 const bool bPosChgDueToOwnFormat = 446 aOldPos != (Frm().*fnRect->fnGetPos)(); 447 // --> OD 2004-08-25 #i3317# 448 if ( !ConsiderObjWrapInfluenceOnObjPos() && 449 OverlapsPrevColumn() ) 450 { 451 bConsiderWrapInfluenceDueToOverlapPrevCol = true; 452 } 453 // <-- 454 // OD 2004-05-12 #i28701# - no format of anchor frame, if 455 // wrapping style influence is considered on object positioning 456 if ( bFormatAnchor ) 457 { 458 SwTxtFrm* pAnchPosAnchorFrm = 459 dynamic_cast<SwTxtFrm*>(GetAnchorFrmContainingAnchPos()); 460 ASSERT( pAnchPosAnchorFrm, 461 "<SwFlyAtCntFrm::MakeAll()> - anchor frame of wrong type -> crash" ); 462 // --> OD 2006-01-27 #i58182# - For the usage of new method 463 // <SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..)> 464 // to check move forward of anchor frame due to the object 465 // positioning it's needed to know, if the object is anchored 466 // at the master frame before the anchor frame is formatted. 467 const bool bAnchoredAtMaster( !pAnchPosAnchorFrm->IsFollow() ); 468 // <-- 469 470 // --> OD 2005-11-17 #i56300# 471 // perform complete format of anchor text frame and its 472 // previous frames, which have become invalid due to the 473 // fly frame format. 474 SwObjectFormatterTxtFrm::FormatAnchorFrmAndItsPrevs( *pAnchPosAnchorFrm ); 475 // <-- 476 // --> OD 2004-10-22 #i35911# 477 // --> OD 2005-01-14 #i40444# 478 // --> OD 2006-01-27 #i58182# - usage of new method 479 // <SwObjectFormatterTxtFrm::CheckMovedFwdCondition(..)> 480 sal_uInt32 nToPageNum( 0L ); 481 bool bDummy( false ); 482 if ( SwObjectFormatterTxtFrm::CheckMovedFwdCondition( 483 *this, GetPageFrm()->GetPhyPageNum(), 484 bAnchoredAtMaster, nToPageNum, bDummy ) ) 485 { 486 bConsiderWrapInfluenceDueToMovedFwdAnchor = true; 487 // --> OD 2005-09-29 #125370#,#125957# - mark anchor text frame 488 // directly, that it is moved forward by object positioning. 489 SwTxtFrm* pAnchorTxtFrm( static_cast<SwTxtFrm*>(AnchorFrm()) ); 490 bool bInsert( true ); 491 sal_uInt32 nAnchorFrmToPageNum( 0L ); 492 const SwDoc& rDoc = *(GetFrmFmt().GetDoc()); 493 if ( SwLayouter::FrmMovedFwdByObjPos( 494 rDoc, *pAnchorTxtFrm, nAnchorFrmToPageNum ) ) 495 { 496 if ( nAnchorFrmToPageNum < nToPageNum ) 497 SwLayouter::RemoveMovedFwdFrm( rDoc, *pAnchorTxtFrm ); 498 else 499 bInsert = false; 500 } 501 if ( bInsert ) 502 { 503 SwLayouter::InsertMovedFwdFrm( rDoc, *pAnchorTxtFrm, 504 nToPageNum ); 505 } 506 // <-- 507 } 508 // <-- 509 } 510 511 if ( aOldPos != (Frm().*fnRect->fnGetPos)() || 512 ( !GetValidPosFlag() && 513 ( pFooter || bPosChgDueToOwnFormat ) ) ) 514 { 515 bOsz = aOszCntrl.ChkOsz(); 516 517 // --> OD 2006-04-13 #b6403541# 518 // special loop prevention for dedicated document: 519 if ( bOsz && 520 HasFixSize() && IsClipped() && 521 GetAnchorFrm()->GetUpper()->IsCellFrm() ) 522 { 523 SwFrmFmt* pFmt = GetFmt(); 524 const SwFmtFrmSize& rFrmSz = pFmt->GetFrmSize(); 525 if ( rFrmSz.GetWidthPercent() && 526 rFrmSz.GetHeightPercent() == 0xFF ) 527 { 528 SwFmtSurround aSurround( pFmt->GetSurround() ); 529 if ( aSurround.GetSurround() == SURROUND_NONE ) 530 { 531 pFmt->LockModify(); 532 aSurround.SetSurround( SURROUND_THROUGHT ); 533 pFmt->SetFmtAttr( aSurround ); 534 pFmt->UnlockModify(); 535 bOsz = false; 536 #if OSL_DEBUG_LEVEL > 1 537 ASSERT( false, 538 "<SwFlyAtCntFrm::MakeAll()> - special loop prevention for dedicated document of b6403541 applied" ); 539 #endif 540 } 541 } 542 } 543 // <-- 544 } 545 546 if ( bExtra && Lower() && !Lower()->GetValidPosFlag() ) 547 { 548 // Wenn ein mehrspaltiger Rahmen wg. Positionswechsel ungueltige 549 // Spalten hinterlaesst, so drehen wir lieber hier eine weitere 550 // Runde und formatieren unseren Inhalt via FormatWidthCols nochmal. 551 _InvalidateSize(); 552 bExtra = sal_False; // Sicherhaltshalber gibt es nur eine Ehrenrunde. 553 } 554 } while ( !IsValid() && !bOsz && 555 // --> OD 2004-08-25 #i3317# 556 !bConsiderWrapInfluenceDueToOverlapPrevCol && 557 // <-- 558 // --> OD 2005-01-14 #i40444# 559 !bConsiderWrapInfluenceDueToMovedFwdAnchor && 560 // <-- 561 GetFmt()->GetDoc()->IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) ); 562 563 // --> OD 2004-08-25 #i3317# - instead of attribute change apply 564 // temporarly the 'straightforward positioning process'. 565 // --> OD 2007-11-29 #i80924# 566 // handle special case during splitting of table rows 567 if ( bConsiderWrapInfluenceDueToMovedFwdAnchor && 568 GetAnchorFrm()->IsInTab() && 569 GetAnchorFrm()->IsInFollowFlowRow() ) 570 { 571 const SwFrm* pCellFrm = GetAnchorFrm(); 572 while ( pCellFrm && !pCellFrm->IsCellFrm() ) 573 { 574 pCellFrm = pCellFrm->GetUpper(); 575 } 576 if ( pCellFrm ) 577 { 578 SWRECTFN( pCellFrm ) 579 if ( (pCellFrm->Frm().*fnRect->fnGetTop)() == 0 && 580 (pCellFrm->Frm().*fnRect->fnGetHeight)() == 0 ) 581 { 582 bConsiderWrapInfluenceDueToMovedFwdAnchor = false; 583 } 584 } 585 } 586 // <-- 587 if ( bOsz || bConsiderWrapInfluenceDueToOverlapPrevCol || 588 // --> OD 2005-01-14 #i40444# 589 bConsiderWrapInfluenceDueToMovedFwdAnchor ) 590 // <-- 591 { 592 SetTmpConsiderWrapInfluence( true ); 593 SetRestartLayoutProcess( true ); 594 // --> OD 2006-07-24 #b6449874# 595 SetTmpConsiderWrapInfluenceOfOtherObjs( true ); 596 // <-- 597 } 598 // <-- 599 bSetCompletePaintOnInvalidate = sal_False; 600 } 601 } 602 } 603 604 /** method to determine, if a <MakeAll()> on the Writer fly frame is possible 605 606 OD 2004-05-11 #i28701# 607 608 @author OD 609 */ 610 bool SwFlyAtCntFrm::IsFormatPossible() const 611 { 612 return SwFlyFreeFrm::IsFormatPossible() && 613 !SwOszControl::IsInProgress( this ); 614 } 615 616 /************************************************************************* 617 |* 618 |* FindAnchor() und Hilfsfunktionen. 619 |* 620 |* Beschreibung: Sucht ausgehend von pOldAnch einen Anker fuer 621 |* Absatzgebundene Objekte. 622 |* Wird beim Draggen von Absatzgebundenen Objekten zur Ankeranzeige sowie 623 |* fuer Ankerwechsel benoetigt. 624 |* Ersterstellung MA 22. Jun. 93 625 |* Letzte Aenderung MA 30. Jan. 95 626 |* 627 |*************************************************************************/ 628 629 class SwDistance 630 { 631 public: 632 SwTwips nMain, nSub; 633 SwDistance() { nMain = nSub = 0; } 634 SwDistance& operator=( const SwDistance &rTwo ) 635 { nMain = rTwo.nMain; nSub = rTwo.nSub; return *this; } 636 sal_Bool operator<( const SwDistance& rTwo ) 637 { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && nSub && 638 rTwo.nSub && nSub < rTwo.nSub ); } 639 sal_Bool operator<=( const SwDistance& rTwo ) 640 { return nMain < rTwo.nMain || ( nMain == rTwo.nMain && ( !nSub || 641 !rTwo.nSub || nSub <= rTwo.nSub ) ); } 642 }; 643 644 const SwFrm * MA_FASTCALL lcl_CalcDownDist( SwDistance &rRet, 645 const Point &rPt, 646 const SwCntntFrm *pCnt ) 647 { 648 rRet.nSub = 0; 649 //Wenn der Point direkt innerhalb des Cnt steht ist die Sache klar und 650 //der Cntnt hat automatisch eine Entfernung von 0 651 if ( pCnt->Frm().IsInside( rPt ) ) 652 { 653 rRet.nMain = 0; 654 return pCnt; 655 } 656 else 657 { 658 const SwLayoutFrm *pUp = pCnt->IsInTab() ? pCnt->FindTabFrm()->GetUpper() : pCnt->GetUpper(); 659 // einspaltige Bereiche muessen zu ihrem Upper durchschalten 660 while( pUp->IsSctFrm() ) 661 pUp = pUp->GetUpper(); 662 const bool bVert = pUp->IsVertical(); 663 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 664 const bool bVertL2R = pUp->IsVertLR(); 665 666 //Dem Textflus folgen. 667 // --> OD 2009-01-12 #i70582# 668 // --> OD 2009-03-05 - adopted for Support for Classical Mongolian Script 669 const SwTwips nTopForObjPos = 670 bVert 671 ? ( bVertL2R 672 ? ( pCnt->Frm().Left() + 673 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) 674 : ( pCnt->Frm().Left() + 675 pCnt->Frm().Width() - 676 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) ) 677 : ( pCnt->Frm().Top() + 678 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ); 679 // <-- 680 if ( pUp->Frm().IsInside( rPt ) ) 681 { 682 // OD 26.09.2003 - <rPt> point is inside environment of given content frame 683 // --> OD 2009-01-12 #i70582# 684 if( bVert ) 685 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 686 { 687 if ( bVertL2R ) 688 rRet.nMain = rPt.X() - nTopForObjPos; 689 else 690 rRet.nMain = nTopForObjPos - rPt.X(); 691 } 692 else 693 rRet.nMain = rPt.Y() - nTopForObjPos; 694 // <-- 695 return pCnt; 696 } 697 else if ( rPt.Y() <= pUp->Frm().Top() ) 698 { 699 // OD 26.09.2003 - <rPt> point is above environment of given content frame 700 // OD: correct for vertical layout? 701 rRet.nMain = LONG_MAX; 702 } 703 else if( rPt.X() < pUp->Frm().Left() && 704 rPt.Y() <= ( bVert ? pUp->Frm().Top() : pUp->Frm().Bottom() ) ) 705 { 706 // OD 26.09.2003 - <rPt> point is left of environment of given content frame 707 // OD: seems not to be correct for vertical layout!? 708 const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, sal_False, pCnt ); 709 if( !pLay || 710 (bVert && (pLay->Frm().Top() + pLay->Prt().Bottom()) <rPt.Y())|| 711 (!bVert && (pLay->Frm().Left() + pLay->Prt().Right())<rPt.X()) ) 712 { 713 // OD 26.09.2003 - <rPt> point is in left border of environment 714 // --> OD 2009-01-12 #i70582# 715 if( bVert ) 716 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 717 { 718 if ( bVertL2R ) 719 rRet.nMain = rPt.X() - nTopForObjPos; 720 else 721 rRet.nMain = nTopForObjPos - rPt.X(); 722 } 723 else 724 rRet.nMain = rPt.Y() - nTopForObjPos; 725 // <-- 726 return pCnt; 727 } 728 else 729 rRet.nMain = LONG_MAX; 730 } 731 else 732 { 733 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 734 // --> OD 2009-01-12 #i70582# 735 rRet.nMain = bVert 736 ? ( bVertL2R 737 ? ( (pUp->Frm().Left() + pUp->Prt().Right()) - nTopForObjPos ) 738 : ( nTopForObjPos - (pUp->Frm().Left() + pUp->Prt().Left() ) ) ) 739 : ( (pUp->Frm().Top() + pUp->Prt().Bottom()) - nTopForObjPos ); 740 741 const SwFrm *pPre = pCnt; 742 const SwFrm *pLay = pUp->GetLeaf( MAKEPAGE_NONE, sal_True, pCnt ); 743 SwTwips nFrmTop = 0; 744 SwTwips nPrtHeight = 0; 745 sal_Bool bSct = sal_False; 746 const SwSectionFrm *pSect = pUp->FindSctFrm(); 747 if( pSect ) 748 { 749 rRet.nSub = rRet.nMain; 750 rRet.nMain = 0; 751 } 752 if( pSect && !pSect->IsAnLower( pLay ) ) 753 { 754 bSct = sal_False; 755 const SwSectionFrm* pNxtSect = pLay ? pLay->FindSctFrm() : 0; 756 if( pSect->IsAnFollow( pNxtSect ) ) 757 { 758 if( pLay->IsVertical() ) 759 { 760 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 761 if ( pLay->IsVertLR() ) 762 nFrmTop = pLay->Frm().Left(); 763 else 764 nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); 765 nPrtHeight = pLay->Prt().Width(); 766 } 767 else 768 { 769 nFrmTop = pLay->Frm().Top(); 770 nPrtHeight = pLay->Prt().Height(); 771 } 772 pSect = pNxtSect; 773 } 774 else 775 { 776 pLay = pSect->GetUpper(); 777 if( pLay->IsVertical() ) 778 { 779 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 780 if ( pLay->IsVertLR() ) 781 { 782 nFrmTop = pSect->Frm().Right(); 783 nPrtHeight = pLay->Frm().Left() + pLay->Prt().Left() 784 + pLay->Prt().Width() - pSect->Frm().Left() 785 - pSect->Frm().Width(); 786 } 787 else 788 { 789 nFrmTop = pSect->Frm().Left(); 790 nPrtHeight = pSect->Frm().Left() - pLay->Frm().Left() 791 - pLay->Prt().Left(); 792 } 793 } 794 else 795 { 796 nFrmTop = pSect->Frm().Bottom(); 797 nPrtHeight = pLay->Frm().Top() + pLay->Prt().Top() 798 + pLay->Prt().Height() - pSect->Frm().Top() 799 - pSect->Frm().Height(); 800 } 801 pSect = 0; 802 } 803 } 804 else if( pLay ) 805 { 806 if( pLay->IsVertical() ) 807 { 808 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 809 if ( pLay->IsVertLR() ) 810 { 811 nFrmTop = pLay->Frm().Left(); 812 nPrtHeight = pLay->Prt().Width(); 813 } 814 else 815 { 816 nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); 817 nPrtHeight = pLay->Prt().Width(); 818 } 819 } 820 else 821 { 822 nFrmTop = pLay->Frm().Top(); 823 nPrtHeight = pLay->Prt().Height(); 824 } 825 bSct = 0 != pSect; 826 } 827 while ( pLay && !pLay->Frm().IsInside( rPt ) && 828 ( pLay->Frm().Top() <= rPt.Y() || pLay->IsInFly() || 829 ( pLay->IsInSct() && 830 pLay->FindSctFrm()->GetUpper()->Frm().Top() <= rPt.Y())) ) 831 { 832 if ( pLay->IsFtnContFrm() ) 833 { 834 if ( !((SwLayoutFrm*)pLay)->Lower() ) 835 { 836 SwFrm *pDel = (SwFrm*)pLay; 837 pDel->Cut(); 838 delete pDel; 839 return pPre; 840 } 841 return 0; 842 } 843 else 844 { 845 if( bSct || pSect ) 846 rRet.nSub += nPrtHeight; 847 else 848 rRet.nMain += nPrtHeight; 849 pPre = pLay; 850 pLay = pLay->GetLeaf( MAKEPAGE_NONE, sal_True, pCnt ); 851 if( pSect && !pSect->IsAnLower( pLay ) ) 852 { // If we're leaving a SwSectionFrm, the next Leaf-Frm 853 // is the part of the upper below the SectionFrm. 854 const SwSectionFrm* pNxtSect = pLay ? 855 pLay->FindSctFrm() : NULL; 856 bSct = sal_False; 857 if( pSect->IsAnFollow( pNxtSect ) ) 858 { 859 pSect = pNxtSect; 860 if( pLay->IsVertical() ) 861 { 862 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 863 if ( pLay->IsVertLR() ) 864 { 865 nFrmTop = pLay->Frm().Left(); 866 nPrtHeight = pLay->Prt().Width(); 867 } 868 else 869 { 870 nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); 871 nPrtHeight = pLay->Prt().Width(); 872 } 873 } 874 else 875 { 876 nFrmTop = pLay->Frm().Top(); 877 nPrtHeight = pLay->Prt().Height(); 878 } 879 } 880 else 881 { 882 pLay = pSect->GetUpper(); 883 if( pLay->IsVertical() ) 884 { 885 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 886 if ( pLay->IsVertLR() ) 887 { 888 nFrmTop = pSect->Frm().Right(); 889 nPrtHeight = pLay->Frm().Left()+pLay->Prt().Left() 890 + pLay->Prt().Width() - pSect->Frm().Left() 891 - pSect->Frm().Width(); 892 } 893 else 894 { 895 nFrmTop = pSect->Frm().Left(); 896 nPrtHeight = pSect->Frm().Left() - 897 pLay->Frm().Left() - pLay->Prt().Left(); 898 } 899 } 900 else 901 { 902 nFrmTop = pSect->Frm().Bottom(); 903 nPrtHeight = pLay->Frm().Top()+pLay->Prt().Top() 904 + pLay->Prt().Height() - pSect->Frm().Top() 905 - pSect->Frm().Height(); 906 } 907 pSect = 0; 908 } 909 } 910 else if( pLay ) 911 { 912 if( pLay->IsVertical() ) 913 { 914 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 915 if ( pLay->IsVertLR() ) 916 { 917 nFrmTop = pLay->Frm().Left(); 918 nPrtHeight = pLay->Prt().Width(); 919 } 920 else 921 { 922 nFrmTop = pLay->Frm().Left() + pLay->Frm().Width(); 923 nPrtHeight = pLay->Prt().Width(); 924 } 925 } 926 else 927 { 928 nFrmTop = pLay->Frm().Top(); 929 nPrtHeight = pLay->Prt().Height(); 930 } 931 bSct = 0 != pSect; 932 } 933 } 934 } 935 if ( pLay ) 936 { 937 if ( pLay->Frm().IsInside( rPt ) ) 938 { 939 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 940 SwTwips nDiff = pLay->IsVertical() ? ( pLay->IsVertLR() ? ( rPt.X() - nFrmTop ) : ( nFrmTop - rPt.X() ) ) 941 : ( rPt.Y() - nFrmTop ); 942 if( bSct || pSect ) 943 rRet.nSub += nDiff; 944 else 945 rRet.nMain += nDiff; 946 } 947 if ( pLay->IsFtnContFrm() && !((SwLayoutFrm*)pLay)->Lower() ) 948 { 949 SwFrm *pDel = (SwFrm*)pLay; 950 pDel->Cut(); 951 delete pDel; 952 return 0; 953 } 954 return pLay; 955 } 956 else 957 rRet.nMain = LONG_MAX; 958 } 959 } 960 return 0; 961 } 962 963 sal_uLong MA_FASTCALL lcl_FindCntDiff( const Point &rPt, const SwLayoutFrm *pLay, 964 const SwCntntFrm *& rpCnt, 965 const sal_Bool bBody, const sal_Bool bFtn ) 966 { 967 //Sucht unterhalb von pLay den dichtesten Cnt zum Point. Der Bezugspunkt 968 //der Cntnts ist immer die linke obere Ecke. 969 //Der Cnt soll moeglichst ueber dem Point liegen. 970 971 #if OSL_DEBUG_LEVEL > 1 972 Point arPoint( rPt ); 973 #endif 974 975 rpCnt = 0; 976 sal_uLong nDistance = ULONG_MAX; 977 sal_uLong nNearest = ULONG_MAX; 978 const SwCntntFrm *pCnt = pLay->ContainsCntnt(); 979 980 while ( pCnt && (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn())) 981 { 982 pCnt = pCnt->GetNextCntntFrm(); 983 if ( !pLay->IsAnLower( pCnt ) ) 984 pCnt = 0; 985 } 986 const SwCntntFrm *pNearest = pCnt; 987 if ( pCnt ) 988 { 989 do 990 { 991 //Jetzt die Entfernung zwischen den beiden Punkten berechnen. 992 //'Delta' X^2 + 'Delta'Y^2 = 'Entfernung'^2 993 sal_uInt32 dX = Max( pCnt->Frm().Left(), rPt.X() ) - 994 Min( pCnt->Frm().Left(), rPt.X() ), 995 dY = Max( pCnt->Frm().Top(), rPt.Y() ) - 996 Min( pCnt->Frm().Top(), rPt.Y() ); 997 BigInt dX1( dX ), dY1( dY ); 998 dX1 *= dX1; dY1 *= dY1; 999 const sal_uLong nDiff = ::SqRt( dX1 + dY1 ); 1000 if ( pCnt->Frm().Top() <= rPt.Y() ) 1001 { 1002 if ( nDiff < nDistance ) 1003 { //Der ist dichter dran 1004 nDistance = nNearest = nDiff; 1005 rpCnt = pNearest = pCnt; 1006 } 1007 } 1008 else if ( nDiff < nNearest ) 1009 { 1010 nNearest = nDiff; 1011 pNearest = pCnt; 1012 } 1013 pCnt = pCnt->GetNextCntntFrm(); 1014 while ( pCnt && 1015 (bBody != pCnt->IsInDocBody() || bFtn != pCnt->IsInFtn())) 1016 pCnt = pCnt->GetNextCntntFrm(); 1017 1018 } while ( pCnt && pLay->IsAnLower( pCnt ) ); 1019 } 1020 if ( nDistance == ULONG_MAX ) 1021 { rpCnt = pNearest; 1022 return nNearest; 1023 } 1024 return nDistance; 1025 } 1026 1027 const SwCntntFrm * MA_FASTCALL lcl_FindCnt( const Point &rPt, const SwCntntFrm *pCnt, 1028 const sal_Bool bBody, const sal_Bool bFtn ) 1029 { 1030 //Sucht ausgehen von pCnt denjenigen CntntFrm, dessen linke obere 1031 //Ecke am dichtesten am Point liegt. 1032 //Liefert _immer_ einen CntntFrm zurueck. 1033 1034 //Zunaechst wird versucht den dichtesten Cntnt innerhalt derjenigen 1035 //Seite zu suchen innerhalb derer der Cntnt steht. 1036 //Ausgehend von der Seite muessen die Seiten in beide 1037 //Richtungen beruecksichtigt werden. 1038 //Falls moeglich wird ein Cntnt geliefert, dessen Y-Position ueber der 1039 //des Point sitzt. 1040 const SwCntntFrm *pRet, *pNew; 1041 const SwLayoutFrm *pLay = pCnt->FindPageFrm(); 1042 sal_uLong nDist; 1043 1044 nDist = ::lcl_FindCntDiff( rPt, pLay, pNew, bBody, bFtn ); 1045 if ( pNew ) 1046 pRet = pNew; 1047 else 1048 { pRet = pCnt; 1049 nDist = ULONG_MAX; 1050 } 1051 const SwCntntFrm *pNearest = pRet; 1052 sal_uLong nNearest = nDist; 1053 1054 if ( pLay ) 1055 { 1056 const SwLayoutFrm *pPge = pLay; 1057 sal_uLong nOldNew = ULONG_MAX; 1058 for ( sal_uInt16 i = 0; pPge->GetPrev() && (i < 3); ++i ) 1059 { 1060 pPge = (SwLayoutFrm*)pPge->GetPrev(); 1061 const sal_uLong nNew = ::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn ); 1062 if ( nNew < nDist ) 1063 { 1064 if ( pNew->Frm().Top() <= rPt.Y() ) 1065 { 1066 pRet = pNearest = pNew; 1067 nDist = nNearest = nNew; 1068 } 1069 else if ( nNew < nNearest ) 1070 { 1071 pNearest = pNew; 1072 nNearest = nNew; 1073 } 1074 } 1075 else if ( nOldNew != ULONG_MAX && nNew > nOldNew ) 1076 break; 1077 else 1078 nOldNew = nNew; 1079 1080 } 1081 pPge = pLay; 1082 nOldNew = ULONG_MAX; 1083 for ( sal_uInt16 j = 0; pPge->GetNext() && (j < 3); ++j ) 1084 { 1085 pPge = (SwLayoutFrm*)pPge->GetNext(); 1086 const sal_uLong nNew = ::lcl_FindCntDiff( rPt, pPge, pNew, bBody, bFtn ); 1087 if ( nNew < nDist ) 1088 { 1089 if ( pNew->Frm().Top() <= rPt.Y() ) 1090 { 1091 pRet = pNearest = pNew; 1092 nDist = nNearest = nNew; 1093 } 1094 else if ( nNew < nNearest ) 1095 { 1096 pNearest = pNew; 1097 nNearest = nNew; 1098 } 1099 } 1100 else if ( nOldNew != ULONG_MAX && nNew > nOldNew ) 1101 break; 1102 else 1103 nOldNew = nNew; 1104 } 1105 } 1106 if ( (pRet->Frm().Top() > rPt.Y()) ) 1107 return pNearest; 1108 else 1109 return pRet; 1110 } 1111 1112 void lcl_PointToPrt( Point &rPoint, const SwFrm *pFrm ) 1113 { 1114 SwRect aTmp( pFrm->Prt() ); 1115 aTmp += pFrm->Frm().Pos(); 1116 if ( rPoint.X() < aTmp.Left() ) 1117 rPoint.X() = aTmp.Left(); 1118 else if ( rPoint.X() > aTmp.Right() ) 1119 rPoint.X() = aTmp.Right(); 1120 if ( rPoint.Y() < aTmp.Top() ) 1121 rPoint.Y() = aTmp.Top(); 1122 else if ( rPoint.Y() > aTmp.Bottom() ) 1123 rPoint.Y() = aTmp.Bottom(); 1124 1125 } 1126 1127 const SwCntntFrm *FindAnchor( const SwFrm *pOldAnch, const Point &rNew, 1128 const sal_Bool bBodyOnly ) 1129 { 1130 //Zu der angegebenen DokumentPosition wird der dichteste Cnt im 1131 //Textfluss gesucht. AusgangsFrm ist der uebergebene Anker. 1132 const SwCntntFrm* pCnt; 1133 if ( pOldAnch->IsCntntFrm() ) 1134 { 1135 pCnt = (const SwCntntFrm*)pOldAnch; 1136 } 1137 else 1138 { 1139 Point aTmp( rNew ); 1140 SwLayoutFrm *pTmpLay = (SwLayoutFrm*)pOldAnch; 1141 if( pTmpLay->IsRootFrm() ) 1142 { 1143 SwRect aTmpRect( aTmp, Size(0,0) ); 1144 pTmpLay = (SwLayoutFrm*)::FindPage( aTmpRect, pTmpLay->Lower() ); 1145 } 1146 pCnt = pTmpLay->GetCntntPos( aTmp, sal_False, bBodyOnly ); 1147 } 1148 1149 //Beim Suchen darauf achten, dass die Bereiche sinnvoll erhalten 1150 //bleiben. D.h. in diesem Fall nicht in Header/Footer hinein und 1151 //nicht aus Header/Footer hinaus. 1152 const sal_Bool bBody = pCnt->IsInDocBody() || bBodyOnly; 1153 const sal_Bool bFtn = !bBodyOnly && pCnt->IsInFtn(); 1154 1155 Point aNew( rNew ); 1156 if ( bBody ) 1157 { 1158 //#38848 Vom Seitenrand in den Body ziehen. 1159 const SwFrm *pPage = pCnt->FindPageFrm(); 1160 ::lcl_PointToPrt( aNew, pPage->GetUpper() ); 1161 SwRect aTmp( aNew, Size( 0, 0 ) ); 1162 pPage = ::FindPage( aTmp, pPage ); 1163 ::lcl_PointToPrt( aNew, pPage ); 1164 } 1165 1166 if ( pCnt->IsInDocBody() == bBody && pCnt->Frm().IsInside( aNew ) ) 1167 return pCnt; 1168 else if ( pOldAnch->IsInDocBody() || pOldAnch->IsPageFrm() ) 1169 { 1170 //Vielleicht befindet sich der gewuenschte Anker ja auf derselben 1171 //Seite wie der aktuelle Anker. 1172 //So gibt es kein Problem mit Spalten. 1173 Point aTmp( aNew ); 1174 const SwCntntFrm *pTmp = pCnt->FindPageFrm()-> 1175 GetCntntPos( aTmp, sal_False, sal_True, sal_False ); 1176 if ( pTmp && pTmp->Frm().IsInside( aNew ) ) 1177 return pTmp; 1178 } 1179 1180 //Ausgehend vom Anker suche ich jetzt in beide Richtungen bis ich 1181 //den jeweils dichtesten gefunden habe. 1182 //Nicht die direkte Entfernung ist relevant sondern die Strecke die 1183 //im Textfluss zurueckgelegt werden muss. 1184 const SwCntntFrm *pUpLst; 1185 const SwCntntFrm *pUpFrm = pCnt; 1186 SwDistance nUp, nUpLst; 1187 ::lcl_CalcDownDist( nUp, aNew, pUpFrm ); 1188 SwDistance nDown = nUp; 1189 sal_Bool bNegAllowed = sal_True;//Einmal aus dem negativen Bereich heraus lassen. 1190 do 1191 { 1192 pUpLst = pUpFrm; nUpLst = nUp; 1193 pUpFrm = pUpLst->GetPrevCntntFrm(); 1194 while ( pUpFrm && 1195 (bBody != pUpFrm->IsInDocBody() || bFtn != pUpFrm->IsInFtn())) 1196 pUpFrm = pUpFrm->GetPrevCntntFrm(); 1197 if ( pUpFrm ) 1198 { 1199 ::lcl_CalcDownDist( nUp, aNew, pUpFrm ); 1200 //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es 1201 //sich weiter zu suchen. 1202 if ( pUpLst->IsInTab() && pUpFrm->IsInTab() ) 1203 { 1204 while ( pUpFrm && ((nUpLst < nUp && pUpFrm->IsInTab()) || 1205 bBody != pUpFrm->IsInDocBody()) ) 1206 { 1207 pUpFrm = pUpFrm->GetPrevCntntFrm(); 1208 if ( pUpFrm ) 1209 ::lcl_CalcDownDist( nUp, aNew, pUpFrm ); 1210 } 1211 } 1212 } 1213 if ( !pUpFrm ) 1214 nUp.nMain = LONG_MAX; 1215 if ( nUp.nMain >= 0 && LONG_MAX != nUp.nMain ) 1216 { 1217 bNegAllowed = sal_False; 1218 if ( nUpLst.nMain < 0 ) //nicht den falschen erwischen, wenn der Wert 1219 //gerade von negativ auf positiv gekippt ist. 1220 { pUpLst = pUpFrm; 1221 nUpLst = nUp; 1222 } 1223 } 1224 } while ( pUpFrm && ( ( bNegAllowed && nUp.nMain < 0 ) || ( nUp <= nUpLst ) ) ); 1225 1226 const SwCntntFrm *pDownLst; 1227 const SwCntntFrm *pDownFrm = pCnt; 1228 SwDistance nDownLst; 1229 if ( nDown.nMain < 0 ) 1230 nDown.nMain = LONG_MAX; 1231 do 1232 { 1233 pDownLst = pDownFrm; nDownLst = nDown; 1234 pDownFrm = pDownLst->GetNextCntntFrm(); 1235 while ( pDownFrm && 1236 (bBody != pDownFrm->IsInDocBody() || bFtn != pDownFrm->IsInFtn())) 1237 pDownFrm = pDownFrm->GetNextCntntFrm(); 1238 if ( pDownFrm ) 1239 { 1240 ::lcl_CalcDownDist( nDown, aNew, pDownFrm ); 1241 if ( nDown.nMain < 0 ) 1242 nDown.nMain = LONG_MAX; 1243 //Wenn die Distanz innnerhalb einer Tabelle waechst, so lohnt es 1244 //sich weiter zu suchen. 1245 if ( pDownLst->IsInTab() && pDownFrm->IsInTab() ) 1246 { 1247 while ( pDownFrm && ( ( nDown.nMain != LONG_MAX && nDownLst < nDownLst 1248 && pDownFrm->IsInTab()) || bBody != pDownFrm->IsInDocBody() ) ) 1249 { 1250 pDownFrm = pDownFrm->GetNextCntntFrm(); 1251 if ( pDownFrm ) 1252 ::lcl_CalcDownDist( nDown, aNew, pDownFrm ); 1253 if ( nDown.nMain < 0 ) 1254 nDown.nMain = LONG_MAX; 1255 } 1256 } 1257 } 1258 if ( !pDownFrm ) 1259 nDown.nMain = LONG_MAX; 1260 1261 } while ( pDownFrm && nDown <= nDownLst && 1262 nDown.nMain != LONG_MAX && nDownLst.nMain != LONG_MAX ); 1263 1264 //Wenn ich in beide Richtungen keinen gefunden habe, so suche ich mir 1265 //denjenigen Cntnt dessen linke obere Ecke dem Point am naechsten liegt. 1266 //Eine derartige Situation tritt z.b. auf, wenn der Point nicht im Text- 1267 //fluss sondern in irgendwelchen Raendern steht. 1268 if ( nDownLst.nMain == LONG_MAX && nUpLst.nMain == LONG_MAX ) 1269 { 1270 // #102861# If an OLE objects, which is contained in a fly frame 1271 // is resized in inplace mode and the new Position is outside the 1272 // fly frame, we do not want to leave our fly frame. 1273 if ( pCnt->IsInFly() ) 1274 return pCnt; 1275 1276 return ::lcl_FindCnt( aNew, pCnt, bBody, bFtn ); 1277 } 1278 else 1279 return nDownLst < nUpLst ? pDownLst : pUpLst; 1280 } 1281 1282 /************************************************************************* 1283 |* 1284 |* SwFlyAtCntFrm::SetAbsPos() 1285 |* 1286 |* Ersterstellung MA 22. Jun. 93 1287 |* Letzte Aenderung MA 11. Sep. 98 1288 |* 1289 |*************************************************************************/ 1290 1291 void SwFlyAtCntFrm::SetAbsPos( const Point &rNew ) 1292 { 1293 SwPageFrm *pOldPage = FindPageFrm(); 1294 const SwRect aOld( GetObjRectWithSpaces() ); 1295 Point aNew( rNew ); 1296 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 1297 if( ( GetAnchorFrm()->IsVertical() && !GetAnchorFrm()->IsVertLR() ) || GetAnchorFrm()->IsRightToLeft() ) 1298 aNew.X() += Frm().Width(); 1299 SwCntntFrm *pCnt = (SwCntntFrm*)::FindAnchor( GetAnchorFrm(), aNew ); 1300 if( pCnt->IsProtected() ) 1301 pCnt = (SwCntntFrm*)GetAnchorFrm(); 1302 1303 SwPageFrm *pTmpPage = 0; 1304 const bool bVert = pCnt->IsVertical(); 1305 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 1306 const bool bVertL2R = pCnt->IsVertLR(); 1307 const sal_Bool bRTL = pCnt->IsRightToLeft(); 1308 1309 if( ( !bVert != !GetAnchorFrm()->IsVertical() ) || 1310 ( !bRTL != !GetAnchorFrm()->IsRightToLeft() ) ) 1311 { 1312 if( bVert || bRTL ) 1313 aNew.X() += Frm().Width(); 1314 else 1315 aNew.X() -= Frm().Width(); 1316 } 1317 1318 if ( pCnt->IsInDocBody() ) 1319 { 1320 //#38848 Vom Seitenrand in den Body ziehen. 1321 pTmpPage = pCnt->FindPageFrm(); 1322 ::lcl_PointToPrt( aNew, pTmpPage->GetUpper() ); 1323 SwRect aTmp( aNew, Size( 0, 0 ) ); 1324 pTmpPage = (SwPageFrm*)::FindPage( aTmp, pTmpPage ); 1325 ::lcl_PointToPrt( aNew, pTmpPage ); 1326 } 1327 1328 //RelPos einstellen, nur auf Wunsch invalidieren. 1329 //rNew ist eine Absolute Position. Um die RelPos korrekt einzustellen 1330 //muessen wir uns die Entfernung von rNew zum Anker im Textfluss besorgen. 1331 //!!!!!Hier kann Optimiert werden: FindAnchor koennte die RelPos mitliefern! 1332 const SwFrm *pFrm = 0; 1333 SwTwips nY; 1334 if ( pCnt->Frm().IsInside( aNew ) ) 1335 { 1336 // --> OD 2009-01-12 #i70582# 1337 const SwTwips nTopForObjPos = 1338 bVert 1339 ? ( bVertL2R 1340 ? ( pCnt->Frm().Left() + 1341 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) 1342 : ( pCnt->Frm().Left() + 1343 pCnt->Frm().Width() - 1344 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) ) 1345 : ( pCnt->Frm().Top() + 1346 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ); 1347 if( bVert ) 1348 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 1349 { 1350 if ( bVertL2R ) 1351 nY = rNew.X() - nTopForObjPos; 1352 else 1353 nY = nTopForObjPos - rNew.X() - Frm().Width(); 1354 } 1355 else 1356 { 1357 nY = rNew.Y() - nTopForObjPos; 1358 } 1359 // <-- 1360 } 1361 else 1362 { 1363 SwDistance aDist; 1364 pFrm = ::lcl_CalcDownDist( aDist, aNew, pCnt ); 1365 nY = aDist.nMain + aDist.nSub; 1366 } 1367 1368 SwTwips nX = 0; 1369 1370 if ( pCnt->IsFollow() ) 1371 { 1372 //Flys haengen niemals an einem Follow sondern immer am 1373 //Master, den suchen wir uns jetzt. 1374 const SwCntntFrm *pOriginal = pCnt; 1375 const SwCntntFrm *pFollow = pCnt; 1376 while ( pCnt->IsFollow() ) 1377 { 1378 do 1379 { pCnt = pCnt->GetPrevCntntFrm(); 1380 } while ( pCnt->GetFollow() != pFollow ); 1381 pFollow = pCnt; 1382 } 1383 SwTwips nDiff = 0; 1384 do 1385 { const SwFrm *pUp = pFollow->GetUpper(); 1386 if( pUp->IsVertical() ) 1387 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 1388 { 1389 if ( pUp->IsVertLR() ) 1390 nDiff += pUp->Prt().Width() - pFollow->GetRelPos().X(); 1391 else 1392 nDiff += pFollow->Frm().Left() + pFollow->Frm().Width() 1393 - pUp->Frm().Left() - pUp->Prt().Left(); 1394 } 1395 else 1396 nDiff += pUp->Prt().Height() - pFollow->GetRelPos().Y(); 1397 pFollow = pFollow->GetFollow(); 1398 } while ( pFollow != pOriginal ); 1399 nY += nDiff; 1400 if( bVert ) 1401 nX = pCnt->Frm().Top() - pOriginal->Frm().Top(); 1402 else 1403 nX = pCnt->Frm().Left() - pOriginal->Frm().Left(); 1404 } 1405 1406 if ( nY == LONG_MAX ) 1407 { 1408 // --> OD 2009-01-12 #i70582# 1409 const SwTwips nTopForObjPos = 1410 bVert 1411 ? ( bVertL2R 1412 ? ( pCnt->Frm().Left() + 1413 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) 1414 : ( pCnt->Frm().Left() + 1415 pCnt->Frm().Width() - 1416 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ) ) 1417 : ( pCnt->Frm().Top() + 1418 pCnt->GetUpperSpaceAmountConsideredForPrevFrmAndPageGrid() ); 1419 if( bVert ) 1420 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 1421 { 1422 if ( bVertL2R ) 1423 nY = rNew.X() - nTopForObjPos; 1424 else 1425 nY = nTopForObjPos - rNew.X(); 1426 } 1427 else 1428 { 1429 nY = rNew.Y() - nTopForObjPos; 1430 } 1431 // <-- 1432 } 1433 1434 SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)GetFmt(); 1435 const SwFmtSurround& rSurround = pFmt->GetSurround(); 1436 const sal_Bool bWrapThrough = 1437 rSurround.GetSurround() == SURROUND_THROUGHT; 1438 SwTwips nBaseOfstForFly = 0; 1439 const SwFrm* pTmpFrm = pFrm ? pFrm : pCnt; 1440 if ( pTmpFrm->IsTxtFrm() ) 1441 nBaseOfstForFly = 1442 ((SwTxtFrm*)pTmpFrm)->GetBaseOfstForFly( !bWrapThrough ); 1443 1444 if( bVert ) 1445 { 1446 if( !pFrm ) 1447 nX += rNew.Y() - pCnt->Frm().Top() - nBaseOfstForFly; 1448 else 1449 nX = rNew.Y() - pFrm->Frm().Top() - nBaseOfstForFly; 1450 } 1451 else 1452 { 1453 if( !pFrm ) 1454 { 1455 if ( pCnt->IsRightToLeft() ) 1456 nX += pCnt->Frm().Right() - rNew.X() - Frm().Width() + 1457 nBaseOfstForFly; 1458 else 1459 nX += rNew.X() - pCnt->Frm().Left() - nBaseOfstForFly; 1460 } 1461 else 1462 { 1463 if ( pFrm->IsRightToLeft() ) 1464 nX += pFrm->Frm().Right() - rNew.X() - Frm().Width() + 1465 nBaseOfstForFly; 1466 else 1467 nX = rNew.X() - pFrm->Frm().Left() - nBaseOfstForFly; 1468 } 1469 } 1470 GetFmt()->GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL ); 1471 1472 if( pCnt != GetAnchorFrm() || ( IsAutoPos() && pCnt->IsTxtFrm() && 1473 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE)) ) 1474 { 1475 //Das Ankerattribut auf den neuen Cnt setzen. 1476 SwFmtAnchor aAnch( pFmt->GetAnchor() ); 1477 SwPosition *pPos = (SwPosition*)aAnch.GetCntntAnchor(); 1478 if( IsAutoPos() && pCnt->IsTxtFrm() ) 1479 { 1480 SwCrsrMoveState eTmpState( MV_SETONLYTEXT ); 1481 Point aPt( rNew ); 1482 if( pCnt->GetCrsrOfst( pPos, aPt, &eTmpState ) 1483 && pPos->nNode == *pCnt->GetNode() ) 1484 { 1485 ResetLastCharRectHeight(); 1486 if( text::RelOrientation::CHAR == pFmt->GetVertOrient().GetRelationOrient() ) 1487 nY = LONG_MAX; 1488 if( text::RelOrientation::CHAR == pFmt->GetHoriOrient().GetRelationOrient() ) 1489 nX = LONG_MAX; 1490 } 1491 else 1492 { 1493 pPos->nNode = *pCnt->GetNode(); 1494 pPos->nContent.Assign( pCnt->GetNode(), 0 ); 1495 } 1496 } 1497 else 1498 { 1499 pPos->nNode = *pCnt->GetNode(); 1500 pPos->nContent.Assign( pCnt->GetNode(), 0 ); 1501 } 1502 1503 // --> OD 2006-02-27 #125892# 1504 // handle change of anchor node: 1505 // if count of the anchor frame also change, the fly frames have to be 1506 // re-created. Thus, delete all fly frames except the <this> before the 1507 // anchor attribute is change and re-create them afterwards. 1508 { 1509 SwHandleAnchorNodeChg aHandleAnchorNodeChg( *pFmt, aAnch, this ); 1510 pFmt->GetDoc()->SetAttr( aAnch, *pFmt ); 1511 } 1512 // <-- 1513 } 1514 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> 1515 else if ( pTmpPage && pTmpPage != GetPageFrm() ) 1516 GetPageFrm()->MoveFly( this, pTmpPage ); 1517 1518 const Point aRelPos = bVert ? Point( -nY, nX ) : Point( nX, nY ); 1519 1520 ChgRelPos( aRelPos ); 1521 1522 GetFmt()->GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL ); 1523 1524 if ( pOldPage != FindPageFrm() ) 1525 ::Notify_Background( GetVirtDrawObj(), pOldPage, aOld, PREP_FLY_LEAVE, 1526 sal_False ); 1527 } 1528 1529 // OD 2004-08-12 #i32795# - Note: method no longer used in <flyincnt.cxx> 1530 //void DeepCalc( const SwFrm *pFrm ) 1531 //{ 1532 // if( pFrm->IsSctFrm() || 1533 // ( pFrm->IsFlyFrm() && ((SwFlyFrm*)pFrm)->IsFlyInCntFrm() ) ) 1534 // return; 1535 // const SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm ); 1536 // if( pFlow && pFlow->IsAnyJoinLocked() ) 1537 // return; 1538 1539 // sal_uInt16 nCnt = 0; 1540 1541 // sal_Bool bContinue = sal_False; 1542 // do 1543 // { 1544 // if ( ++nCnt == 10 ) 1545 // { 1546 // ASSERT( !nCnt, "DeepCalc: Loop detected1?" ); 1547 // break; 1548 // } 1549 1550 // const sal_Bool bSetComplete = !pFrm->IsValid(); 1551 // const SwRect aOldFrm( pFrm->Frm() ); 1552 // const SwRect aOldPrt( pFrm->Prt() ); 1553 1554 // const SwFrm *pUp = pFrm->GetUpper(); 1555 // if ( pUp ) 1556 // { 1557 // //Nicht weiter wenn der Up ein Fly mit Spalten ist. 1558 // if( ( !pUp->IsFlyFrm() || !((SwLayoutFrm*)pUp)->Lower() || 1559 // !((SwLayoutFrm*)pUp)->Lower()->IsColumnFrm() ) && 1560 // !pUp->IsSctFrm() ) 1561 // { 1562 // SWRECTFN( pUp ) 1563 // const Point aPt( (pUp->Frm().*fnRect->fnGetPos)() ); 1564 // ::DeepCalc( pUp ); 1565 // bContinue = aPt != (pUp->Frm().*fnRect->fnGetPos)(); 1566 // } 1567 // } 1568 // else 1569 // pUp = pFrm; 1570 1571 // pFrm->Calc(); 1572 // if ( bSetComplete && (aOldFrm != pFrm->Frm() || aOldPrt != pFrm->Prt())) 1573 // pFrm->SetCompletePaint(); 1574 1575 // if ( pUp->IsFlyFrm() ) 1576 // { 1577 // if ( ((SwFlyFrm*)pUp)->IsLocked() || 1578 // (((SwFlyFrm*)pUp)->IsFlyAtCntFrm() && 1579 // SwOszControl::IsInProgress( (const SwFlyFrm*)pUp )) ) 1580 // { 1581 // bContinue = sal_False; 1582 // } 1583 // } 1584 // } while ( bContinue ); 1585 //} 1586 1587 /** method to assure that anchored object is registered at the correct 1588 page frame 1589 1590 OD 2004-07-02 #i28701# 1591 takes over functionality of deleted method <SwFlyAtCntFrm::AssertPage()> 1592 1593 @author OD 1594 */ 1595 void SwFlyAtCntFrm::RegisterAtCorrectPage() 1596 { 1597 SwPageFrm* pPageFrm( 0L ); 1598 if ( GetVertPosOrientFrm() ) 1599 { 1600 pPageFrm = const_cast<SwPageFrm*>(GetVertPosOrientFrm()->FindPageFrm()); 1601 } 1602 if ( pPageFrm && GetPageFrm() != pPageFrm ) 1603 { 1604 if ( GetPageFrm() ) 1605 GetPageFrm()->MoveFly( this, pPageFrm ); 1606 else 1607 pPageFrm->AppendFlyToPage( this ); 1608 } 1609 } 1610 1611 // OD 2004-03-23 #i26791# 1612 //void SwFlyAtCntFrm::MakeFlyPos() 1613 void SwFlyAtCntFrm::MakeObjPos() 1614 { 1615 // OD 02.10.2002 #102646# 1616 // if fly frame position is valid, nothing is to do. Thus, return 1617 if ( bValidPos ) 1618 { 1619 return; 1620 } 1621 1622 // OD 2004-03-24 #i26791# - validate position flag here. 1623 bValidPos = sal_True; 1624 1625 // --> OD 2004-10-22 #i35911# - no calculation of new position, if 1626 // anchored object is marked that it clears its environment and its 1627 // environment is already cleared. 1628 // --> OD 2006-01-02 #125977# - before checking for cleared environment 1629 // check, if member <mpVertPosOrientFrm> is set. 1630 if ( GetVertPosOrientFrm() && 1631 ClearedEnvironment() && HasClearedEnvironment() ) 1632 { 1633 return; 1634 } 1635 // <-- 1636 1637 // OD 29.10.2003 #113049# - use new class to position object 1638 objectpositioning::SwToCntntAnchoredObjectPosition 1639 aObjPositioning( *GetVirtDrawObj() ); 1640 aObjPositioning.CalcPosition(); 1641 1642 SetVertPosOrientFrm ( aObjPositioning.GetVertPosOrientFrm() ); 1643 } 1644 1645 // OD 2004-05-12 #i28701# 1646 bool SwFlyAtCntFrm::_InvalidationAllowed( const InvalidationType _nInvalid ) const 1647 { 1648 bool bAllowed( SwFlyFreeFrm::_InvalidationAllowed( _nInvalid ) ); 1649 1650 // forbiddance of base instance can't be over ruled. 1651 if ( bAllowed ) 1652 { 1653 if ( _nInvalid == INVALID_POS || 1654 _nInvalid == INVALID_ALL ) 1655 { 1656 bAllowed = InvalidationOfPosAllowed(); 1657 } 1658 } 1659 1660 return bAllowed; 1661 } 1662