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