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