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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_sw.hxx" 24 25 #include <hintids.hxx> 26 #include <tools/bigint.hxx> 27 #include <svx/svdmodel.hxx> 28 #include <svx/svdpage.hxx> 29 #include <editeng/brshitem.hxx> 30 #include <editeng/keepitem.hxx> 31 #include <editeng/shaditem.hxx> 32 #include <editeng/ulspitem.hxx> 33 #include <editeng/lrspitem.hxx> 34 #include <editeng/boxitem.hxx> 35 #include <sfx2/printer.hxx> 36 #include <editeng/lspcitem.hxx> 37 #include <fmtornt.hxx> 38 #include <fmtanchr.hxx> 39 #include <fmthdft.hxx> 40 #include <fmtcntnt.hxx> 41 #include <fmtfsize.hxx> 42 #include <fmtsrnd.hxx> 43 #include <docary.hxx> 44 #include <lineinfo.hxx> 45 #include <swmodule.hxx> 46 #include "pagefrm.hxx" 47 #include "colfrm.hxx" 48 #include "doc.hxx" 49 #include "fesh.hxx" 50 #include "viewimp.hxx" 51 #include "viewopt.hxx" 52 #include "pam.hxx" 53 #include "dflyobj.hxx" 54 #include "dcontact.hxx" 55 #include "frmtool.hxx" 56 #include "docsh.hxx" 57 #include "tabfrm.hxx" 58 #include "rowfrm.hxx" 59 #include "ftnfrm.hxx" 60 #include "txtfrm.hxx" 61 #include "notxtfrm.hxx" 62 #include "flyfrms.hxx" 63 #include "layact.hxx" 64 #include "pagedesc.hxx" 65 #include "section.hxx" 66 #include "sectfrm.hxx" 67 #include "node2lay.hxx" 68 #include "ndole.hxx" 69 #include "ndtxt.hxx" 70 #include "swtable.hxx" 71 #include "hints.hxx" 72 #include <layhelp.hxx> 73 #include <laycache.hxx> 74 #include <rootfrm.hxx> 75 #include "mdiexp.hxx" 76 #include "statstr.hrc" 77 #include <paratr.hxx> 78 #include <sortedobjs.hxx> 79 #include <objectformatter.hxx> 80 #include <switerator.hxx> 81 #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx> 82 #include <drawdoc.hxx> 83 84 // ftnfrm.cxx: 85 void lcl_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes ); 86 87 using namespace ::com::sun::star; 88 89 90 sal_Bool bObjsDirect = sal_True; 91 sal_Bool bDontCreateObjects = sal_False; 92 sal_Bool bSetCompletePaintOnInvalidate = sal_False; 93 94 sal_uInt8 StackHack::nCnt = 0; 95 sal_Bool StackHack::bLocked = sal_False; 96 97 98 99 /*************************************************************************/ 100 101 SwFrmNotify::SwFrmNotify( SwFrm *pF ) : 102 pFrm( pF ), 103 aFrm( pF->Frm() ), 104 aPrt( pF->Prt() ), 105 bInvaKeep( sal_False ), 106 bValidSize( pF->GetValidSizeFlag() ), 107 mbFrmDeleted( false ) // #i49383# 108 { 109 if ( pF->IsTxtFrm() ) 110 { 111 mnFlyAnchorOfst = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_True ); 112 mnFlyAnchorOfstNoWrap = ((SwTxtFrm*)pF)->GetBaseOfstForFly( sal_False ); 113 } 114 else 115 { 116 mnFlyAnchorOfst = 0; 117 mnFlyAnchorOfstNoWrap = 0; 118 } 119 120 bHadFollow = pF->IsCntntFrm() ? 121 (((SwCntntFrm*)pF)->GetFollow() ? sal_True : sal_False) : 122 sal_False; 123 } 124 125 /*************************************************************************/ 126 127 SwFrmNotify::~SwFrmNotify() 128 { 129 // #i49383# 130 if ( mbFrmDeleted ) 131 { 132 return; 133 } 134 135 SWRECTFN( pFrm ) 136 const sal_Bool bAbsP = POS_DIFF( aFrm, pFrm->Frm() ); 137 const sal_Bool bChgWidth = 138 (aFrm.*fnRect->fnGetWidth)() != (pFrm->Frm().*fnRect->fnGetWidth)(); 139 const sal_Bool bChgHeight = 140 (aFrm.*fnRect->fnGetHeight)()!=(pFrm->Frm().*fnRect->fnGetHeight)(); 141 const sal_Bool bChgFlyBasePos = pFrm->IsTxtFrm() && 142 ( ( mnFlyAnchorOfst != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_True ) ) || 143 ( mnFlyAnchorOfstNoWrap != ((SwTxtFrm*)pFrm)->GetBaseOfstForFly( sal_False ) ) ); 144 145 if ( pFrm->IsFlowFrm() && !pFrm->IsInFtn() ) 146 { 147 SwFlowFrm *pFlow = SwFlowFrm::CastFlowFrm( pFrm ); 148 149 if ( !pFlow->IsFollow() ) 150 { 151 if ( !pFrm->GetIndPrev() ) 152 { 153 if ( bInvaKeep ) 154 { 155 SwFrm *pPre = pFrm->FindPrev(); 156 if ( pPre && pPre->IsFlowFrm() ) 157 { 158 // 1. pPre wants to keep with me: 159 bool bInvalidPrePos = SwFlowFrm::CastFlowFrm( pPre )->IsKeep( *pPre->GetAttrSet() ) && pPre->GetIndPrev(); 160 161 // 2. pPre is a table and the last row wants to keep with me: 162 if ( !bInvalidPrePos && pPre->IsTabFrm() ) 163 { 164 SwTabFrm* pPreTab = static_cast<SwTabFrm*>(pPre); 165 if ( pPreTab->GetFmt()->GetDoc()->get(IDocumentSettingAccess::TABLE_ROW_KEEP) ) 166 { 167 SwRowFrm* pLastRow = static_cast<SwRowFrm*>(pPreTab->GetLastLower()); 168 if ( pLastRow && pLastRow->ShouldRowKeepWithNext() ) 169 bInvalidPrePos = true; 170 } 171 } 172 173 if ( bInvalidPrePos ) 174 pPre->InvalidatePos(); 175 } 176 } 177 } 178 else if ( !pFlow->HasFollow() ) 179 { 180 long nOldHeight = (aFrm.*fnRect->fnGetHeight)(); 181 long nNewHeight = (pFrm->Frm().*fnRect->fnGetHeight)(); 182 if( (nOldHeight > nNewHeight) || (!nOldHeight && nNewHeight) ) 183 pFlow->CheckKeep(); 184 } 185 } 186 } 187 188 if ( bAbsP ) 189 { 190 pFrm->SetCompletePaint(); 191 192 SwFrm* pNxt = pFrm->GetIndNext(); 193 // #121888# - skip empty section frames 194 while ( pNxt && 195 pNxt->IsSctFrm() && !static_cast<SwSectionFrm*>(pNxt)->GetSection() ) 196 { 197 pNxt = pNxt->GetIndNext(); 198 } 199 200 if ( pNxt ) 201 pNxt->InvalidatePos(); 202 else 203 { 204 // #104100# - correct condition for setting retouche 205 // flag for vertical layout. 206 if( pFrm->IsRetoucheFrm() && 207 (aFrm.*fnRect->fnTopDist)( (pFrm->Frm().*fnRect->fnGetTop)() ) > 0 ) 208 { 209 pFrm->SetRetouche(); 210 } 211 212 // A fresh follow frame does not have to be invalidated, because 213 // it is already formatted: 214 if ( bHadFollow || !pFrm->IsCntntFrm() || !((SwCntntFrm*)pFrm)->GetFollow() ) 215 { 216 if ( !pFrm->IsTabFrm() || !((SwTabFrm*)pFrm)->GetFollow() ) 217 pFrm->InvalidateNextPos(); 218 } 219 } 220 } 221 222 //Fuer Hintergrundgrafiken muss bei Groessenaenderungen ein Repaint her. 223 const sal_Bool bPrtWidth = 224 (aPrt.*fnRect->fnGetWidth)() != (pFrm->Prt().*fnRect->fnGetWidth)(); 225 const sal_Bool bPrtHeight = 226 (aPrt.*fnRect->fnGetHeight)()!=(pFrm->Prt().*fnRect->fnGetHeight)(); 227 if ( bPrtWidth || bPrtHeight ) 228 { 229 //UUUU 230 drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(pFrm->getSdrAllFillAttributesHelper()); 231 232 if(aFillAttributes.get() && aFillAttributes->isUsed()) 233 { 234 //UUUU use SetCompletePaint if needed 235 if(aFillAttributes->needCompleteRepaint()) 236 { 237 pFrm->SetCompletePaint(); 238 } 239 } 240 else 241 { 242 const SvxGraphicPosition ePos = pFrm->GetAttrSet()->GetBackground().GetGraphicPos(); 243 if(GPOS_NONE != ePos && GPOS_TILED != ePos) 244 pFrm->SetCompletePaint(); 245 } 246 } 247 else 248 { 249 // #97597# - consider case that *only* margins between 250 // frame and printing area has changed. Then, frame has to be repainted, 251 // in order to force paint of the margin areas. 252 if ( !bAbsP && (bChgWidth || bChgHeight) ) 253 { 254 pFrm->SetCompletePaint(); 255 } 256 } 257 258 const sal_Bool bPrtP = POS_DIFF( aPrt, pFrm->Prt() ); 259 if ( bAbsP || bPrtP || bChgWidth || bChgHeight || 260 bPrtWidth || bPrtHeight || bChgFlyBasePos ) 261 { 262 if( pFrm->IsAccessibleFrm() ) 263 { 264 SwRootFrm *pRootFrm = pFrm->getRootFrm(); 265 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && 266 pRootFrm->GetCurrShell() ) 267 { 268 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pFrm, aFrm ); 269 } 270 } 271 272 // Notification of anchored objects 273 if ( pFrm->GetDrawObjs() ) 274 { 275 const SwSortedObjs &rObjs = *pFrm->GetDrawObjs(); 276 SwPageFrm* pPageFrm = 0; 277 for ( sal_uInt32 i = 0; i < rObjs.Count(); ++i ) 278 { 279 // OD 2004-03-31 #i26791# - no general distinction between 280 // Writer fly frames and drawing objects 281 bool bNotify = false; 282 bool bNotifySize = false; 283 SwAnchoredObject* pObj = rObjs[i]; 284 SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() ); 285 // --> OD 2004-12-08 #115759# 286 const bool bAnchoredAsChar = pContact->ObjAnchoredAsChar(); 287 if ( !bAnchoredAsChar ) 288 // <-- 289 { 290 // Notify object, which aren't anchored as-character: 291 292 // always notify objects, if frame position has changed 293 // or if the object is to-page|to-fly anchored. 294 if ( bAbsP || 295 pContact->ObjAnchoredAtPage() || 296 pContact->ObjAnchoredAtFly() ) 297 { 298 bNotify = true; 299 300 // assure that to-fly anchored Writer fly frames are 301 // registered at the correct page frame, if frame 302 // position has changed. 303 if ( bAbsP && pContact->ObjAnchoredAtFly() && 304 pObj->ISA(SwFlyFrm) ) 305 { 306 // determine to-fly anchored Writer fly frame 307 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj); 308 // determine page frame of to-fly anchored 309 // Writer fly frame 310 SwPageFrm* pFlyPageFrm = pFlyFrm->FindPageFrm(); 311 // determine page frame, if needed. 312 if ( !pPageFrm ) 313 { 314 pPageFrm = pFrm->FindPageFrm(); 315 } 316 if ( pPageFrm != pFlyPageFrm ) 317 { 318 ASSERT( pFlyPageFrm, "~SwFrmNotify: Fly from Nowhere" ); 319 if( pFlyPageFrm ) 320 pFlyPageFrm->MoveFly( pFlyFrm, pPageFrm ); 321 else 322 pPageFrm->AppendFlyToPage( pFlyFrm ); 323 } 324 } 325 } 326 // otherwise the objects are notified in dependence to 327 // its positioning and alignment 328 else 329 { 330 const SwFmtVertOrient& rVert = 331 pContact->GetFmt()->GetVertOrient(); 332 if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER || 333 rVert.GetVertOrient() == text::VertOrientation::BOTTOM || 334 rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) && 335 ( bChgHeight || bPrtHeight ) ) 336 { 337 bNotify = true; 338 } 339 if ( !bNotify ) 340 { 341 const SwFmtHoriOrient& rHori = 342 pContact->GetFmt()->GetHoriOrient(); 343 if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE || 344 rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA || 345 rHori.GetRelationOrient()== text::RelOrientation::FRAME ) && 346 ( bChgWidth || bPrtWidth || bChgFlyBasePos ) ) 347 { 348 bNotify = true; 349 } 350 } 351 } 352 } 353 else if ( bPrtWidth ) 354 { 355 // Notify as-character anchored objects, if printing area 356 // width has changed. 357 bNotify = true; 358 bNotifySize = true; 359 } 360 361 // perform notification via the corresponding invalidations 362 if ( bNotify ) 363 { 364 if ( pObj->ISA(SwFlyFrm) ) 365 { 366 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj); 367 if ( bNotifySize ) 368 pFlyFrm->_InvalidateSize(); 369 // --> OD 2004-12-08 #115759# - no invalidation of 370 // position for as-character anchored objects. 371 if ( !bAnchoredAsChar ) 372 { 373 pFlyFrm->_InvalidatePos(); 374 } 375 // <-- 376 pFlyFrm->_Invalidate(); 377 } 378 else if ( pObj->ISA(SwAnchoredDrawObject) ) 379 { 380 // --> OD 2004-12-08 #115759# - no invalidation of 381 // position for as-character anchored objects. 382 if ( !bAnchoredAsChar ) 383 { 384 pObj->InvalidateObjPos(); 385 } 386 // <-- 387 } 388 else 389 { 390 ASSERT( false, 391 "<SwCntntNotify::~SwCntntNotify()> - unknown anchored object type. Please inform OD." ); 392 } 393 } 394 } 395 } 396 } 397 else if( pFrm->IsTxtFrm() && bValidSize != pFrm->GetValidSizeFlag() ) 398 { 399 SwRootFrm *pRootFrm = pFrm->getRootFrm(); 400 if( pRootFrm && pRootFrm->IsAnyShellAccessible() && 401 pRootFrm->GetCurrShell() ) 402 { 403 pRootFrm->GetCurrShell()->Imp()->InvalidateAccessibleFrmContent( pFrm ); 404 } 405 } 406 407 // #i9046# Automatic frame width 408 SwFlyFrm* pFly = 0; 409 // --> FME 2004-10-21 #i35879# Do not trust the inf flags. pFrm does not 410 // necessarily have to have an upper! 411 if ( !pFrm->IsFlyFrm() && 0 != ( pFly = pFrm->ImplFindFlyFrm() ) ) 412 // <-- 413 { 414 // --> OD 2006-05-08 #i61999# 415 // no invalidation of columned Writer fly frames, because automatic 416 // width doesn't make sense for such Writer fly frames. 417 if ( pFly->Lower() && !pFly->Lower()->IsColumnFrm() ) 418 { 419 const SwFmtFrmSize &rFrmSz = pFly->GetFmt()->GetFrmSize(); 420 421 // This could be optimized. Basically the fly frame only has to 422 // be invalidated, if the first line of pFrm (if pFrm is a content 423 // frame, for other frame types its the print area) has changed its 424 // size and pFrm was responsible for the current width of pFly. On 425 // the other hand, this is only rarely used and re-calculation of 426 // the fly frame does not cause too much trouble. So we keep it this 427 // way: 428 if ( ATT_FIX_SIZE != rFrmSz.GetWidthSizeType() ) 429 { 430 // --> OD 2005-07-29 #i50668#, #i50998# - invalidation of position 431 // of as-character anchored fly frames not needed and can cause 432 // layout loops 433 if ( !pFly->ISA(SwFlyInCntFrm) ) 434 { 435 pFly->InvalidatePos(); 436 } 437 // <-- 438 pFly->InvalidateSize(); 439 } 440 } 441 // <-- 442 } 443 } 444 445 /*************************************************************************/ 446 447 SwLayNotify::SwLayNotify( SwLayoutFrm *pLayFrm ) : 448 SwFrmNotify( pLayFrm ), 449 bLowersComplete( sal_False ) 450 { 451 } 452 453 /*************************************************************************/ 454 455 // OD 2004-05-11 #i28701# - local method to invalidate the position of all 456 // frames inclusive its floating screen objects, which are lowers of the given 457 // layout frame 458 void lcl_InvalidatePosOfLowers( SwLayoutFrm& _rLayoutFrm ) 459 { 460 if( _rLayoutFrm.IsFlyFrm() && _rLayoutFrm.GetDrawObjs() ) 461 { 462 _rLayoutFrm.InvalidateObjs( true, false ); 463 } 464 465 SwFrm* pLowerFrm = _rLayoutFrm.Lower(); 466 while ( pLowerFrm ) 467 { 468 pLowerFrm->InvalidatePos(); 469 if ( pLowerFrm->IsTxtFrm() ) 470 { 471 static_cast<SwTxtFrm*>(pLowerFrm)->Prepare( PREP_POS_CHGD ); 472 } 473 else if ( pLowerFrm->IsTabFrm() ) 474 { 475 pLowerFrm->InvalidatePrt(); 476 } 477 478 pLowerFrm->InvalidateObjs( true, false ); 479 480 pLowerFrm = pLowerFrm->GetNext(); 481 }; 482 } 483 484 SwLayNotify::~SwLayNotify() 485 { 486 // --> OD 2005-07-29 #i49383# 487 if ( mbFrmDeleted ) 488 { 489 return; 490 } 491 // <-- 492 493 SwLayoutFrm *pLay = GetLay(); 494 SWRECTFN( pLay ) 495 sal_Bool bNotify = sal_False; 496 if ( pLay->Prt().SSize() != aPrt.SSize() ) 497 { 498 if ( !IsLowersComplete() ) 499 { 500 sal_Bool bInvaPercent; 501 502 if ( pLay->IsRowFrm() ) 503 { 504 bInvaPercent = sal_True; 505 long nNew = (pLay->Prt().*fnRect->fnGetHeight)(); 506 if( nNew != (aPrt.*fnRect->fnGetHeight)() ) 507 ((SwRowFrm*)pLay)->AdjustCells( nNew, sal_True); 508 if( (pLay->Prt().*fnRect->fnGetWidth)() 509 != (aPrt.*fnRect->fnGetWidth)() ) 510 ((SwRowFrm*)pLay)->AdjustCells( 0, sal_False ); 511 } 512 else 513 { 514 //Proportionale Anpassung der innenliegenden. 515 //1. Wenn der Formatierte kein Fly ist 516 //2. Wenn er keine Spalten enthaelt 517 //3. Wenn der Fly eine feste Hoehe hat und die Spalten in der 518 // Hoehe danebenliegen. 519 //4. niemals bei SectionFrms. 520 sal_Bool bLow; 521 if( pLay->IsFlyFrm() ) 522 { 523 if ( pLay->Lower() ) 524 { 525 bLow = !pLay->Lower()->IsColumnFrm() || 526 (pLay->Lower()->Frm().*fnRect->fnGetHeight)() 527 != (pLay->Prt().*fnRect->fnGetHeight)(); 528 } 529 else 530 bLow = sal_False; 531 } 532 else if( pLay->IsSctFrm() ) 533 { 534 if ( pLay->Lower() ) 535 { 536 if( pLay->Lower()->IsColumnFrm() && pLay->Lower()->GetNext() ) 537 bLow = pLay->Lower()->Frm().Height() != pLay->Prt().Height(); 538 else 539 bLow = pLay->Prt().Width() != aPrt.Width(); 540 } 541 else 542 bLow = sal_False; 543 } 544 else if( pLay->IsFooterFrm() && !pLay->HasFixSize() ) 545 bLow = pLay->Prt().Width() != aPrt.Width(); 546 else 547 bLow = sal_True; 548 bInvaPercent = bLow; 549 if ( bLow ) 550 { 551 pLay->ChgLowersProp( aPrt.SSize() ); 552 } 553 //Wenn die PrtArea gewachsen ist, so ist es moeglich, dass die 554 //Kette der Untergeordneten einen weiteren Frm aufnehmen kann, 555 //mithin muss also der 'moeglicherweise passende' Invalidiert werden. 556 //Das invalidieren lohnt nur, wenn es sich beim mir bzw. meinen 557 //Uppers um eine Moveable-Section handelt. 558 //Die PrtArea ist gewachsen, wenn die Breite oder die Hoehe groesser 559 //geworden ist. 560 if ( (pLay->Prt().Height() > aPrt.Height() || 561 pLay->Prt().Width() > aPrt.Width()) && 562 (pLay->IsMoveable() || pLay->IsFlyFrm()) ) 563 { 564 SwFrm *pTmpFrm = pLay->Lower(); 565 if ( pTmpFrm && pTmpFrm->IsFlowFrm() ) 566 { 567 while ( pTmpFrm->GetNext() ) 568 pTmpFrm = pTmpFrm->GetNext(); 569 pTmpFrm->InvalidateNextPos(); 570 } 571 } 572 } 573 bNotify = sal_True; 574 //TEUER!! aber wie macht man es geschickter? 575 if( bInvaPercent ) 576 pLay->InvaPercentLowers( pLay->Prt().Height() - aPrt.Height() ); 577 } 578 if ( pLay->IsTabFrm() ) 579 //Damit _nur_ der Shatten bei Groessenaenderungen gemalt wird. 580 ((SwTabFrm*)pLay)->SetComplete(); 581 else 582 { 583 const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell(); 584 if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) || 585 !(pLay->GetType() & (FRM_BODY | FRM_PAGE)) ) 586 //Damit die untergeordneten sauber retouchiert werden. 587 //Problembsp: Flys an den Henkeln packen und verkleinern. 588 //Nicht fuer Body und Page, sonst flackerts beim HTML-Laden. 589 pLay->SetCompletePaint(); 590 } 591 } 592 //Lower benachrichtigen wenn sich die Position veraendert hat. 593 const sal_Bool bPrtPos = POS_DIFF( aPrt, pLay->Prt() ); 594 const sal_Bool bPos = bPrtPos || POS_DIFF( aFrm, pLay->Frm() ); 595 const sal_Bool bSize = pLay->Frm().SSize() != aFrm.SSize(); 596 597 if ( bPos && pLay->Lower() && !IsLowersComplete() ) 598 pLay->Lower()->InvalidatePos(); 599 600 if ( bPrtPos ) 601 pLay->SetCompletePaint(); 602 603 //Nachfolger benachrichtigen wenn sich die SSize geaendert hat. 604 if ( bSize ) 605 { 606 if( pLay->GetNext() ) 607 { 608 if ( pLay->GetNext()->IsLayoutFrm() ) 609 pLay->GetNext()->_InvalidatePos(); 610 else 611 pLay->GetNext()->InvalidatePos(); 612 } 613 else if( pLay->IsSctFrm() ) 614 pLay->InvalidateNextPos(); 615 } 616 if ( !IsLowersComplete() && 617 !(pLay->GetType()&(FRM_FLY|FRM_SECTION) && 618 pLay->Lower() && pLay->Lower()->IsColumnFrm()) && 619 (bPos || bNotify) && !(pLay->GetType() & 0x1823) ) //Tab, Row, FtnCont, Root, Page 620 { 621 // --> OD 2005-03-11 #i44016# - force unlock of position of lower objects. 622 // --> OD 2005-03-30 #i43913# - no unlock of position of objects, 623 // if <pLay> is a cell frame, and its table frame resp. its parent table 624 // frame is locked. 625 // --> OD 2005-04-15 #i47458# - force unlock of position of lower objects, 626 // only if position of layout frame has changed. 627 bool bUnlockPosOfObjs( bPos ); 628 if ( bUnlockPosOfObjs && pLay->IsCellFrm() ) 629 { 630 SwTabFrm* pTabFrm( pLay->FindTabFrm() ); 631 if ( pTabFrm && 632 ( pTabFrm->IsJoinLocked() || 633 ( pTabFrm->IsFollow() && 634 pTabFrm->FindMaster()->IsJoinLocked() ) ) ) 635 { 636 bUnlockPosOfObjs = false; 637 } 638 } 639 // --> OD 2005-05-18 #i49383# - check for footnote frame, if unlock 640 // of position of lower objects is allowed. 641 else if ( bUnlockPosOfObjs && pLay->IsFtnFrm() ) 642 { 643 bUnlockPosOfObjs = static_cast<SwFtnFrm*>(pLay)->IsUnlockPosOfLowerObjs(); 644 } 645 // <-- 646 // --> OD 2005-07-29 #i51303# - no unlock of object positions for sections 647 else if ( bUnlockPosOfObjs && pLay->IsSctFrm() ) 648 { 649 bUnlockPosOfObjs = false; 650 } 651 // <-- 652 pLay->NotifyLowerObjs( bUnlockPosOfObjs ); 653 // <-- 654 } 655 if ( bPos && pLay->IsFtnFrm() && pLay->Lower() ) 656 { 657 // OD 2004-05-11 #i28701# 658 ::lcl_InvalidatePosOfLowers( *pLay ); 659 } 660 if( ( bPos || bSize ) && pLay->IsFlyFrm() && ((SwFlyFrm*)pLay)->GetAnchorFrm() 661 && ((SwFlyFrm*)pLay)->GetAnchorFrm()->IsFlyFrm() ) 662 ((SwFlyFrm*)pLay)->AnchorFrm()->InvalidateSize(); 663 } 664 665 /*************************************************************************/ 666 667 SwFlyNotify::SwFlyNotify( SwFlyFrm *pFlyFrm ) : 668 SwLayNotify( pFlyFrm ), 669 // --> OD 2004-11-24 #115759# - keep correct page frame - the page frame 670 // the Writer fly frame is currently registered at. 671 pOldPage( pFlyFrm->GetPageFrm() ), 672 // <-- 673 aFrmAndSpace( pFlyFrm->GetObjRectWithSpaces() ) 674 { 675 } 676 677 /*************************************************************************/ 678 679 SwFlyNotify::~SwFlyNotify() 680 { 681 // --> OD 2005-07-29 #i49383# 682 if ( mbFrmDeleted ) 683 { 684 return; 685 } 686 // <-- 687 688 SwFlyFrm *pFly = GetFly(); 689 if ( pFly->IsNotifyBack() ) 690 { 691 ViewShell *pSh = pFly->getRootFrm()->GetCurrShell(); 692 SwViewImp *pImp = pSh ? pSh->Imp() : 0; 693 if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() ) 694 { 695 //Wenn in der LayAction das IsAgain gesetzt ist kann es sein, 696 //dass die alte Seite inzwischen vernichtet wurde! 697 ::Notify( pFly, pOldPage, aFrmAndSpace, &aPrt ); 698 // --> OD 2004-10-20 #i35640# - additional notify anchor text frame, 699 // if Writer fly frame has changed its page 700 if ( pFly->GetAnchorFrm()->IsTxtFrm() && 701 pFly->GetPageFrm() != pOldPage ) 702 { 703 pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE ); 704 } 705 // <-- 706 } 707 pFly->ResetNotifyBack(); 708 } 709 710 //Haben sich Groesse oder Position geaendert, so sollte die View 711 //das wissen. 712 SWRECTFN( pFly ) 713 const bool bPosChgd = POS_DIFF( aFrm, pFly->Frm() ); 714 const bool bFrmChgd = pFly->Frm().SSize() != aFrm.SSize(); 715 const bool bPrtChgd = aPrt != pFly->Prt(); 716 if ( bPosChgd || bFrmChgd || bPrtChgd ) 717 { 718 pFly->NotifyDrawObj(); 719 } 720 if ( bPosChgd && aFrm.Pos().X() != WEIT_WECH ) 721 { 722 // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames. 723 // reason: New positioning and alignment (e.g. to-paragraph anchored, 724 // but aligned at page) are introduced. 725 // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower 726 // floating screen objects by calling method <SwLayoutFrm::NotifyLowerObjs()>. 727 728 if ( pFly->IsFlyAtCntFrm() ) 729 { 730 SwFrm *pNxt = pFly->AnchorFrm()->FindNext(); 731 if ( pNxt ) 732 { 733 pNxt->InvalidatePos(); 734 } 735 } 736 737 // --> OD 2004-11-05 #i26945# - notify anchor. 738 // Needed for negative positioned Writer fly frames 739 if ( pFly->GetAnchorFrm()->IsTxtFrm() ) 740 { 741 pFly->AnchorFrm()->Prepare( PREP_FLY_LEAVE ); 742 } 743 // <-- 744 } 745 746 // OD 2004-05-13 #i28701# 747 // --> OD 2005-03-21 #i45180# - no adjustment of layout process flags and 748 // further notifications/invalidations, if format is called by grow/shrink 749 if ( pFly->ConsiderObjWrapInfluenceOnObjPos() && 750 ( !pFly->ISA(SwFlyFreeFrm) || 751 !static_cast<SwFlyFreeFrm*>(pFly)->IsNoMoveOnCheckClip() ) ) 752 // <-- 753 { 754 // --> OD 2005-09-05 #i54138# - suppress restart of the layout process 755 // on changed frame height. 756 // Note: It doesn't seem to be necessary and can cause layout loops. 757 if ( bPosChgd ) 758 // <-- 759 { 760 // indicate a restart of the layout process 761 pFly->SetRestartLayoutProcess( true ); 762 } 763 else 764 { 765 // lock position 766 pFly->LockPosition(); 767 768 if ( !pFly->ConsiderForTextWrap() ) 769 { 770 // indicate that object has to be considered for text wrap 771 pFly->SetConsiderForTextWrap( true ); 772 // invalidate 'background' in order to allow its 'background' 773 // to wrap around it. 774 pFly->NotifyBackground( pFly->GetPageFrm(), 775 pFly->GetObjRectWithSpaces(), 776 PREP_FLY_ARRIVE ); 777 // invalidate position of anchor frame in order to force 778 // a re-format of the anchor frame, which also causes a 779 // re-format of the invalid previous frames of the anchor frame. 780 pFly->AnchorFrm()->InvalidatePos(); 781 } 782 } 783 } 784 } 785 786 /*************************************************************************/ 787 788 SwCntntNotify::SwCntntNotify( SwCntntFrm *pCntntFrm ) : 789 SwFrmNotify( pCntntFrm ), 790 // OD 08.01.2004 #i11859# 791 mbChkHeightOfLastLine( false ), 792 mnHeightOfLastLine( 0L ), 793 // OD 2004-02-26 #i25029# 794 mbInvalidatePrevPrtArea( false ), 795 mbBordersJoinedWithPrev( false ) 796 { 797 // OD 08.01.2004 #i11859# 798 if ( pCntntFrm->IsTxtFrm() ) 799 { 800 SwTxtFrm* pTxtFrm = static_cast<SwTxtFrm*>(pCntntFrm); 801 if ( !pTxtFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::OLD_LINE_SPACING) ) 802 { 803 const SwAttrSet* pSet = pTxtFrm->GetAttrSet(); 804 const SvxLineSpacingItem &rSpace = pSet->GetLineSpacing(); 805 if ( rSpace.GetInterLineSpaceRule() == SVX_INTER_LINE_SPACE_PROP ) 806 { 807 mbChkHeightOfLastLine = true; 808 mnHeightOfLastLine = pTxtFrm->GetHeightOfLastLine(); 809 } 810 } 811 } 812 } 813 814 /*************************************************************************/ 815 816 SwCntntNotify::~SwCntntNotify() 817 { 818 // --> OD 2005-07-29 #i49383# 819 if ( mbFrmDeleted ) 820 { 821 return; 822 } 823 // <-- 824 825 SwCntntFrm *pCnt = GetCnt(); 826 if ( bSetCompletePaintOnInvalidate ) 827 pCnt->SetCompletePaint(); 828 829 SWRECTFN( pCnt ) 830 if ( pCnt->IsInTab() && ( POS_DIFF( pCnt->Frm(), aFrm ) || 831 pCnt->Frm().SSize() != aFrm.SSize())) 832 { 833 SwLayoutFrm* pCell = pCnt->GetUpper(); 834 while( !pCell->IsCellFrm() && pCell->GetUpper() ) 835 pCell = pCell->GetUpper(); 836 ASSERT( pCell->IsCellFrm(), "Where's my cell?" ); 837 if ( text::VertOrientation::NONE != pCell->GetFmt()->GetVertOrient().GetVertOrient() ) 838 pCell->InvalidatePrt(); //fuer vertikale Ausrichtung. 839 } 840 841 // OD 2004-02-26 #i25029# 842 if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev && 843 pCnt->IsTxtFrm() && 844 !pCnt->IsFollow() && !pCnt->GetIndPrev() ) 845 { 846 // determine previous frame 847 SwFrm* pPrevFrm = pCnt->FindPrev(); 848 // skip empty section frames and hidden text frames 849 { 850 while ( pPrevFrm && 851 ( ( pPrevFrm->IsSctFrm() && 852 !static_cast<SwSectionFrm*>(pPrevFrm)->GetSection() ) || 853 ( pPrevFrm->IsTxtFrm() && 854 static_cast<SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) ) ) 855 { 856 pPrevFrm = pPrevFrm->FindPrev(); 857 } 858 } 859 860 // Invalidate printing area of found previous frame 861 if ( pPrevFrm ) 862 { 863 if ( pPrevFrm->IsSctFrm() ) 864 { 865 if ( pCnt->IsInSct() ) 866 { 867 // Note: found previous frame is a section frame and 868 // <pCnt> is also inside a section. 869 // Thus due to <mbBordersJoinedWithPrev>, 870 // <pCnt> had joined its borders/shadow with the 871 // last content of the found section. 872 // Invalidate printing area of last content in found section. 873 SwFrm* pLstCntntOfSctFrm = 874 static_cast<SwSectionFrm*>(pPrevFrm)->FindLastCntnt(); 875 if ( pLstCntntOfSctFrm ) 876 { 877 pLstCntntOfSctFrm->InvalidatePrt(); 878 } 879 } 880 } 881 else 882 { 883 pPrevFrm->InvalidatePrt(); 884 } 885 } 886 } 887 888 const bool bFirst = (aFrm.*fnRect->fnGetWidth)() == 0; 889 890 if ( pCnt->IsNoTxtFrm() ) 891 { 892 //Aktive PlugIn's oder OLE-Objekte sollten etwas von der Veraenderung 893 //mitbekommen, damit sie Ihr Window entsprechend verschieben. 894 ViewShell *pSh = pCnt->getRootFrm()->GetCurrShell(); 895 if ( pSh ) 896 { 897 SwOLENode *pNd; 898 if ( 0 != (pNd = pCnt->GetNode()->GetOLENode()) && 899 (pNd->GetOLEObj().IsOleRef() || 900 pNd->IsOLESizeInvalid()) ) 901 { 902 // --> OD #i117189# 903 const bool bNoTxtFrmPrtAreaChanged = 904 ( aPrt.SSize().Width() != 0 && 905 aPrt.SSize().Height() != 0 ) && 906 aPrt.SSize() != pCnt->Prt().SSize(); 907 // <-- 908 ASSERT( pCnt->IsInFly(), "OLE not in FlyFrm" ); 909 SwFlyFrm *pFly = pCnt->FindFlyFrm(); 910 svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject(); 911 SwFEShell *pFESh = 0; 912 ViewShell *pTmp = pSh; 913 do 914 { if ( pTmp->ISA( SwCrsrShell ) ) 915 { 916 pFESh = (SwFEShell*)pTmp; 917 // #108369#: Here used to be the condition if (!bFirst). 918 // I think this should mean "do not call CalcAndSetScale" 919 // if the frame is formatted for the first time. 920 // Unfortunately this is not valid anymore since the 921 // SwNoTxtFrm already gets a width during CalcLowerPreps. 922 // Nevertheless, the indention of !bFirst seemed to be 923 // to assure that the OLE objects have already been notified 924 // if necessary before calling CalcAndSetScale. 925 // So I replaced !bFirst by !IsOLESizeInvalid. There is 926 // one additional problem specific to the word import: 927 // The layout is calculated _before_ calling PrtOLENotify, 928 // and the OLE objects are not invalidated during import. 929 // Therefore I added the condition !IsUpdateExpFld, 930 // have a look at the occurrence of CalcLayout in 931 // uiview/view.cxx. 932 if ( !pNd->IsOLESizeInvalid() && 933 !pSh->GetDoc()->IsUpdateExpFld() ) 934 pFESh->CalcAndSetScale( xObj, 935 &pFly->Prt(), &pFly->Frm(), 936 bNoTxtFrmPrtAreaChanged ); 937 } 938 pTmp = (ViewShell*)pTmp->GetNext(); 939 } while ( pTmp != pSh ); 940 941 if ( pFESh && pNd->IsOLESizeInvalid() ) 942 { 943 pNd->SetOLESizeInvalid( sal_False ); 944 //TODO/LATER: needs OnDocumentPrinterChanged 945 //xObj->OnDocumentPrinterChanged( pNd->GetDoc()->getPrinter( false ) ); 946 pFESh->CalcAndSetScale( xObj );//Client erzeugen lassen. 947 } 948 } 949 //dito Animierte Grafiken 950 if ( Frm().HasArea() && ((SwNoTxtFrm*)pCnt)->HasAnimation() ) 951 { 952 ((SwNoTxtFrm*)pCnt)->StopAnimation(); 953 pSh->InvalidateWindows( Frm() ); 954 } 955 } 956 } 957 958 if ( bFirst ) 959 { 960 pCnt->SetRetouche(); //fix(13870) 961 962 SwDoc *pDoc = pCnt->GetNode()->GetDoc(); 963 if ( pDoc->GetSpzFrmFmts()->Count() && 964 pDoc->DoesContainAtPageObjWithContentAnchor() && !pDoc->IsNewDoc() ) 965 { 966 // If certain import filters for foreign file format import 967 // AT_PAGE anchored objects, the corresponding page number is 968 // typically not known. In this case the content position is 969 // stored at which the anchored object is found in the 970 // imported document. 971 // When this content is formatted it is the time at which 972 // the page is known. Thus, this data can be corrected now. 973 974 const SwPageFrm* pPage = 0; 975 SwNodeIndex *pIdx = 0; 976 SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts(); 977 for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i ) 978 { 979 SwFrmFmt *pFmt = (*pTbl)[i]; 980 const SwFmtAnchor &rAnch = pFmt->GetAnchor(); 981 if ( FLY_AT_PAGE != rAnch.GetAnchorId() || 982 rAnch.GetCntntAnchor() == 0 ) 983 { 984 continue; 985 } 986 987 if ( !pIdx ) 988 { 989 pIdx = new SwNodeIndex( *pCnt->GetNode() ); 990 } 991 if ( rAnch.GetCntntAnchor()->nNode == *pIdx ) 992 { 993 ASSERT( false, "<SwCntntNotify::~SwCntntNotify()> - to page anchored object with content position. Please inform OD." ); 994 if ( !pPage ) 995 { 996 pPage = pCnt->FindPageFrm(); 997 } 998 SwFmtAnchor aAnch( rAnch ); 999 aAnch.SetAnchor( 0 ); 1000 aAnch.SetPageNum( pPage->GetPhyPageNum() ); 1001 pFmt->SetFmtAttr( aAnch ); 1002 if ( RES_DRAWFRMFMT != pFmt->Which() ) 1003 { 1004 pFmt->MakeFrms(); 1005 } 1006 } 1007 } 1008 delete pIdx; 1009 } 1010 } 1011 1012 // OD 12.01.2004 #i11859# - invalidate printing area of following frame, 1013 // if height of last line has changed. 1014 if ( pCnt->IsTxtFrm() && mbChkHeightOfLastLine ) 1015 { 1016 if ( mnHeightOfLastLine != static_cast<SwTxtFrm*>(pCnt)->GetHeightOfLastLine() ) 1017 { 1018 pCnt->InvalidateNextPrtArea(); 1019 } 1020 } 1021 1022 // --> OD 2005-03-07 #i44049# 1023 if ( pCnt->IsTxtFrm() && POS_DIFF( aFrm, pCnt->Frm() ) ) 1024 { 1025 pCnt->InvalidateObjs( true ); 1026 } 1027 // <-- 1028 1029 // --> OD 2005-04-12 #i43255# - move code to invalidate at-character 1030 // anchored objects due to a change of its anchor character from 1031 // method <SwTxtFrm::Format(..)>. 1032 if ( pCnt->IsTxtFrm() ) 1033 { 1034 SwTxtFrm* pMasterFrm = pCnt->IsFollow() 1035 ? static_cast<SwTxtFrm*>(pCnt)->FindMaster() 1036 : static_cast<SwTxtFrm*>(pCnt); 1037 if ( pMasterFrm && !pMasterFrm->IsFlyLock() && 1038 pMasterFrm->GetDrawObjs() ) 1039 { 1040 SwSortedObjs* pObjs = pMasterFrm->GetDrawObjs(); 1041 for ( sal_uInt32 i = 0; i < pObjs->Count(); ++i ) 1042 { 1043 SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 1044 if ( pAnchoredObj->GetFrmFmt().GetAnchor().GetAnchorId() 1045 == FLY_AT_CHAR ) 1046 { 1047 pAnchoredObj->CheckCharRectAndTopOfLine( !pMasterFrm->IsEmpty() ); 1048 } 1049 } 1050 } 1051 } 1052 // <-- 1053 } 1054 1055 /*************************************************************************/ 1056 1057 void AppendObjs( const SwSpzFrmFmts *pTbl, sal_uLong nIndex, 1058 SwFrm *pFrm, SwPageFrm *pPage ) 1059 { 1060 for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i ) 1061 { 1062 SwFrmFmt *pFmt = (SwFrmFmt*)(*pTbl)[i]; 1063 const SwFmtAnchor &rAnch = pFmt->GetAnchor(); 1064 if ( rAnch.GetCntntAnchor() && 1065 (rAnch.GetCntntAnchor()->nNode.GetIndex() == nIndex) ) 1066 { 1067 const bool bFlyAtFly = rAnch.GetAnchorId() == FLY_AT_FLY; // LAYER_IMPL 1068 //Wird ein Rahmen oder ein SdrObject beschrieben? 1069 const bool bSdrObj = RES_DRAWFRMFMT == pFmt->Which(); 1070 // OD 23.06.2003 #108784# - append also drawing objects anchored 1071 // as character. 1072 const bool bDrawObjInCntnt = bSdrObj && 1073 (rAnch.GetAnchorId() == FLY_AS_CHAR); 1074 1075 if( bFlyAtFly || 1076 (rAnch.GetAnchorId() == FLY_AT_PARA) || 1077 (rAnch.GetAnchorId() == FLY_AT_CHAR) || 1078 bDrawObjInCntnt ) 1079 { 1080 SdrObject* pSdrObj = 0; 1081 if ( bSdrObj && 0 == (pSdrObj = pFmt->FindSdrObject()) ) 1082 { 1083 ASSERT( !bSdrObj, "DrawObject not found." ); 1084 pFmt->GetDoc()->DelFrmFmt( pFmt ); 1085 --i; 1086 continue; 1087 } 1088 if ( pSdrObj ) 1089 { 1090 if ( !pSdrObj->GetPage() ) 1091 { 1092 pFmt->getIDocumentDrawModelAccess()->GetDrawModel()->GetPage(0)-> 1093 InsertObject(pSdrObj, pSdrObj->GetOrdNumDirect()); 1094 } 1095 1096 SwDrawContact* pNew = 1097 static_cast<SwDrawContact*>(GetUserCall( pSdrObj )); 1098 if ( !pNew->GetAnchorFrm() ) 1099 { 1100 pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( 0L )) ); 1101 } 1102 // OD 19.06.2003 #108784# - add 'virtual' drawing object, 1103 // if necessary. But control objects have to be excluded. 1104 else if ( !::CheckControlLayer( pSdrObj ) && 1105 pNew->GetAnchorFrm() != pFrm && 1106 !pNew->GetDrawObjectByAnchorFrm( *pFrm ) ) 1107 { 1108 SwDrawVirtObj* pDrawVirtObj = pNew->AddVirtObj(); 1109 pFrm->AppendDrawObj( *(pNew->GetAnchoredObj( pDrawVirtObj )) ); 1110 1111 // for repaint, use new ActionChanged() 1112 // pDrawVirtObj->SendRepaintBroadcast(); 1113 pDrawVirtObj->ActionChanged(); 1114 } 1115 1116 } 1117 else 1118 { 1119 SwFlyFrm *pFly; 1120 if( bFlyAtFly ) 1121 pFly = new SwFlyLayFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm ); 1122 else 1123 pFly = new SwFlyAtCntFrm( (SwFlyFrmFmt*)pFmt, pFrm, pFrm ); 1124 pFly->Lock(); 1125 pFrm->AppendFly( pFly ); 1126 pFly->Unlock(); 1127 if ( pPage ) 1128 ::RegistFlys( pPage, pFly ); 1129 } 1130 } 1131 } 1132 } 1133 } 1134 1135 bool lcl_ObjConnected( SwFrmFmt *pFmt, const SwFrm* pSib ) 1136 { 1137 SwIterator<SwFlyFrm,SwFmt> aIter( *pFmt ); 1138 if ( RES_FLYFRMFMT == pFmt->Which() ) 1139 { 1140 const SwRootFrm* pRoot = pSib ? pSib->getRootFrm() : 0; 1141 const SwFlyFrm* pTmpFrm; 1142 for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() ) 1143 { 1144 if(! pRoot || pRoot == pTmpFrm->getRootFrm() ) 1145 return true; 1146 } 1147 } 1148 else 1149 { 1150 SwDrawContact *pContact = SwIterator<SwDrawContact,SwFmt>::FirstElement(*pFmt); 1151 if ( pContact ) 1152 return pContact->GetAnchorFrm() != 0; 1153 } 1154 return false; 1155 } 1156 1157 /** helper method to determine, if a <SwFrmFmt>, which has an object connected, 1158 is located in header or footer. 1159 1160 OD 23.06.2003 #108784# 1161 1162 @author OD 1163 */ 1164 bool lcl_InHeaderOrFooter( SwFrmFmt& _rFmt ) 1165 { 1166 bool bRetVal = false; 1167 1168 const SwFmtAnchor& rAnch = _rFmt.GetAnchor(); 1169 1170 if (rAnch.GetAnchorId() != FLY_AT_PAGE) 1171 { 1172 bRetVal = _rFmt.GetDoc()->IsInHeaderFooter( rAnch.GetCntntAnchor()->nNode ); 1173 } 1174 1175 return bRetVal; 1176 } 1177 1178 void AppendAllObjs( const SwSpzFrmFmts *pTbl, const SwFrm* pSib ) 1179 { 1180 //Verbinden aller Objekte, die in der SpzTbl beschrieben sind mit dem 1181 //Layout. 1182 //Wenn sich nix mehr tut hoeren wir auf. Dann koennen noch Formate 1183 //uebrigbleiben, weil wir weder zeichengebunde Rahmen verbinden noch 1184 //Objecte die in zeichengebundenen verankert sind. 1185 1186 SwSpzFrmFmts aCpy( 255, 255 ); 1187 aCpy.Insert( pTbl, 0 ); 1188 1189 sal_uInt16 nOldCnt = USHRT_MAX; 1190 1191 while ( aCpy.Count() && aCpy.Count() != nOldCnt ) 1192 { 1193 nOldCnt = aCpy.Count(); 1194 for ( int i = 0; i < int(aCpy.Count()); ++i ) 1195 { 1196 SwFrmFmt *pFmt = (SwFrmFmt*)aCpy[ sal_uInt16(i) ]; 1197 const SwFmtAnchor &rAnch = pFmt->GetAnchor(); 1198 sal_Bool bRemove = sal_False; 1199 if ((rAnch.GetAnchorId() == FLY_AT_PAGE) || 1200 (rAnch.GetAnchorId() == FLY_AS_CHAR)) 1201 { 1202 //Seitengebunde sind bereits verankert, zeichengebundene 1203 //will ich hier nicht. 1204 bRemove = sal_True; 1205 } 1206 else if ( sal_False == (bRemove = ::lcl_ObjConnected( pFmt, pSib )) || 1207 ::lcl_InHeaderOrFooter( *pFmt ) ) 1208 { 1209 // OD 23.06.2003 #108784# - correction: for objects in header 1210 // or footer create frames, in spite of the fact that an connected 1211 // objects already exists. 1212 //Fuer Flys und DrawObjs nur dann ein MakeFrms rufen wenn noch 1213 //keine abhaengigen Existieren, andernfalls, oder wenn das 1214 //MakeFrms keine abhaengigen erzeugt, entfernen. 1215 pFmt->MakeFrms(); 1216 bRemove = ::lcl_ObjConnected( pFmt, pSib ); 1217 } 1218 if ( bRemove ) 1219 { 1220 aCpy.Remove( sal_uInt16(i) ); 1221 --i; 1222 } 1223 } 1224 } 1225 aCpy.Remove( 0, aCpy.Count() ); 1226 } 1227 1228 /** local method to set 'working' position for newly inserted frames 1229 1230 OD 12.08.2003 #i17969# 1231 1232 @author OD 1233 */ 1234 void lcl_SetPos( SwFrm& _rNewFrm, 1235 const SwLayoutFrm& _rLayFrm ) 1236 { 1237 SWRECTFN( (&_rLayFrm) ) 1238 (_rNewFrm.Frm().*fnRect->fnSetPos)( (_rLayFrm.Frm().*fnRect->fnGetPos)() ); 1239 // move position by one SwTwip in text flow direction in order to get 1240 // notifications for a new calculated position after its formatting. 1241 if ( bVert ) 1242 _rNewFrm.Frm().Pos().X() -= 1; 1243 else 1244 _rNewFrm.Frm().Pos().Y() += 1; 1245 } 1246 1247 void MA_FASTCALL _InsertCnt( SwLayoutFrm *pLay, SwDoc *pDoc, 1248 sal_uLong nIndex, sal_Bool bPages, sal_uLong nEndIndex, 1249 SwFrm *pPrv ) 1250 { 1251 pDoc->BlockIdling(); 1252 SwRootFrm* pLayout = pLay->getRootFrm(); 1253 const sal_Bool bOldCallbackActionEnabled = pLayout ? pLayout->IsCallbackActionEnabled() : sal_False; 1254 if( bOldCallbackActionEnabled ) 1255 pLayout->SetCallbackActionEnabled( sal_False ); 1256 1257 //Bei der Erzeugung des Layouts wird bPages mit sal_True uebergeben. Dann 1258 //werden schon mal alle x Absaetze neue Seiten angelegt. Bei umbruechen 1259 //und/oder Pagedescriptorwechseln werden gleich die entsprechenden Seiten 1260 //angelegt. 1261 //Vorteil ist, das einerseits schon eine annaehernd realistische Zahl von 1262 //Seiten angelegt wird, vor allem aber gibt es nicht mehr eine schier 1263 //lange Kette von Absaetzen teuer verschoben werden muss, bis sie sich auf 1264 //ertraegliches mass reduziert hat. 1265 //Wir gehen mal davon aus, da? 20 Absaetze auf eine Seite passen 1266 //Damit es in extremen Faellen nicht gar so heftig rechenen wir je nach 1267 //Node noch etwas drauf. 1268 //Wenn in der DocStatistik eine brauchebare Seitenzahl angegeben ist 1269 //(wird beim Schreiben gepflegt), so wird von dieser Seitenanzahl 1270 //ausgegengen. 1271 const sal_Bool bStartPercent = bPages && !nEndIndex; 1272 1273 SwPageFrm *pPage = pLay->FindPageFrm(); 1274 const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts(); 1275 SwFrm *pFrm = 0; 1276 sal_Bool bBreakAfter = sal_False; 1277 1278 SwActualSection *pActualSection = 0; 1279 SwLayHelper *pPageMaker; 1280 1281 //Wenn das Layout erzeugt wird (bPages == sal_True) steuern wir den Progress 1282 //an. Flys und DrawObjekte werden dann nicht gleich verbunden, dies 1283 //passiert erst am Ende der Funktion. 1284 if ( bPages ) 1285 { 1286 // Attention: the SwLayHelper class uses references to the content-, 1287 // page-, layout-frame etc. and may change them! 1288 pPageMaker = new SwLayHelper( pDoc, pFrm, pPrv, pPage, pLay, 1289 pActualSection, bBreakAfter, nIndex, 0 == nEndIndex ); 1290 if( bStartPercent ) 1291 { 1292 const sal_uLong nPageCount = pPageMaker->CalcPageCount(); 1293 if( nPageCount ) 1294 bObjsDirect = sal_False; 1295 } 1296 } 1297 else 1298 pPageMaker = NULL; 1299 1300 if( pLay->IsInSct() && 1301 ( pLay->IsSctFrm() || pLay->GetUpper() ) ) // Hierdurch werden Frischlinge 1302 // abgefangen, deren Flags noch nicht ermittelt werden koennen, 1303 // so z.B. beim Einfuegen einer Tabelle 1304 { 1305 SwSectionFrm* pSct = pLay->FindSctFrm(); 1306 // Wenn Inhalt in eine Fussnote eingefuegt wird, die in einem spaltigen 1307 // Bereich liegt, so darf der spaltige Bereich nicht aufgebrochen werden. 1308 // Nur wenn im Innern der Fussnote ein Bereich liegt, ist dies ein 1309 // Kandidat fuer pActualSection. 1310 // Gleiches gilt fuer Bereiche in Tabellen, wenn innerhalb einer Tabelle 1311 // eingefuegt wird, duerfen nur Bereiche, die ebenfalls im Innern liegen, 1312 // aufgebrochen werden. 1313 if( ( !pLay->IsInFtn() || pSct->IsInFtn() ) && 1314 ( !pLay->IsInTab() || pSct->IsInTab() ) ) 1315 { 1316 pActualSection = new SwActualSection( 0, pSct, 0 ); 1317 ASSERT( !pLay->Lower() || !pLay->Lower()->IsColumnFrm(), 1318 "_InsertCnt: Wrong Call" ); 1319 } 1320 } 1321 1322 //If a section is "open", the pActualSection points to an SwActualSection. 1323 //If the page breaks, for "open" sections a follow will created. 1324 //For nested sections (which have, however, not a nested layout), 1325 //the SwActualSection class has a member, which points to an upper(section). 1326 //When the "inner" section finishs, the upper will used instead. 1327 1328 while( sal_True ) 1329 { 1330 SwNode *pNd = pDoc->GetNodes()[nIndex]; 1331 if ( pNd->IsCntntNode() ) 1332 { 1333 SwCntntNode* pNode = (SwCntntNode*)pNd; 1334 pFrm = pNode->IsTxtNode() ? new SwTxtFrm( (SwTxtNode*)pNode, pLay ) : 1335 pNode->MakeFrm( pLay ); 1336 if( pPageMaker ) 1337 pPageMaker->CheckInsert( nIndex ); 1338 1339 pFrm->InsertBehind( pLay, pPrv ); 1340 // --> OD 2005-12-01 #i27138# 1341 // notify accessibility paragraphs objects about changed 1342 // CONTENT_FLOWS_FROM/_TO relation. 1343 // Relation CONTENT_FLOWS_FROM for next paragraph will change 1344 // and relation CONTENT_FLOWS_TO for previous paragraph will change. 1345 if ( pFrm->IsTxtFrm() ) 1346 { 1347 ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() ); 1348 // no notification, if <ViewShell> is in construction 1349 if ( pViewShell && !pViewShell->IsInConstructor() && 1350 pViewShell->GetLayout() && 1351 pViewShell->GetLayout()->IsAnyShellAccessible() ) 1352 { 1353 pViewShell->InvalidateAccessibleParaFlowRelation( 1354 dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )), 1355 dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) ); 1356 // --> OD 2006-08-28 #i68958# 1357 // The information flags of the text frame are validated 1358 // in methods <FindNextCnt(..)> and <FindPrevCnt(..)>. 1359 // The information flags have to be invalidated, because 1360 // it is possible, that the one of its upper frames 1361 // isn't inserted into the layout. 1362 pFrm->InvalidateInfFlags(); 1363 // <-- 1364 } 1365 } 1366 // <-- 1367 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout 1368 // for setting position at newly inserted frame 1369 lcl_SetPos( *pFrm, *pLay ); 1370 pPrv = pFrm; 1371 1372 if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects ) 1373 AppendObjs( pTbl, nIndex, pFrm, pPage ); 1374 } 1375 else if ( pNd->IsTableNode() ) 1376 { //Sollten wir auf eine Tabelle gestossen sein? 1377 SwTableNode *pTblNode = (SwTableNode*)pNd; 1378 1379 // #108116# loading may produce table structures that GCLines 1380 // needs to clean up. To keep table formulas correct, change 1381 // all table formulas to internal (BOXPTR) representation. 1382 SwTableFmlUpdate aMsgHnt( &pTblNode->GetTable() ); 1383 aMsgHnt.eFlags = TBL_BOXPTR; 1384 pDoc->UpdateTblFlds( &aMsgHnt ); 1385 pTblNode->GetTable().GCLines(); 1386 1387 pFrm = pTblNode->MakeFrm( pLay ); 1388 1389 if( pPageMaker ) 1390 pPageMaker->CheckInsert( nIndex ); 1391 1392 pFrm->InsertBehind( pLay, pPrv ); 1393 // --> OD 2005-12-01 #i27138# 1394 // notify accessibility paragraphs objects about changed 1395 // CONTENT_FLOWS_FROM/_TO relation. 1396 // Relation CONTENT_FLOWS_FROM for next paragraph will change 1397 // and relation CONTENT_FLOWS_TO for previous paragraph will change. 1398 { 1399 ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() ); 1400 // no notification, if <ViewShell> is in construction 1401 if ( pViewShell && !pViewShell->IsInConstructor() && 1402 pViewShell->GetLayout() && 1403 pViewShell->GetLayout()->IsAnyShellAccessible() ) 1404 { 1405 pViewShell->InvalidateAccessibleParaFlowRelation( 1406 dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )), 1407 dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) ); 1408 } 1409 } 1410 // <-- 1411 if ( bObjsDirect && pTbl->Count() ) 1412 ((SwTabFrm*)pFrm)->RegistFlys(); 1413 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout 1414 // for setting position at newly inserted frame 1415 lcl_SetPos( *pFrm, *pLay ); 1416 1417 pPrv = pFrm; 1418 //Index auf den Endnode der Tabellensection setzen. 1419 nIndex = pTblNode->EndOfSectionIndex(); 1420 1421 SwTabFrm* pTmpFrm = (SwTabFrm*)pFrm; 1422 while ( pTmpFrm ) 1423 { 1424 pTmpFrm->CheckDirChange(); 1425 pTmpFrm = pTmpFrm->IsFollow() ? pTmpFrm->FindMaster() : NULL; 1426 } 1427 1428 } 1429 else if ( pNd->IsSectionNode() ) 1430 { 1431 SwSectionNode *pNode = (SwSectionNode*)pNd; 1432 if( pNode->GetSection().CalcHiddenFlag() ) 1433 // ist versteckt, ueberspringe den Bereich 1434 nIndex = pNode->EndOfSectionIndex(); 1435 else 1436 { 1437 pFrm = pNode->MakeFrm( pLay ); 1438 pActualSection = new SwActualSection( pActualSection, 1439 (SwSectionFrm*)pFrm, pNode ); 1440 if ( pActualSection->GetUpper() ) 1441 { 1442 //Hinter den Upper einsetzen, beim EndNode wird der "Follow" 1443 //des Uppers erzeugt. 1444 SwSectionFrm *pTmp = pActualSection->GetUpper()->GetSectionFrm(); 1445 pFrm->InsertBehind( pTmp->GetUpper(), pTmp ); 1446 // OD 25.03.2003 #108339# - direct initialization of section 1447 // after insertion in the layout 1448 static_cast<SwSectionFrm*>(pFrm)->Init(); 1449 } 1450 else 1451 { 1452 pFrm->InsertBehind( pLay, pPrv ); 1453 // OD 25.03.2003 #108339# - direct initialization of section 1454 // after insertion in the layout 1455 static_cast<SwSectionFrm*>(pFrm)->Init(); 1456 1457 // --> FME 2004-09-08 #i33963# 1458 // Do not trust the IsInFtn flag. If we are currently 1459 // building up a table, the upper of pPrv may be a cell 1460 // frame, but the cell frame does not have an upper yet. 1461 if( pPrv && 0 != pPrv->ImplFindFtnFrm() ) 1462 // <-- 1463 { 1464 if( pPrv->IsSctFrm() ) 1465 pPrv = ((SwSectionFrm*)pPrv)->ContainsCntnt(); 1466 if( pPrv && pPrv->IsTxtFrm() ) 1467 ((SwTxtFrm*)pPrv)->Prepare( PREP_QUOVADIS, 0, sal_False ); 1468 } 1469 } 1470 // --> OD 2005-12-01 #i27138# 1471 // notify accessibility paragraphs objects about changed 1472 // CONTENT_FLOWS_FROM/_TO relation. 1473 // Relation CONTENT_FLOWS_FROM for next paragraph will change 1474 // and relation CONTENT_FLOWS_TO for previous paragraph will change. 1475 { 1476 ViewShell* pViewShell( pFrm->getRootFrm()->GetCurrShell() ); 1477 // no notification, if <ViewShell> is in construction 1478 if ( pViewShell && !pViewShell->IsInConstructor() && 1479 pViewShell->GetLayout() && 1480 pViewShell->GetLayout()->IsAnyShellAccessible() ) 1481 { 1482 pViewShell->InvalidateAccessibleParaFlowRelation( 1483 dynamic_cast<SwTxtFrm*>(pFrm->FindNextCnt( true )), 1484 dynamic_cast<SwTxtFrm*>(pFrm->FindPrevCnt( true )) ); 1485 } 1486 } 1487 // <-- 1488 pFrm->CheckDirChange(); 1489 1490 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout 1491 // for setting position at newly inserted frame 1492 lcl_SetPos( *pFrm, *pLay ); 1493 1494 // OD 20.11.2002 #105405# - no page, no invalidate. 1495 if ( pPage ) 1496 { 1497 // OD 18.09.2002 #100522# 1498 // invalidate page in order to force format and paint of 1499 // inserted section frame 1500 pFrm->InvalidatePage( pPage ); 1501 1502 // FME 10.11.2003 #112243# 1503 // Invalidate fly content flag: 1504 if ( pFrm->IsInFly() ) 1505 pPage->InvalidateFlyCntnt(); 1506 1507 // OD 14.11.2002 #104684# - invalidate page content in order to 1508 // force format and paint of section content. 1509 pPage->InvalidateCntnt(); 1510 } 1511 1512 pLay = (SwLayoutFrm*)pFrm; 1513 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() ) 1514 pLay = pLay->GetNextLayoutLeaf(); 1515 pPrv = 0; 1516 } 1517 } 1518 else if ( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() ) 1519 { 1520 ASSERT( pActualSection, "Sectionende ohne Anfang?" ); 1521 ASSERT( pActualSection->GetSectionNode() == pNd->StartOfSectionNode(), 1522 "Sectionende mit falschen Start Node?" ); 1523 1524 //Section schliessen, ggf. die umgebende Section wieder 1525 //aktivieren. 1526 SwActualSection *pTmp = pActualSection->GetUpper(); 1527 delete pActualSection; 1528 pLay = pLay->FindSctFrm(); 1529 if ( 0 != (pActualSection = pTmp) ) 1530 { 1531 //Koennte noch sein, das der letzte SectionFrm leer geblieben 1532 //ist. Dann ist es jetzt an der Zeit ihn zu entfernen. 1533 if ( !pLay->ContainsCntnt() ) 1534 { 1535 SwFrm *pTmpFrm = pLay; 1536 pLay = pTmpFrm->GetUpper(); 1537 pPrv = pTmpFrm->GetPrev(); 1538 pTmpFrm->Remove(); 1539 delete pTmpFrm; 1540 } 1541 else 1542 { 1543 pPrv = pLay; 1544 pLay = pLay->GetUpper(); 1545 } 1546 1547 // new section frame 1548 pFrm = pActualSection->GetSectionNode()->MakeFrm( pLay ); 1549 pFrm->InsertBehind( pLay, pPrv ); 1550 static_cast<SwSectionFrm*>(pFrm)->Init(); 1551 1552 // OD 12.08.2003 #i17969# - consider horizontal/vertical layout 1553 // for setting position at newly inserted frame 1554 lcl_SetPos( *pFrm, *pLay ); 1555 1556 SwSectionFrm* pOuterSectionFrm = pActualSection->GetSectionFrm(); 1557 1558 // a follow has to be appended to the new section frame 1559 SwSectionFrm* pFollow = pOuterSectionFrm->GetFollow(); 1560 if ( pFollow ) 1561 { 1562 pOuterSectionFrm->SetFollow( NULL ); 1563 pOuterSectionFrm->InvalidateSize(); 1564 ((SwSectionFrm*)pFrm)->SetFollow( pFollow ); 1565 } 1566 1567 // Wir wollen keine leeren Teile zuruecklassen 1568 if( ! pOuterSectionFrm->IsColLocked() && 1569 ! pOuterSectionFrm->ContainsCntnt() ) 1570 { 1571 pOuterSectionFrm->DelEmpty( sal_True ); 1572 delete pOuterSectionFrm; 1573 } 1574 pActualSection->SetSectionFrm( (SwSectionFrm*)pFrm ); 1575 1576 pLay = (SwLayoutFrm*)pFrm; 1577 if ( pLay->Lower() && pLay->Lower()->IsLayoutFrm() ) 1578 pLay = pLay->GetNextLayoutLeaf(); 1579 pPrv = 0; 1580 } 1581 else 1582 { 1583 //Nix mehr mit Sections, es geht direkt hinter dem SectionFrame 1584 //weiter. 1585 pPrv = pLay; 1586 pLay = pLay->GetUpper(); 1587 } 1588 } 1589 else if( pNd->IsStartNode() && 1590 SwFlyStartNode == ((SwStartNode*)pNd)->GetStartNodeType() ) 1591 { 1592 if ( pTbl->Count() && bObjsDirect && !bDontCreateObjects ) 1593 { 1594 SwFlyFrm* pFly = pLay->FindFlyFrm(); 1595 if( pFly ) 1596 AppendObjs( pTbl, nIndex, pFly, pPage ); 1597 } 1598 } 1599 else 1600 // Weder Cntnt noch Tabelle noch Section, 1601 // also muessen wir fertig sein. 1602 break; 1603 1604 ++nIndex; 1605 // Der Endnode wird nicht mehr mitgenommen, es muss vom 1606 // Aufrufenden (Section/MakeFrms()) sichergestellt sein, dass das Ende 1607 // des Bereichs vor dem EndIndex liegt! 1608 if ( nEndIndex && nIndex >= nEndIndex ) 1609 break; 1610 } 1611 1612 if ( pActualSection ) 1613 { 1614 //Kann passieren, dass noch eine leere (Follow-)Section uebrig geblieben ist. 1615 if ( !(pLay = pActualSection->GetSectionFrm())->ContainsCntnt() ) 1616 { 1617 pLay->Remove(); 1618 delete pLay; 1619 } 1620 delete pActualSection; 1621 } 1622 1623 if ( bPages ) //Jetzt noch die Flys verbinden lassen. 1624 { 1625 if ( !bDontCreateObjects ) 1626 AppendAllObjs( pTbl, pLayout ); 1627 bObjsDirect = sal_True; 1628 } 1629 1630 if( pPageMaker ) 1631 { 1632 pPageMaker->CheckFlyCache( pPage ); 1633 delete pPageMaker; 1634 if( pDoc->GetLayoutCache() ) 1635 { 1636 #ifdef DBG_UTIL 1637 #if OSL_DEBUG_LEVEL > 1 1638 pDoc->GetLayoutCache()->CompareLayout( *pDoc ); 1639 #endif 1640 #endif 1641 pDoc->GetLayoutCache()->ClearImpl(); 1642 } 1643 } 1644 1645 pDoc->UnblockIdling(); 1646 if( bOldCallbackActionEnabled ) 1647 pLayout->SetCallbackActionEnabled( bOldCallbackActionEnabled ); 1648 } 1649 1650 1651 void MakeFrms( SwDoc *pDoc, const SwNodeIndex &rSttIdx, 1652 const SwNodeIndex &rEndIdx ) 1653 { 1654 bObjsDirect = sal_False; 1655 1656 SwNodeIndex aTmp( rSttIdx ); 1657 sal_uLong nEndIdx = rEndIdx.GetIndex(); 1658 SwNode* pNd = pDoc->GetNodes().FindPrvNxtFrmNode( aTmp, 1659 pDoc->GetNodes()[ nEndIdx-1 ]); 1660 if ( pNd ) 1661 { 1662 sal_Bool bApres = aTmp < rSttIdx; 1663 SwNode2Layout aNode2Layout( *pNd, rSttIdx.GetIndex() ); 1664 SwFrm* pFrm; 1665 while( 0 != (pFrm = aNode2Layout.NextFrm()) ) 1666 { 1667 SwLayoutFrm *pUpper = pFrm->GetUpper(); 1668 SwFtnFrm* pFtnFrm = pUpper->FindFtnFrm(); 1669 sal_Bool bOldLock, bOldFtn; 1670 if( pFtnFrm ) 1671 { 1672 bOldFtn = pFtnFrm->IsColLocked(); 1673 pFtnFrm->ColLock(); 1674 } 1675 else 1676 bOldFtn = sal_True; 1677 SwSectionFrm* pSct = pUpper->FindSctFrm(); 1678 // Es sind innerhalb von Fussnoten nur die Bereiche interessant, 1679 // die in den Fussnoten liegen, nicht etwa die (spaltigen) Bereiche, 1680 // in denen die Fussnoten(Container) liegen. 1681 // #109767# Table frame is in section, insert section in cell frame. 1682 if( pSct && ((pFtnFrm && !pSct->IsInFtn()) || pUpper->IsCellFrm()) ) 1683 pSct = NULL; 1684 if( pSct ) 1685 { // damit der SectionFrm nicht zerstoert wird durch pTmp->MoveFwd() 1686 bOldLock = pSct->IsColLocked(); 1687 pSct->ColLock(); 1688 } 1689 else 1690 bOldLock = sal_True; 1691 1692 // Wenn pFrm sich nicht bewegen kann, koennen wir auch niemanden 1693 // auf die naechste Seite schieben. Innerhalb eines Rahmens auch 1694 // nicht ( in der 1. Spalte eines Rahmens waere pFrm Moveable()! ) 1695 // Auch in spaltigen Bereichen in Tabellen waere pFrm Moveable. 1696 sal_Bool bMoveNext = nEndIdx - rSttIdx.GetIndex() > 120; 1697 sal_Bool bAllowMove = !pFrm->IsInFly() && pFrm->IsMoveable() && 1698 (!pFrm->IsInTab() || pFrm->IsTabFrm() ); 1699 if ( bMoveNext && bAllowMove ) 1700 { 1701 SwFrm *pMove = pFrm; 1702 SwFrm *pPrev = pFrm->GetPrev(); 1703 SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pMove ); 1704 ASSERT( pTmp, "Missing FlowFrm" ); 1705 1706 if ( bApres ) 1707 { 1708 // Wir wollen, dass der Rest der Seite leer ist, d.h. 1709 // der naechste muss auf die naechste Seite wandern. 1710 // Dieser kann auch in der naechsten Spalte stehen! 1711 ASSERT( !pTmp->HasFollow(), "Follows forbidden" ); 1712 pPrev = pFrm; 1713 // Wenn unser umgebender SectionFrm einen Next besitzt, 1714 // so soll dieser ebenfalls gemoved werden! 1715 pMove = pFrm->GetIndNext(); 1716 SwColumnFrm* pCol = (SwColumnFrm*)pFrm->FindColFrm(); 1717 if( pCol ) 1718 pCol = (SwColumnFrm*)pCol->GetNext(); 1719 do 1720 { 1721 if( pCol && !pMove ) 1722 { // Bisher haben wir keinen Nachfolger gefunden 1723 // jetzt gucken wir in die naechste Spalte 1724 pMove = pCol->ContainsAny(); 1725 if( pCol->GetNext() ) 1726 pCol = (SwColumnFrm*)pCol->GetNext(); 1727 else if( pCol->IsInSct() ) 1728 { // Wenn es keine naechste Spalte gibt, wir aber 1729 // innerhalb eines spaltigen Bereichs sind, 1730 // koennte es noch ausserhalb des Bereich 1731 // (Seiten-)Spalten geben 1732 pCol = (SwColumnFrm*)pCol->FindSctFrm()->FindColFrm(); 1733 if( pCol ) 1734 pCol = (SwColumnFrm*)pCol->GetNext(); 1735 } 1736 else 1737 pCol = NULL; 1738 } 1739 // Falls hier verschrottete SectionFrms herumgammeln, 1740 // muessen diese uebersprungen werden. 1741 while( pMove && pMove->IsSctFrm() && 1742 !((SwSectionFrm*)pMove)->GetSection() ) 1743 pMove = pMove->GetNext(); 1744 } while( !pMove && pCol ); 1745 1746 if( pMove ) 1747 { 1748 if ( pMove->IsCntntFrm() ) 1749 pTmp = (SwCntntFrm*)pMove; 1750 else if ( pMove->IsTabFrm() ) 1751 pTmp = (SwTabFrm*)pMove; 1752 else if ( pMove->IsSctFrm() ) 1753 { 1754 pMove = ((SwSectionFrm*)pMove)->ContainsAny(); 1755 if( pMove ) 1756 pTmp = SwFlowFrm::CastFlowFrm( pMove ); 1757 else 1758 pTmp = NULL; 1759 } 1760 } 1761 else 1762 pTmp = 0; 1763 } 1764 else 1765 { 1766 ASSERT( !pTmp->IsFollow(), "Follows really forbidden" ); 1767 // Bei Bereichen muss natuerlich der Inhalt auf die Reise 1768 // geschickt werden. 1769 if( pMove->IsSctFrm() ) 1770 { 1771 while( pMove && pMove->IsSctFrm() && 1772 !((SwSectionFrm*)pMove)->GetSection() ) 1773 pMove = pMove->GetNext(); 1774 if( pMove && pMove->IsSctFrm() ) 1775 pMove = ((SwSectionFrm*)pMove)->ContainsAny(); 1776 if( pMove ) 1777 pTmp = SwFlowFrm::CastFlowFrm( pMove ); 1778 else 1779 pTmp = NULL; 1780 } 1781 } 1782 1783 if( pTmp ) 1784 { 1785 SwFrm* pOldUp = pTmp->GetFrm()->GetUpper(); 1786 // MoveFwd==sal_True bedeutet, dass wir auf der gleichen 1787 // Seite geblieben sind, wir wollen aber die Seite wechseln, 1788 // sofern dies moeglich ist 1789 sal_Bool bTmpOldLock = pTmp->IsJoinLocked(); 1790 pTmp->LockJoin(); 1791 while( pTmp->MoveFwd( sal_True, sal_False, sal_True ) ) 1792 { 1793 if( pOldUp == pTmp->GetFrm()->GetUpper() ) 1794 break; 1795 pOldUp = pTmp->GetFrm()->GetUpper(); 1796 } 1797 if( !bTmpOldLock ) 1798 pTmp->UnlockJoin(); 1799 } 1800 ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), 1801 pFrm->IsInDocBody(), nEndIdx, pPrev ); 1802 } 1803 else 1804 { 1805 sal_Bool bSplit; 1806 SwFrm* pPrv = bApres ? pFrm : pFrm->GetPrev(); 1807 // Wenn in einen SectionFrm ein anderer eingefuegt wird, 1808 // muss dieser aufgebrochen werden 1809 if( pSct && rSttIdx.GetNode().IsSectionNode() ) 1810 { 1811 bSplit = pSct->SplitSect( pFrm, bApres ); 1812 // Wenn pSct nicht aufgespalten werden konnte 1813 if( !bSplit && !bApres ) 1814 { 1815 pUpper = pSct->GetUpper(); 1816 pPrv = pSct->GetPrev(); 1817 } 1818 } 1819 else 1820 bSplit = sal_False; 1821 ::_InsertCnt( pUpper, pDoc, rSttIdx.GetIndex(), sal_False, 1822 nEndIdx, pPrv ); 1823 // OD 23.06.2003 #108784# - correction: append objects doesn't 1824 // depend on value of <bAllowMove> 1825 if( !bDontCreateObjects ) 1826 { 1827 const SwSpzFrmFmts *pTbl = pDoc->GetSpzFrmFmts(); 1828 if( pTbl->Count() ) 1829 AppendAllObjs( pTbl, pUpper ); 1830 } 1831 1832 // Wenn nichts eingefuegt wurde, z.B. ein ausgeblendeter Bereich, 1833 // muss das Splitten rueckgaengig gemacht werden 1834 if( bSplit && pSct && pSct->GetNext() 1835 && pSct->GetNext()->IsSctFrm() ) 1836 pSct->MergeNext( (SwSectionFrm*)pSct->GetNext() ); 1837 if( pFrm->IsInFly() ) 1838 pFrm->FindFlyFrm()->_Invalidate(); 1839 if( pFrm->IsInTab() ) 1840 pFrm->InvalidateSize(); 1841 } 1842 1843 SwPageFrm *pPage = pUpper->FindPageFrm(); 1844 SwFrm::CheckPageDescs( pPage, sal_False ); 1845 if( !bOldFtn ) 1846 pFtnFrm->ColUnlock(); 1847 if( !bOldLock ) 1848 { 1849 pSct->ColUnlock(); 1850 // Zum Beispiel beim Einfuegen von gelinkten Bereichen, 1851 // die wiederum Bereiche enthalten, kann pSct jetzt leer sein 1852 // und damit ruhig zerstoert werden. 1853 if( !pSct->ContainsCntnt() ) 1854 { 1855 pSct->DelEmpty( sal_True ); 1856 pUpper->getRootFrm()->RemoveFromList( pSct ); 1857 delete pSct; 1858 } 1859 } 1860 } 1861 } 1862 1863 bObjsDirect = sal_True; 1864 } 1865 1866 1867 /*************************************************************************/ 1868 1869 SwBorderAttrs::SwBorderAttrs( const SwModify *pMod, const SwFrm *pConstructor ) : 1870 SwCacheObj( pMod ), 1871 rAttrSet( pConstructor->IsCntntFrm() 1872 ? ((SwCntntFrm*)pConstructor)->GetNode()->GetSwAttrSet() 1873 : ((SwLayoutFrm*)pConstructor)->GetFmt()->GetAttrSet() ), 1874 rUL ( rAttrSet.GetULSpace() ), 1875 // --> OD 2008-12-04 #i96772# 1876 // LRSpaceItem is copied due to the possibility that it is adjusted - see below 1877 rLR ( rAttrSet.GetLRSpace() ), 1878 // <-- 1879 rBox ( rAttrSet.GetBox() ), 1880 rShadow ( rAttrSet.GetShadow() ), 1881 aFrmSize( rAttrSet.GetFrmSize().GetSize() ) 1882 { 1883 // --> OD 2008-12-02 #i96772# 1884 const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(pConstructor); 1885 if ( pTxtFrm ) 1886 { 1887 pTxtFrm->GetTxtNode()->ClearLRSpaceItemDueToListLevelIndents( rLR ); 1888 } 1889 1890 //Achtung: Die USHORTs fuer die gecache'ten Werte werden absichtlich 1891 //nicht initialisiert! 1892 1893 //Muessen alle einmal berechnet werden: 1894 bTopLine = bBottomLine = bLeftLine = bRightLine = 1895 bTop = bBottom = bLine = sal_True; 1896 1897 bCacheGetLine = bCachedGetTopLine = bCachedGetBottomLine = sal_False; 1898 // OD 21.05.2003 #108789# - init cache status for values <bJoinedWithPrev> 1899 // and <bJoinedWithNext>, which aren't initialized by default. 1900 bCachedJoinedWithPrev = sal_False; 1901 bCachedJoinedWithNext = sal_False; 1902 1903 bBorderDist = 0 != (pConstructor->GetType() & (FRM_CELL)); 1904 } 1905 1906 SwBorderAttrs::~SwBorderAttrs() 1907 { 1908 ((SwModify*)pOwner)->SetInCache( sal_False ); 1909 } 1910 1911 /************************************************************************* 1912 |* 1913 |* SwBorderAttrs::CalcTop(), CalcBottom(), CalcLeft(), CalcRight() 1914 |* 1915 |* Beschreibung Die Calc-Methoden errechnen zusaetzlich zu den 1916 |* von den Attributen vorgegebenen Groessen einen Sicherheitsabstand. 1917 |* der Sicherheitsabstand wird nur einkalkuliert, wenn Umrandung und/oder 1918 |* Schatten im Spiel sind; er soll vermeiden, dass aufgrund der 1919 |* groben physikalischen Gegebenheiten Raender usw. uebermalt werden. 1920 |* 1921 |*************************************************************************/ 1922 1923 void SwBorderAttrs::_CalcTop() 1924 { 1925 nTop = CalcTopLine() + rUL.GetUpper(); 1926 bTop = sal_False; 1927 } 1928 1929 void SwBorderAttrs::_CalcBottom() 1930 { 1931 nBottom = CalcBottomLine() + rUL.GetLower(); 1932 bBottom = sal_False; 1933 } 1934 1935 long SwBorderAttrs::CalcRight( const SwFrm* pCaller ) const 1936 { 1937 long nRight; 1938 1939 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left 1940 // and right border are painted on the right respectively left. 1941 if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() ) 1942 nRight = CalcLeftLine(); 1943 else 1944 nRight = CalcRightLine(); 1945 1946 // for paragraphs, "left" is "before text" and "right" is "after text" 1947 if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() ) 1948 nRight += rLR.GetLeft(); 1949 else 1950 nRight += rLR.GetRight(); 1951 1952 // --> OD 2008-01-21 #newlistlevelattrs# 1953 // correction: retrieve left margin for numbering in R2L-layout 1954 if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() ) 1955 { 1956 nRight += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum(); 1957 } 1958 // <-- 1959 1960 return nRight; 1961 } 1962 1963 long SwBorderAttrs::CalcLeft( const SwFrm *pCaller ) const 1964 { 1965 long nLeft; 1966 1967 // OD 23.01.2003 #106895# - for cell frame in R2L text direction the left 1968 // and right border are painted on the right respectively left. 1969 if ( pCaller->IsCellFrm() && pCaller->IsRightToLeft() ) 1970 nLeft = CalcRightLine(); 1971 else 1972 nLeft = CalcLeftLine(); 1973 1974 // for paragraphs, "left" is "before text" and "right" is "after text" 1975 if ( pCaller->IsTxtFrm() && pCaller->IsRightToLeft() ) 1976 nLeft += rLR.GetRight(); 1977 else 1978 nLeft += rLR.GetLeft(); 1979 1980 // --> OD 2008-01-21 #newlistlevelattrs# 1981 // correction: do not retrieve left margin for numbering in R2L-layout 1982 // if ( pCaller->IsTxtFrm() ) 1983 if ( pCaller->IsTxtFrm() && !pCaller->IsRightToLeft() ) 1984 // <-- 1985 { 1986 nLeft += ((SwTxtFrm*)pCaller)->GetTxtNode()->GetLeftMarginWithNum(); 1987 } 1988 1989 return nLeft; 1990 } 1991 1992 /************************************************************************* 1993 |* 1994 |* SwBorderAttrs::CalcTopLine(), CalcBottomLine(), 1995 |* CalcLeftLine(), CalcRightLine() 1996 |* 1997 |* Beschreibung Berechnung der Groessen fuer Umrandung und Schatten. 1998 |* Es kann auch ohne Linien ein Abstand erwuenscht sein, 1999 |* dieser wird dann nicht vom Attribut sondern hier 2000 |* beruecksichtigt (bBorderDist, z.B. fuer Zellen). 2001 |* 2002 |*************************************************************************/ 2003 2004 void SwBorderAttrs::_CalcTopLine() 2005 { 2006 nTopLine = (bBorderDist && !rBox.GetTop()) 2007 ? rBox.GetDistance (BOX_LINE_TOP) 2008 : rBox.CalcLineSpace(BOX_LINE_TOP); 2009 nTopLine = nTopLine + rShadow.CalcShadowSpace(SHADOW_TOP); 2010 bTopLine = sal_False; 2011 } 2012 2013 void SwBorderAttrs::_CalcBottomLine() 2014 { 2015 nBottomLine = (bBorderDist && !rBox.GetBottom()) 2016 ? rBox.GetDistance (BOX_LINE_BOTTOM) 2017 : rBox.CalcLineSpace(BOX_LINE_BOTTOM); 2018 nBottomLine = nBottomLine + rShadow.CalcShadowSpace(SHADOW_BOTTOM); 2019 bBottomLine = sal_False; 2020 } 2021 2022 void SwBorderAttrs::_CalcLeftLine() 2023 { 2024 nLeftLine = (bBorderDist && !rBox.GetLeft()) 2025 ? rBox.GetDistance (BOX_LINE_LEFT) 2026 : rBox.CalcLineSpace(BOX_LINE_LEFT); 2027 nLeftLine = nLeftLine + rShadow.CalcShadowSpace(SHADOW_LEFT); 2028 bLeftLine = sal_False; 2029 } 2030 2031 void SwBorderAttrs::_CalcRightLine() 2032 { 2033 nRightLine = (bBorderDist && !rBox.GetRight()) 2034 ? rBox.GetDistance (BOX_LINE_RIGHT) 2035 : rBox.CalcLineSpace(BOX_LINE_RIGHT); 2036 nRightLine = nRightLine + rShadow.CalcShadowSpace(SHADOW_RIGHT); 2037 bRightLine = sal_False; 2038 } 2039 2040 /*************************************************************************/ 2041 2042 void SwBorderAttrs::_IsLine() 2043 { 2044 bIsLine = rBox.GetTop() || rBox.GetBottom() || 2045 rBox.GetLeft()|| rBox.GetRight(); 2046 bLine = sal_False; 2047 } 2048 2049 /************************************************************************* 2050 |* 2051 |* SwBorderAttrs::CmpLeftRightLine(), IsTopLine(), IsBottomLine() 2052 |* 2053 |* Die Umrandungen benachbarter Absaetze werden nach folgendem 2054 |* Algorithmus zusammengefasst: 2055 |* 2056 |* 1. Die Umrandung oben faellt weg, wenn der Vorgaenger dieselbe 2057 |* Umrandung oben aufweist und 3. Zutrifft. 2058 |* Zusaetzlich muss der Absatz mindestens rechts oder links oder 2059 |* unten eine Umrandung haben. 2060 |* 2. Die Umrandung unten faellt weg, wenn der Nachfolger dieselbe 2061 |* Umrandung untern aufweist und 3. Zustrifft. 2062 |* Zusaetzlich muss der Absatz mindestens rechts oder links oder 2063 |* oben eine Umrandung haben. 2064 |* 3. Die Umrandungen links und rechts vor Vorgaenger bzw. Nachfolger 2065 |* sind identisch. 2066 |* 2067 |*************************************************************************/ 2068 inline int CmpLines( const SvxBorderLine *pL1, const SvxBorderLine *pL2 ) 2069 { 2070 return ( ((pL1 && pL2) && (*pL1 == *pL2)) || (!pL1 && !pL2) ); 2071 } 2072 2073 // OD 21.05.2003 #108789# - change name of 1st parameter - "rAttrs" -> "rCmpAttrs" 2074 // OD 21.05.2003 #108789# - compare <CalcRight()> and <rCmpAttrs.CalcRight()> 2075 // instead of only the right LR-spacing, because R2L-layout has to be 2076 // considered. 2077 sal_Bool SwBorderAttrs::CmpLeftRight( const SwBorderAttrs &rCmpAttrs, 2078 const SwFrm *pCaller, 2079 const SwFrm *pCmp ) const 2080 { 2081 return ( CmpLines( rCmpAttrs.GetBox().GetLeft(), GetBox().GetLeft() ) && 2082 CmpLines( rCmpAttrs.GetBox().GetRight(),GetBox().GetRight() ) && 2083 CalcLeft( pCaller ) == rCmpAttrs.CalcLeft( pCmp ) && 2084 // OD 21.05.2003 #108789# - compare <CalcRight> with <rCmpAttrs.CalcRight>. 2085 CalcRight( pCaller ) == rCmpAttrs.CalcRight( pCmp ) ); 2086 } 2087 2088 sal_Bool SwBorderAttrs::_JoinWithCmp( const SwFrm& _rCallerFrm, 2089 const SwFrm& _rCmpFrm ) const 2090 { 2091 sal_Bool bReturnVal = sal_False; 2092 2093 SwBorderAttrAccess aCmpAccess( SwFrm::GetCache(), &_rCmpFrm ); 2094 const SwBorderAttrs &rCmpAttrs = *aCmpAccess.Get(); 2095 if ( rShadow == rCmpAttrs.GetShadow() && 2096 CmpLines( rBox.GetTop(), rCmpAttrs.GetBox().GetTop() ) && 2097 CmpLines( rBox.GetBottom(), rCmpAttrs.GetBox().GetBottom() ) && 2098 CmpLeftRight( rCmpAttrs, &_rCallerFrm, &_rCmpFrm ) 2099 ) 2100 { 2101 bReturnVal = sal_True; 2102 } 2103 2104 return bReturnVal; 2105 } 2106 2107 // OD 21.05.2003 #108789# - method to determine, if borders are joined with 2108 // previous frame. Calculated value saved in cached value <bJoinedWithPrev> 2109 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm> 2110 void SwBorderAttrs::_CalcJoinedWithPrev( const SwFrm& _rFrm, 2111 const SwFrm* _pPrevFrm ) 2112 { 2113 // set default 2114 bJoinedWithPrev = sal_False; 2115 2116 if ( _rFrm.IsTxtFrm() ) 2117 { 2118 // text frame can potentially join with previous text frame, if 2119 // corresponding attribute set is set at previous text frame. 2120 // OD 2004-02-26 #i25029# - If parameter <_pPrevFrm> is set, take this 2121 // one as previous frame. 2122 const SwFrm* pPrevFrm = _pPrevFrm ? _pPrevFrm : _rFrm.GetPrev(); 2123 // OD 2004-02-13 #i25029# - skip hidden text frames. 2124 while ( pPrevFrm && pPrevFrm->IsTxtFrm() && 2125 static_cast<const SwTxtFrm*>(pPrevFrm)->IsHiddenNow() ) 2126 { 2127 pPrevFrm = pPrevFrm->GetPrev(); 2128 } 2129 if ( pPrevFrm && pPrevFrm->IsTxtFrm() && 2130 pPrevFrm->GetAttrSet()->GetParaConnectBorder().GetValue() 2131 ) 2132 { 2133 bJoinedWithPrev = _JoinWithCmp( _rFrm, *(pPrevFrm) ); 2134 } 2135 } 2136 2137 // valid cache status, if demanded 2138 // OD 2004-02-26 #i25029# - Do not validate cache, if parameter <_pPrevFrm> 2139 // is set. 2140 bCachedJoinedWithPrev = bCacheGetLine && !_pPrevFrm; 2141 } 2142 2143 // OD 21.05.2003 #108789# - method to determine, if borders are joined with 2144 // next frame. Calculated value saved in cached value <bJoinedWithNext> 2145 void SwBorderAttrs::_CalcJoinedWithNext( const SwFrm& _rFrm ) 2146 { 2147 // set default 2148 bJoinedWithNext = sal_False; 2149 2150 if ( _rFrm.IsTxtFrm() ) 2151 { 2152 // text frame can potentially join with next text frame, if 2153 // corresponding attribute set is set at current text frame. 2154 // OD 2004-02-13 #i25029# - get next frame, but skip hidden text frames. 2155 const SwFrm* pNextFrm = _rFrm.GetNext(); 2156 while ( pNextFrm && pNextFrm->IsTxtFrm() && 2157 static_cast<const SwTxtFrm*>(pNextFrm)->IsHiddenNow() ) 2158 { 2159 pNextFrm = pNextFrm->GetNext(); 2160 } 2161 if ( pNextFrm && pNextFrm->IsTxtFrm() && 2162 _rFrm.GetAttrSet()->GetParaConnectBorder().GetValue() 2163 ) 2164 { 2165 bJoinedWithNext = _JoinWithCmp( _rFrm, *(pNextFrm) ); 2166 } 2167 } 2168 2169 // valid cache status, if demanded 2170 bCachedJoinedWithNext = bCacheGetLine; 2171 } 2172 2173 // OD 21.05.2003 #108789# - accessor for cached values <bJoinedWithPrev> 2174 // OD 2004-02-26 #i25029# - add 2nd parameter <_pPrevFrm>, which is passed to 2175 // method <_CalcJoindWithPrev(..)>. 2176 sal_Bool SwBorderAttrs::JoinedWithPrev( const SwFrm& _rFrm, 2177 const SwFrm* _pPrevFrm ) const 2178 { 2179 if ( !bCachedJoinedWithPrev || _pPrevFrm ) 2180 { 2181 // OD 2004-02-26 #i25029# - pass <_pPrevFrm> as 2nd parameter 2182 const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithPrev( _rFrm, _pPrevFrm ); 2183 } 2184 2185 return bJoinedWithPrev; 2186 } 2187 2188 sal_Bool SwBorderAttrs::JoinedWithNext( const SwFrm& _rFrm ) const 2189 { 2190 if ( !bCachedJoinedWithNext ) 2191 { 2192 const_cast<SwBorderAttrs*>(this)->_CalcJoinedWithNext( _rFrm ); 2193 } 2194 2195 return bJoinedWithNext; 2196 } 2197 2198 // OD 2004-02-26 #i25029# - added 2nd parameter <_pPrevFrm>, which is passed to 2199 // method <JoinedWithPrev> 2200 void SwBorderAttrs::_GetTopLine( const SwFrm& _rFrm, 2201 const SwFrm* _pPrevFrm ) 2202 { 2203 sal_uInt16 nRet = CalcTopLine(); 2204 2205 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()> 2206 // OD 2004-02-26 #i25029# - add 2nd parameter 2207 if ( JoinedWithPrev( _rFrm, _pPrevFrm ) ) 2208 { 2209 nRet = 0; 2210 } 2211 2212 bCachedGetTopLine = bCacheGetLine; 2213 2214 nGetTopLine = nRet; 2215 } 2216 2217 void SwBorderAttrs::_GetBottomLine( const SwFrm& _rFrm ) 2218 { 2219 sal_uInt16 nRet = CalcBottomLine(); 2220 2221 // OD 21.05.2003 #108789# - use new method <JoinWithPrev()> 2222 if ( JoinedWithNext( _rFrm ) ) 2223 { 2224 nRet = 0; 2225 } 2226 2227 bCachedGetBottomLine = bCacheGetLine; 2228 2229 nGetBottomLine = nRet; 2230 } 2231 2232 /*************************************************************************/ 2233 2234 SwBorderAttrAccess::SwBorderAttrAccess( SwCache &rCach, const SwFrm *pFrm ) : 2235 SwCacheAccess( rCach, (pFrm->IsCntntFrm() ? 2236 (void*)((SwCntntFrm*)pFrm)->GetNode() : 2237 (void*)((SwLayoutFrm*)pFrm)->GetFmt()), 2238 (sal_Bool)(pFrm->IsCntntFrm() ? 2239 ((SwModify*)((SwCntntFrm*)pFrm)->GetNode())->IsInCache() : 2240 ((SwModify*)((SwLayoutFrm*)pFrm)->GetFmt())->IsInCache()) ), 2241 pConstructor( pFrm ) 2242 { 2243 } 2244 2245 /*************************************************************************/ 2246 2247 SwCacheObj *SwBorderAttrAccess::NewObj() 2248 { 2249 ((SwModify*)pOwner)->SetInCache( sal_True ); 2250 return new SwBorderAttrs( (SwModify*)pOwner, pConstructor ); 2251 } 2252 2253 SwBorderAttrs *SwBorderAttrAccess::Get() 2254 { 2255 return (SwBorderAttrs*)SwCacheAccess::Get(); 2256 } 2257 2258 /*************************************************************************/ 2259 2260 SwOrderIter::SwOrderIter( const SwPageFrm *pPg, sal_Bool bFlys ) : 2261 pPage( pPg ), 2262 pCurrent( 0 ), 2263 bFlysOnly( bFlys ) 2264 { 2265 } 2266 2267 /*************************************************************************/ 2268 2269 const SdrObject *SwOrderIter::Top() 2270 { 2271 pCurrent = 0; 2272 if ( pPage->GetSortedObjs() ) 2273 { 2274 sal_uInt32 nTopOrd = 0; 2275 const SwSortedObjs *pObjs = pPage->GetSortedObjs(); 2276 if ( pObjs->Count() ) 2277 { 2278 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen! 2279 for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i ) 2280 { 2281 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj(); 2282 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) ) 2283 continue; 2284 sal_uInt32 nTmp = pObj->GetOrdNumDirect(); 2285 if ( nTmp >= nTopOrd ) 2286 { 2287 nTopOrd = nTmp; 2288 pCurrent = pObj; 2289 } 2290 } 2291 } 2292 } 2293 return pCurrent; 2294 } 2295 2296 /*************************************************************************/ 2297 2298 const SdrObject *SwOrderIter::Bottom() 2299 { 2300 pCurrent = 0; 2301 if ( pPage->GetSortedObjs() ) 2302 { 2303 sal_uInt32 nBotOrd = USHRT_MAX; 2304 const SwSortedObjs *pObjs = pPage->GetSortedObjs(); 2305 if ( pObjs->Count() ) 2306 { 2307 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen! 2308 for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i ) 2309 { 2310 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj(); 2311 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) ) 2312 continue; 2313 sal_uInt32 nTmp = pObj->GetOrdNumDirect(); 2314 if ( nTmp < nBotOrd ) 2315 { 2316 nBotOrd = nTmp; 2317 pCurrent = pObj; 2318 } 2319 } 2320 } 2321 } 2322 return pCurrent; 2323 } 2324 2325 /*************************************************************************/ 2326 2327 const SdrObject *SwOrderIter::Next() 2328 { 2329 const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0; 2330 pCurrent = 0; 2331 if ( pPage->GetSortedObjs() ) 2332 { 2333 sal_uInt32 nOrd = USHRT_MAX; 2334 const SwSortedObjs *pObjs = pPage->GetSortedObjs(); 2335 if ( pObjs->Count() ) 2336 { 2337 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen! 2338 for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i ) 2339 { 2340 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj(); 2341 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) ) 2342 continue; 2343 sal_uInt32 nTmp = pObj->GetOrdNumDirect(); 2344 if ( nTmp > nCurOrd && nTmp < nOrd ) 2345 { 2346 nOrd = nTmp; 2347 pCurrent = pObj; 2348 } 2349 } 2350 } 2351 } 2352 return pCurrent; 2353 } 2354 2355 /*************************************************************************/ 2356 2357 const SdrObject *SwOrderIter::Prev() 2358 { 2359 const sal_uInt32 nCurOrd = pCurrent ? pCurrent->GetOrdNumDirect() : 0; 2360 pCurrent = 0; 2361 if ( pPage->GetSortedObjs() ) 2362 { 2363 sal_uInt32 nOrd = 0; 2364 const SwSortedObjs *pObjs = pPage->GetSortedObjs(); 2365 if ( pObjs->Count() ) 2366 { 2367 (*pObjs)[0]->GetDrawObj()->GetOrdNum(); //Aktualisieren erzwingen! 2368 for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i ) 2369 { 2370 const SdrObject* pObj = (*pObjs)[i]->GetDrawObj(); 2371 if ( bFlysOnly && !pObj->ISA(SwVirtFlyDrawObj) ) 2372 continue; 2373 sal_uInt32 nTmp = pObj->GetOrdNumDirect(); 2374 if ( nTmp < nCurOrd && nTmp >= nOrd ) 2375 { 2376 nOrd = nTmp; 2377 pCurrent = pObj; 2378 } 2379 } 2380 } 2381 } 2382 return pCurrent; 2383 } 2384 2385 /*************************************************************************/ 2386 2387 //Unterstruktur eines LayoutFrms fuer eine Aktion aufheben und wieder 2388 //restaurieren. 2389 //Neuer Algorithmus: Es ist unuetz jeden Nachbarn einzeln zu betrachten und 2390 //die Pointer sauber zu setzen (Upper, Nachbarn, usw.) 2391 //Es reicht vollkommen jeweils eine Einzelkette zu loesen, und mit dem 2392 //Letzen der Einzelkette nachzuschauen ob noch eine weitere Kette 2393 //angeheangt werden muss. Es brauchen nur die Pointer korrigiert werden, 2394 //die zur Verkettung notwendig sind. So koennen Beipspielsweise die Pointer 2395 //auf die Upper auf den alten Uppern stehenbleiben. Korrigiert werden die 2396 //Pointer dann im RestoreCntnt. Zwischenzeitlich ist sowieso jeder Zugriff 2397 //verboten. 2398 //Unterwegs werden die Flys bei der Seite abgemeldet. 2399 2400 // --> OD 2004-11-29 #115759# - 'remove' also drawing object from page and 2401 // at-fly anchored objects from page 2402 void MA_FASTCALL lcl_RemoveObjsFromPage( SwFrm* _pFrm ) 2403 { 2404 ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_RemoveFlysFromPage." ); 2405 SwSortedObjs &rObjs = *_pFrm->GetDrawObjs(); 2406 for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i ) 2407 { 2408 SwAnchoredObject* pObj = rObjs[i]; 2409 // --> OD 2004-11-29 #115759# - reset member, at which the anchored 2410 // object orients its vertical position 2411 pObj->ClearVertPosOrientFrm(); 2412 // <-- 2413 // --> OD 2005-03-03 #i43913# 2414 pObj->ResetLayoutProcessBools(); 2415 // <-- 2416 // --> OD 2004-11-29 #115759# - remove also lower objects of as-character 2417 // anchored Writer fly frames from page 2418 if ( pObj->ISA(SwFlyFrm) ) 2419 { 2420 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj); 2421 2422 // --> OD 2004-11-29 #115759# - remove also direct lowers of Writer 2423 // fly frame from page 2424 if ( pFlyFrm->GetDrawObjs() ) 2425 { 2426 ::lcl_RemoveObjsFromPage( pFlyFrm ); 2427 } 2428 // <-- 2429 2430 SwCntntFrm* pCnt = pFlyFrm->ContainsCntnt(); 2431 while ( pCnt ) 2432 { 2433 if ( pCnt->GetDrawObjs() ) 2434 ::lcl_RemoveObjsFromPage( pCnt ); 2435 pCnt = pCnt->GetNextCntntFrm(); 2436 } 2437 if ( pFlyFrm->IsFlyFreeFrm() ) 2438 { 2439 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> 2440 pFlyFrm->GetPageFrm()->RemoveFlyFromPage( pFlyFrm ); 2441 } 2442 } 2443 // <-- 2444 // --> OD 2004-11-29 #115759# - remove also drawing objects from page 2445 else if ( pObj->ISA(SwAnchoredDrawObject) ) 2446 { 2447 if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR) 2448 { 2449 pObj->GetPageFrm()->RemoveDrawObjFromPage( 2450 *(static_cast<SwAnchoredDrawObject*>(pObj)) ); 2451 } 2452 } 2453 // <-- 2454 } 2455 } 2456 2457 SwFrm *SaveCntnt( SwLayoutFrm *pLay, SwFrm *pStart ) 2458 { 2459 if( pLay->IsSctFrm() && pLay->Lower() && pLay->Lower()->IsColumnFrm() ) 2460 lcl_RemoveFtns( (SwColumnFrm*)pLay->Lower(), sal_True, sal_True ); 2461 2462 SwFrm *pSav; 2463 if ( 0 == (pSav = pLay->ContainsAny()) ) 2464 return 0; 2465 2466 if( pSav->IsInFtn() && !pLay->IsInFtn() ) 2467 { 2468 do 2469 pSav = pSav->FindNext(); 2470 while( pSav && pSav->IsInFtn() ); 2471 if( !pSav || !pLay->IsAnLower( pSav ) ) 2472 return NULL; 2473 } 2474 2475 // Tables should be saved as a whole, expection: 2476 // The contents of a section or a cell inside a table should be saved 2477 if ( pSav->IsInTab() && !( ( pLay->IsSctFrm() || pLay->IsCellFrm() ) && pLay->IsInTab() ) ) 2478 while ( !pSav->IsTabFrm() ) 2479 pSav = pSav->GetUpper(); 2480 2481 if( pSav->IsInSct() ) 2482 { // Jetzt wird der oberste Bereich gesucht, der innerhalb von pLay ist. 2483 SwFrm* pSect = pLay->FindSctFrm(); 2484 SwFrm *pTmp = pSav; 2485 do 2486 { 2487 pSav = pTmp; 2488 pTmp = pSav->GetUpper() ? pSav->GetUpper()->FindSctFrm() : NULL; 2489 } while ( pTmp != pSect ); 2490 } 2491 2492 SwFrm *pFloat = pSav; 2493 if( !pStart ) 2494 pStart = pSav; 2495 sal_Bool bGo = pStart == pSav; 2496 do 2497 { 2498 if( bGo ) 2499 pFloat->GetUpper()->pLower = 0; //Die Teilkette ausklinken. 2500 2501 //Das Ende der Teilkette suchen, unterwegs die Flys abmelden. 2502 do 2503 { 2504 if( bGo ) 2505 { 2506 if ( pFloat->IsCntntFrm() ) 2507 { 2508 if ( pFloat->GetDrawObjs() ) 2509 ::lcl_RemoveObjsFromPage( (SwCntntFrm*)pFloat ); 2510 } 2511 else if ( pFloat->IsTabFrm() || pFloat->IsSctFrm() ) 2512 { 2513 SwCntntFrm *pCnt = ((SwLayoutFrm*)pFloat)->ContainsCntnt(); 2514 if( pCnt ) 2515 { 2516 do 2517 { if ( pCnt->GetDrawObjs() ) 2518 ::lcl_RemoveObjsFromPage( pCnt ); 2519 pCnt = pCnt->GetNextCntntFrm(); 2520 } while ( pCnt && ((SwLayoutFrm*)pFloat)->IsAnLower( pCnt ) ); 2521 } 2522 } 2523 else { 2524 ASSERT( !pFloat, "Neuer Float-Frame?" ); 2525 } 2526 } 2527 if ( pFloat->GetNext() ) 2528 { 2529 if( bGo ) 2530 pFloat->pUpper = NULL; 2531 pFloat = pFloat->GetNext(); 2532 if( !bGo && pFloat == pStart ) 2533 { 2534 bGo = sal_True; 2535 pFloat->pPrev->pNext = NULL; 2536 pFloat->pPrev = NULL; 2537 } 2538 } 2539 else 2540 break; 2541 2542 } while ( pFloat ); 2543 2544 //Die naechste Teilkette suchen und die Ketten miteinander verbinden. 2545 SwFrm *pTmp = pFloat->FindNext(); 2546 if( bGo ) 2547 pFloat->pUpper = NULL; 2548 2549 if( !pLay->IsInFtn() ) 2550 while( pTmp && pTmp->IsInFtn() ) 2551 pTmp = pTmp->FindNext(); 2552 2553 if ( !pLay->IsAnLower( pTmp ) ) 2554 pTmp = 0; 2555 2556 if ( pTmp && bGo ) 2557 { 2558 pFloat->pNext = pTmp; //Die beiden Ketten verbinden. 2559 pFloat->pNext->pPrev = pFloat; 2560 } 2561 pFloat = pTmp; 2562 bGo = bGo || ( pStart == pFloat ); 2563 } while ( pFloat ); 2564 2565 return bGo ? pStart : NULL; 2566 } 2567 2568 // --> OD 2004-11-29 #115759# - add also drawing objects to page and at-fly 2569 // anchored objects to page 2570 void MA_FASTCALL lcl_AddObjsToPage( SwFrm* _pFrm, SwPageFrm* _pPage ) 2571 { 2572 ASSERT( _pFrm->GetDrawObjs(), "Keine DrawObjs fuer lcl_AddFlysToPage." ); 2573 SwSortedObjs &rObjs = *_pFrm->GetDrawObjs(); 2574 for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i ) 2575 { 2576 SwAnchoredObject* pObj = rObjs[i]; 2577 2578 // --> OD 2004-11-29 #115759# - unlock position of anchored object 2579 // in order to get the object's position calculated. 2580 pObj->UnlockPosition(); 2581 // <-- 2582 // --> OD 2004-11-29 #115759# - add also lower objects of as-character 2583 // anchored Writer fly frames from page 2584 if ( pObj->ISA(SwFlyFrm) ) 2585 { 2586 SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pObj); 2587 if ( pObj->ISA(SwFlyFreeFrm) ) 2588 { 2589 _pPage->AppendFlyToPage( pFlyFrm ); 2590 } 2591 pFlyFrm->_InvalidatePos(); 2592 pFlyFrm->_InvalidateSize(); 2593 pFlyFrm->InvalidatePage( _pPage ); 2594 2595 // --> OD 2004-11-29 #115759# - add also at-fly anchored objects 2596 // to page 2597 if ( pFlyFrm->GetDrawObjs() ) 2598 { 2599 ::lcl_AddObjsToPage( pFlyFrm, _pPage ); 2600 } 2601 // <-- 2602 2603 SwCntntFrm *pCnt = pFlyFrm->ContainsCntnt(); 2604 while ( pCnt ) 2605 { 2606 if ( pCnt->GetDrawObjs() ) 2607 ::lcl_AddObjsToPage( pCnt, _pPage ); 2608 pCnt = pCnt->GetNextCntntFrm(); 2609 } 2610 } 2611 // <-- 2612 // --> OD 2004-11-29 #115759# - remove also drawing objects from page 2613 else if ( pObj->ISA(SwAnchoredDrawObject) ) 2614 { 2615 if (pObj->GetFrmFmt().GetAnchor().GetAnchorId() != FLY_AS_CHAR) 2616 { 2617 pObj->InvalidateObjPos(); 2618 _pPage->AppendDrawObjToPage( 2619 *(static_cast<SwAnchoredDrawObject*>(pObj)) ); 2620 } 2621 } 2622 // <-- 2623 } 2624 } 2625 2626 void RestoreCntnt( SwFrm *pSav, SwLayoutFrm *pParent, SwFrm *pSibling, bool bGrow ) 2627 { 2628 ASSERT( pSav && pParent, "Kein Save oder Parent fuer Restore." ); 2629 SWRECTFN( pParent ) 2630 2631 //Wenn es bereits FlowFrms unterhalb des neuen Parent gibt, so wird die 2632 //Kette, beginnend mit pSav, hinter dem letzten angehaengt. 2633 //Die Teile werden kurzerhand insertet und geeignet invalidiert. 2634 //Unterwegs werden die Flys der CntntFrms bei der Seite angemeldet. 2635 2636 SwPageFrm *pPage = pParent->FindPageFrm(); 2637 2638 if ( pPage ) 2639 pPage->InvalidatePage( pPage ); //Invalides Layout anmelden. 2640 2641 //Vorgaenger festellen und die Verbindung herstellen bzw. initialisieren. 2642 pSav->pPrev = pSibling; 2643 SwFrm* pNxt; 2644 if ( pSibling ) 2645 { 2646 pNxt = pSibling->pNext; 2647 pSibling->pNext = pSav; 2648 pSibling->_InvalidatePrt(); 2649 ((SwCntntFrm*)pSibling)->InvalidatePage( pPage );//Invaliden Cntnt anmelden. 2650 if ( ((SwCntntFrm*)pSibling)->GetFollow() ) 2651 pSibling->Prepare( PREP_CLEAR, 0, sal_False ); 2652 } 2653 else 2654 { pNxt = pParent->pLower; 2655 pParent->pLower = pSav; 2656 pSav->pUpper = pParent; //Schon mal setzen, sonst ist fuer das 2657 //invalidate der Parent (z.B. ein Fly) nicht klar. 2658 //Invaliden Cntnt anmelden. 2659 if ( pSav->IsCntntFrm() ) 2660 ((SwCntntFrm*)pSav)->InvalidatePage( pPage ); 2661 else 2662 { // pSav koennte auch ein leerer SectFrm sein 2663 SwCntntFrm* pCnt = pParent->ContainsCntnt(); 2664 if( pCnt ) 2665 pCnt->InvalidatePage( pPage ); 2666 } 2667 } 2668 2669 //Der Parent muss entsprechend gegrow'ed werden. 2670 SwTwips nGrowVal = 0; 2671 SwFrm* pLast; 2672 do 2673 { pSav->pUpper = pParent; 2674 nGrowVal += (pSav->Frm().*fnRect->fnGetHeight)(); 2675 pSav->_InvalidateAll(); 2676 2677 //Jetzt die Flys anmelden, fuer TxtFrms gleich geeignet invalidieren. 2678 if ( pSav->IsCntntFrm() ) 2679 { 2680 if ( pSav->IsTxtFrm() && 2681 ((SwTxtFrm*)pSav)->GetCacheIdx() != USHRT_MAX ) 2682 ((SwTxtFrm*)pSav)->Init(); //Ich bin sein Freund. 2683 2684 if ( pPage && pSav->GetDrawObjs() ) 2685 ::lcl_AddObjsToPage( (SwCntntFrm*)pSav, pPage ); 2686 } 2687 else 2688 { SwCntntFrm *pBlub = ((SwLayoutFrm*)pSav)->ContainsCntnt(); 2689 if( pBlub ) 2690 { 2691 do 2692 { if ( pPage && pBlub->GetDrawObjs() ) 2693 ::lcl_AddObjsToPage( pBlub, pPage ); 2694 if( pBlub->IsTxtFrm() && ((SwTxtFrm*)pBlub)->HasFtn() && 2695 ((SwTxtFrm*)pBlub)->GetCacheIdx() != USHRT_MAX ) 2696 ((SwTxtFrm*)pBlub)->Init(); //Ich bin sein Freund. 2697 pBlub = pBlub->GetNextCntntFrm(); 2698 } while ( pBlub && ((SwLayoutFrm*)pSav)->IsAnLower( pBlub )); 2699 } 2700 } 2701 pLast = pSav; 2702 pSav = pSav->GetNext(); 2703 2704 } while ( pSav ); 2705 2706 if( pNxt ) 2707 { 2708 pLast->pNext = pNxt; 2709 pNxt->pPrev = pLast; 2710 } 2711 2712 if ( bGrow ) 2713 pParent->Grow( nGrowVal ); 2714 } 2715 2716 /************************************************************************* 2717 |* 2718 |* SqRt() Berechnung der Quadratwurzel, damit die math.lib 2719 |* nicht auch noch dazugelinkt werden muss. 2720 |* 2721 |*************************************************************************/ 2722 2723 sal_uLong MA_FASTCALL SqRt( BigInt nX ) 2724 { 2725 BigInt nErg = 1; 2726 2727 if ( !nX.IsNeg() ) 2728 { 2729 BigInt nOldErg = 1; 2730 for ( int i = 0; i <= 5; i++ ) 2731 { 2732 nErg = (nOldErg + (nX / nOldErg)) / BigInt(2); 2733 nOldErg = nErg; 2734 } 2735 } 2736 return nErg >= BigInt(SAL_MAX_UINT32) ? ULONG_MAX : (sal_uLong)nErg; 2737 } 2738 2739 /*************************************************************************/ 2740 2741 SwPageFrm * MA_FASTCALL InsertNewPage( SwPageDesc &rDesc, SwFrm *pUpper, 2742 sal_Bool bOdd, sal_Bool bInsertEmpty, sal_Bool bFtn, 2743 SwFrm *pSibling ) 2744 { 2745 SwPageFrm *pRet; 2746 SwDoc *pDoc = ((SwLayoutFrm*)pUpper)->GetFmt()->GetDoc(); 2747 SwFrmFmt *pFmt = bOdd ? rDesc.GetRightFmt() : rDesc.GetLeftFmt(); 2748 //Wenn ich kein FrmFmt fuer die Seite gefunden habe, muss ich eben 2749 //eine Leerseite einfuegen. 2750 if ( !pFmt ) 2751 { 2752 pFmt = bOdd ? rDesc.GetLeftFmt() : rDesc.GetRightFmt(); 2753 ASSERT( pFmt, "Descriptor without any format?!" ); 2754 bInsertEmpty = !bInsertEmpty; 2755 } 2756 if( bInsertEmpty ) 2757 { 2758 SwPageDesc *pTmpDesc = pSibling && pSibling->GetPrev() ? 2759 ((SwPageFrm*)pSibling->GetPrev())->GetPageDesc() : &rDesc; 2760 pRet = new SwPageFrm( pDoc->GetEmptyPageFmt(), pUpper, pTmpDesc ); 2761 pRet->Paste( pUpper, pSibling ); 2762 pRet->PreparePage( bFtn ); 2763 } 2764 pRet = new SwPageFrm( pFmt, pUpper, &rDesc ); 2765 pRet->Paste( pUpper, pSibling ); 2766 pRet->PreparePage( bFtn ); 2767 if ( pRet->GetNext() ) 2768 ((SwRootFrm*)pRet->GetUpper())->AssertPageFlys( pRet ); 2769 return pRet; 2770 } 2771 2772 2773 /************************************************************************* 2774 |* 2775 |* RegistFlys(), Regist() Die beiden folgenden Methoden durchsuchen rekursiv 2776 |* eine Layoutstruktur und melden alle FlyFrms, die einen beliebigen Frm 2777 |* innerhalb der Struktur als Anker haben bei der Seite an. 2778 |* 2779 |*************************************************************************/ 2780 2781 void MA_FASTCALL lcl_Regist( SwPageFrm *pPage, const SwFrm *pAnch ) 2782 { 2783 SwSortedObjs *pObjs = (SwSortedObjs*)pAnch->GetDrawObjs(); 2784 for ( sal_uInt16 i = 0; i < pObjs->Count(); ++i ) 2785 { 2786 SwAnchoredObject* pObj = (*pObjs)[i]; 2787 if ( pObj->ISA(SwFlyFrm) ) 2788 { 2789 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj); 2790 //Ggf. ummelden, nicht anmelden wenn bereits bekannt. 2791 // --> OD 2004-06-30 #i28701# - use new method <GetPageFrm()> 2792 SwPageFrm *pPg = pFly->IsFlyFreeFrm() 2793 ? pFly->GetPageFrm() : pFly->FindPageFrm(); 2794 if ( pPg != pPage ) 2795 { 2796 if ( pPg ) 2797 pPg->RemoveFlyFromPage( pFly ); 2798 pPage->AppendFlyToPage( pFly ); 2799 } 2800 ::RegistFlys( pPage, pFly ); 2801 } 2802 else 2803 { 2804 // --> OD 2008-04-22 #i87493# 2805 if ( pPage != pObj->GetPageFrm() ) 2806 { 2807 // --> OD 2004-07-02 #i28701# 2808 if ( pObj->GetPageFrm() ) 2809 pObj->GetPageFrm()->RemoveDrawObjFromPage( *pObj ); 2810 pPage->AppendDrawObjToPage( *pObj ); 2811 // <-- 2812 } 2813 // <-- 2814 } 2815 2816 const SwFlyFrm* pFly = pAnch->FindFlyFrm(); 2817 if ( pFly && 2818 pObj->GetDrawObj()->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() && 2819 pObj->GetDrawObj()->GetPage() ) 2820 { 2821 //#i119945# set pFly's OrdNum to pObj's. So when pFly is removed by Undo, the original OrdNum will not be changed. 2822 pObj->DrawObj()->GetPage()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(), 2823 pObj->GetDrawObj()->GetOrdNumDirect() ); 2824 } 2825 } 2826 } 2827 2828 void RegistFlys( SwPageFrm *pPage, const SwLayoutFrm *pLay ) 2829 { 2830 if ( pLay->GetDrawObjs() ) 2831 ::lcl_Regist( pPage, pLay ); 2832 const SwFrm *pFrm = pLay->Lower(); 2833 while ( pFrm ) 2834 { 2835 if ( pFrm->IsLayoutFrm() ) 2836 ::RegistFlys( pPage, (const SwLayoutFrm*)pFrm ); 2837 else if ( pFrm->GetDrawObjs() ) 2838 ::lcl_Regist( pPage, pFrm ); 2839 pFrm = pFrm->GetNext(); 2840 } 2841 } 2842 2843 /************************************************************************* 2844 |* 2845 |* void Notify() 2846 |* 2847 |* Beschreibung Benachrichtigt den Hintergrund je nach der 2848 |* Veraenderung zwischen altem und neuem Rechteckt. 2849 |* 2850 |*************************************************************************/ 2851 2852 void Notify( SwFlyFrm *pFly, SwPageFrm *pOld, const SwRect &rOld, 2853 const SwRect* pOldPrt ) 2854 { 2855 const SwRect aFrm( pFly->GetObjRectWithSpaces() ); 2856 if ( rOld.Pos() != aFrm.Pos() ) 2857 { //Positionsaenderung, alten und neuen Bereich invalidieren 2858 if ( rOld.HasArea() && 2859 rOld.Left()+pFly->GetFmt()->GetLRSpace().GetLeft() < WEIT_WECH ) 2860 { 2861 pFly->NotifyBackground( pOld, rOld, PREP_FLY_LEAVE ); 2862 } 2863 pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE ); 2864 } 2865 else if ( rOld.SSize() != aFrm.SSize() ) 2866 { //Groessenaenderung, den Bereich der Verlassen wurde bzw. jetzt 2867 //ueberdeckt wird invalidieren. 2868 //Der Einfachheit halber wird hier bewusst jeweils ein Twip 2869 //unnoetig invalidiert. 2870 2871 ViewShell *pSh = pFly->getRootFrm()->GetCurrShell(); 2872 if( pSh && rOld.HasArea() ) 2873 pSh->InvalidateWindows( rOld ); 2874 2875 // --> OD 2005-08-19 #i51941# - consider case that fly frame isn't 2876 // registered at the old page <pOld> 2877 SwPageFrm* pPageFrm = pFly->FindPageFrm(); 2878 if ( pOld != pPageFrm ) 2879 { 2880 pFly->NotifyBackground( pPageFrm, aFrm, PREP_FLY_ARRIVE ); 2881 } 2882 // <-- 2883 2884 if ( rOld.Left() != aFrm.Left() ) 2885 { 2886 SwRect aTmp( rOld ); 2887 aTmp.Union( aFrm ); 2888 aTmp.Left( Min(aFrm.Left(), rOld.Left()) ); 2889 aTmp.Right( Max(aFrm.Left(), rOld.Left()) ); 2890 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD ); 2891 } 2892 SwTwips nOld = rOld.Right(); 2893 SwTwips nNew = aFrm.Right(); 2894 if ( nOld != nNew ) 2895 { 2896 SwRect aTmp( rOld ); 2897 aTmp.Union( aFrm ); 2898 aTmp.Left( Min(nNew, nOld) ); 2899 aTmp.Right( Max(nNew, nOld) ); 2900 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD ); 2901 } 2902 if ( rOld.Top() != aFrm.Top() ) 2903 { 2904 SwRect aTmp( rOld ); 2905 aTmp.Union( aFrm ); 2906 aTmp.Top( Min(aFrm.Top(), rOld.Top()) ); 2907 aTmp.Bottom( Max(aFrm.Top(), rOld.Top()) ); 2908 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD ); 2909 } 2910 nOld = rOld.Bottom(); 2911 nNew = aFrm.Bottom(); 2912 if ( nOld != nNew ) 2913 { 2914 SwRect aTmp( rOld ); 2915 aTmp.Union( aFrm ); 2916 aTmp.Top( Min(nNew, nOld) ); 2917 aTmp.Bottom( Max(nNew, nOld) ); 2918 pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD ); 2919 } 2920 } 2921 else if ( pOldPrt && *pOldPrt != pFly->Prt() && 2922 pFly->GetFmt()->GetSurround().IsContour() ) 2923 { 2924 // #i24097# 2925 pFly->NotifyBackground( pFly->FindPageFrm(), aFrm, PREP_FLY_ARRIVE ); 2926 } 2927 } 2928 2929 /*************************************************************************/ 2930 2931 void lcl_CheckFlowBack( SwFrm* pFrm, const SwRect &rRect ) 2932 { 2933 SwTwips nBottom = rRect.Bottom(); 2934 while( pFrm ) 2935 { 2936 if( pFrm->IsLayoutFrm() ) 2937 { 2938 if( rRect.IsOver( pFrm->Frm() ) ) 2939 lcl_CheckFlowBack( ((SwLayoutFrm*)pFrm)->Lower(), rRect ); 2940 } 2941 else if( !pFrm->GetNext() && nBottom > pFrm->Frm().Bottom() ) 2942 { 2943 if( pFrm->IsCntntFrm() && ((SwCntntFrm*)pFrm)->HasFollow() ) 2944 pFrm->InvalidateSize(); 2945 else 2946 pFrm->InvalidateNextPos(); 2947 } 2948 pFrm = pFrm->GetNext(); 2949 } 2950 } 2951 2952 void MA_FASTCALL lcl_NotifyCntnt( const SdrObject *pThis, SwCntntFrm *pCnt, 2953 const SwRect &rRect, const PrepareHint eHint ) 2954 { 2955 if ( pCnt->IsTxtFrm() ) 2956 { 2957 SwRect aCntPrt( pCnt->Prt() ); 2958 aCntPrt.Pos() += pCnt->Frm().Pos(); 2959 if ( eHint == PREP_FLY_ATTR_CHG ) 2960 { 2961 // --> OD 2004-10-20 #i35640# - use given rectangle <rRect> instead 2962 // of current bound rectangle 2963 if ( aCntPrt.IsOver( rRect ) ) 2964 // <-- 2965 pCnt->Prepare( PREP_FLY_ATTR_CHG ); 2966 } 2967 // --> OD 2004-11-01 #i23129# - only invalidate, if the text frame 2968 // printing area overlaps with the given rectangle. 2969 else if ( aCntPrt.IsOver( rRect ) ) 2970 // <-- 2971 pCnt->Prepare( eHint, (void*)&aCntPrt._Intersection( rRect ) ); 2972 if ( pCnt->GetDrawObjs() ) 2973 { 2974 const SwSortedObjs &rObjs = *pCnt->GetDrawObjs(); 2975 for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i ) 2976 { 2977 SwAnchoredObject* pObj = rObjs[i]; 2978 if ( pObj->ISA(SwFlyFrm) ) 2979 { 2980 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pObj); 2981 if ( pFly->IsFlyInCntFrm() ) 2982 { 2983 SwCntntFrm *pCntnt = pFly->ContainsCntnt(); 2984 while ( pCntnt ) 2985 { 2986 ::lcl_NotifyCntnt( pThis, pCntnt, rRect, eHint ); 2987 pCntnt = pCntnt->GetNextCntntFrm(); 2988 } 2989 } 2990 } 2991 } 2992 } 2993 } 2994 } 2995 2996 void Notify_Background( const SdrObject* pObj, 2997 SwPageFrm* pPage, 2998 const SwRect& rRect, 2999 const PrepareHint eHint, 3000 const sal_Bool bInva ) 3001 { 3002 3003 //Wenn der Frm gerade erstmalig sinnvoll positioniert wurde, braucht der 3004 //alte Bereich nicht benachrichtigt werden. 3005 if ( eHint == PREP_FLY_LEAVE && rRect.Top() == WEIT_WECH ) 3006 return; 3007 3008 SwLayoutFrm* pArea; 3009 SwFlyFrm *pFlyFrm = 0; 3010 SwFrm* pAnchor; 3011 if( pObj->ISA(SwVirtFlyDrawObj) ) 3012 { 3013 pFlyFrm = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm(); 3014 pAnchor = pFlyFrm->AnchorFrm(); 3015 } 3016 else 3017 { 3018 pFlyFrm = NULL; 3019 pAnchor = const_cast<SwFrm*>( 3020 GetUserCall(pObj)->GetAnchoredObj( pObj )->GetAnchorFrm() ); 3021 } 3022 if( PREP_FLY_LEAVE != eHint && pAnchor->IsInFly() ) 3023 pArea = pAnchor->FindFlyFrm(); 3024 else 3025 pArea = pPage; 3026 SwCntntFrm *pCnt = 0; 3027 if ( pArea ) 3028 { 3029 if( PREP_FLY_ARRIVE != eHint ) 3030 lcl_CheckFlowBack( pArea, rRect ); 3031 3032 //Es reagieren sowieso nur die auf den Anker folgenden auf den Fly, also 3033 //brauchen diese nicht abgeklappert werden. 3034 //Ausnahme sind ist natuerlich das LEAVE, denn der Fly koennte ja von 3035 //"oben" kommen. 3036 // Wenn der Anker auf der vorhergehenden Seite liegt, muss ebenfalls 3037 // die gesamte Seite abgearbeitet werden. (47722) 3038 // OD 2004-05-13 #i28701# - If the wrapping style has to be considered 3039 // on the object positioning, the complete area has to be processed, 3040 // because content frames before the anchor frame also have to consider 3041 // the object for the text wrapping. 3042 // --> OD 2004-08-25 #i3317# - The complete area has always been 3043 // processed. 3044 { 3045 pCnt = pArea->ContainsCntnt(); 3046 } 3047 // <-- 3048 } 3049 SwFrm *pLastTab = 0; 3050 3051 while ( pCnt && pArea && pArea->IsAnLower( pCnt ) ) 3052 { 3053 ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint ); 3054 if ( pCnt->IsInTab() ) 3055 { 3056 SwLayoutFrm* pCell = pCnt->GetUpper(); 3057 // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()> 3058 // instead of <GetCurrentBoundRect()>, because a recalculation 3059 // of the bounding rectangle isn't intended here. 3060 if ( pCell->IsCellFrm() && 3061 ( pCell->Frm().IsOver( pObj->GetLastBoundRect() ) || 3062 pCell->Frm().IsOver( rRect ) ) ) 3063 // <-- 3064 { 3065 const SwFmtVertOrient &rOri = pCell->GetFmt()->GetVertOrient(); 3066 if ( text::VertOrientation::NONE != rOri.GetVertOrient() ) 3067 pCell->InvalidatePrt(); 3068 } 3069 SwTabFrm *pTab = pCnt->FindTabFrm(); 3070 if ( pTab != pLastTab ) 3071 { 3072 pLastTab = pTab; 3073 // --> OD 2005-01-14 #i40606# - use <GetLastBoundRect()> 3074 // instead of <GetCurrentBoundRect()>, because a recalculation 3075 // of the bounding rectangle isn't intended here. 3076 if ( pTab->Frm().IsOver( pObj->GetLastBoundRect() ) || 3077 pTab->Frm().IsOver( rRect ) ) 3078 // <-- 3079 { 3080 if ( !pFlyFrm || !pFlyFrm->IsLowerOf( pTab ) ) 3081 pTab->InvalidatePrt(); 3082 } 3083 } 3084 } 3085 pCnt = pCnt->GetNextCntntFrm(); 3086 } 3087 // #108745# Sorry, but this causes nothing but trouble. I remove these lines 3088 // taking the risk that the footer frame will have a wrong height 3089 // if( pPage->Lower() ) 3090 // { 3091 // SwFrm* pFrm = pPage->Lower(); 3092 // while( pFrm->GetNext() ) 3093 // pFrm = pFrm->GetNext(); 3094 // if( pFrm->IsFooterFrm() && 3095 // ( ( pFrm->Frm().IsOver( pObj->GetBoundRect() ) || 3096 // pFrm->Frm().IsOver( rRect ) ) ) ) 3097 // pFrm->InvalidateSize(); 3098 // } 3099 // --> OD 2007-07-24 #128702# - make code robust 3100 if ( pPage && pPage->GetSortedObjs() ) 3101 // <-- 3102 { 3103 pObj->GetOrdNum(); 3104 const SwSortedObjs &rObjs = *pPage->GetSortedObjs(); 3105 for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i ) 3106 { 3107 SwAnchoredObject* pAnchoredObj = rObjs[i]; 3108 if ( pAnchoredObj->ISA(SwFlyFrm) ) 3109 { 3110 if( pAnchoredObj->GetDrawObj() == pObj ) 3111 continue; 3112 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj); 3113 if ( pFly->Frm().Top() == WEIT_WECH ) 3114 continue; 3115 3116 if ( !pFlyFrm || 3117 (!pFly->IsLowerOf( pFlyFrm ) && 3118 pFly->GetVirtDrawObj()->GetOrdNumDirect() < pObj->GetOrdNumDirect())) 3119 { 3120 pCnt = pFly->ContainsCntnt(); 3121 while ( pCnt ) 3122 { 3123 ::lcl_NotifyCntnt( pObj, pCnt, rRect, eHint ); 3124 pCnt = pCnt->GetNextCntntFrm(); 3125 } 3126 } 3127 if( pFly->IsFlyLayFrm() ) 3128 { 3129 if( pFly->Lower() && pFly->Lower()->IsColumnFrm() && 3130 pFly->Frm().Bottom() >= rRect.Top() && 3131 pFly->Frm().Top() <= rRect.Bottom() && 3132 pFly->Frm().Right() >= rRect.Left() && 3133 pFly->Frm().Left() <= rRect.Right() ) 3134 { 3135 pFly->InvalidateSize(); 3136 } 3137 } 3138 //Flys, die ueber mir liegen muessen/mussten evtl. 3139 //ausweichen, wenn sie eine automatische Ausrichtung haben. 3140 //das ist unabhaengig von meinem Attribut, weil dies sich 3141 //gerade geaendert haben kann und eben deshalb 3142 //umformatiert wurde. 3143 else if ( pFly->IsFlyAtCntFrm() && 3144 pObj->GetOrdNumDirect() < 3145 pFly->GetVirtDrawObj()->GetOrdNumDirect() && 3146 pFlyFrm && !pFly->IsLowerOf( pFlyFrm ) ) 3147 { 3148 const SwFmtHoriOrient &rH = pFly->GetFmt()->GetHoriOrient(); 3149 if ( text::HoriOrientation::NONE != rH.GetHoriOrient() && 3150 text::HoriOrientation::CENTER != rH.GetHoriOrient() && 3151 ( !pFly->IsAutoPos() || text::RelOrientation::CHAR != rH.GetRelationOrient() ) && 3152 (pFly->Frm().Bottom() >= rRect.Top() && 3153 pFly->Frm().Top() <= rRect.Bottom()) ) 3154 pFly->InvalidatePos(); 3155 } 3156 } 3157 } 3158 } 3159 if ( pFlyFrm && pAnchor->GetUpper() && pAnchor->IsInTab() )//MA_FLY_HEIGHT 3160 pAnchor->GetUpper()->InvalidateSize(); 3161 3162 // --> OD 2008-01-30 #i82258# - make code robust 3163 ViewShell* pSh = 0; 3164 if ( bInva && pPage && 3165 0 != (pSh = pPage->getRootFrm()->GetCurrShell()) ) 3166 { 3167 pSh->InvalidateWindows( rRect ); 3168 } 3169 // <-- 3170 } 3171 3172 /************************************************************************* 3173 |* 3174 |* GetVirtualUpper() liefert bei absatzgebundenen Objekten den Upper 3175 |* des Ankers. Falls es sich dabei um verkettete Rahmen oder 3176 |* Fussnoten handelt, wird ggf. der "virtuelle" Upper ermittelt. 3177 |* 3178 |*************************************************************************/ 3179 3180 const SwFrm* GetVirtualUpper( const SwFrm* pFrm, const Point& rPos ) 3181 { 3182 if( pFrm->IsTxtFrm() ) 3183 { 3184 pFrm = pFrm->GetUpper(); 3185 if( !pFrm->Frm().IsInside( rPos ) ) 3186 { 3187 if( pFrm->IsFtnFrm() ) 3188 { 3189 const SwFtnFrm* pTmp = ((SwFtnFrm*)pFrm)->GetFollow(); 3190 while( pTmp ) 3191 { 3192 if( pTmp->Frm().IsInside( rPos ) ) 3193 return pTmp; 3194 pTmp = pTmp->GetFollow(); 3195 } 3196 } 3197 else 3198 { 3199 SwFlyFrm* pTmp = (SwFlyFrm*)pFrm->FindFlyFrm(); 3200 while( pTmp ) 3201 { 3202 if( pTmp->Frm().IsInside( rPos ) ) 3203 return pTmp; 3204 pTmp = pTmp->GetNextLink(); 3205 } 3206 } 3207 } 3208 } 3209 return pFrm; 3210 } 3211 3212 /*************************************************************************/ 3213 3214 sal_Bool Is_Lower_Of( const SwFrm *pCurrFrm, const SdrObject* pObj ) 3215 { 3216 Point aPos; 3217 const SwFrm* pFrm; 3218 if( pObj->ISA(SwVirtFlyDrawObj) ) 3219 { 3220 const SwFlyFrm* pFly = ( (SwVirtFlyDrawObj*)pObj )->GetFlyFrm(); 3221 pFrm = pFly->GetAnchorFrm(); 3222 aPos = pFly->Frm().Pos(); 3223 } 3224 else 3225 { 3226 pFrm = ( (SwDrawContact*)GetUserCall(pObj) )->GetAnchorFrm(pObj); 3227 aPos = pObj->GetCurrentBoundRect().TopLeft(); 3228 } 3229 ASSERT( pFrm, "8-( Fly is lost in Space." ); 3230 pFrm = GetVirtualUpper( pFrm, aPos ); 3231 do 3232 { if ( pFrm == pCurrFrm ) 3233 return sal_True; 3234 if( pFrm->IsFlyFrm() ) 3235 { 3236 aPos = pFrm->Frm().Pos(); 3237 pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos ); 3238 } 3239 else 3240 pFrm = pFrm->GetUpper(); 3241 } while ( pFrm ); 3242 return sal_False; 3243 } 3244 3245 const SwFrm *FindKontext( const SwFrm *pFrm, sal_uInt16 nAdditionalKontextTyp ) 3246 { 3247 //Liefert die Umgebung des Frm in die kein Fly aus einer anderen 3248 //Umgebung hineinragen kann. 3249 const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT | 3250 FRM_FTN | FRM_FLY | 3251 FRM_TAB | FRM_ROW | FRM_CELL | 3252 nAdditionalKontextTyp; 3253 do 3254 { if ( pFrm->GetType() & nTyp ) 3255 break; 3256 pFrm = pFrm->GetUpper(); 3257 } while( pFrm ); 3258 return pFrm; 3259 } 3260 3261 sal_Bool IsFrmInSameKontext( const SwFrm *pInnerFrm, const SwFrm *pFrm ) 3262 { 3263 const SwFrm *pKontext = FindKontext( pInnerFrm, 0 ); 3264 3265 const sal_uInt16 nTyp = FRM_ROOT | FRM_HEADER | FRM_FOOTER | FRM_FTNCONT | 3266 FRM_FTN | FRM_FLY | 3267 FRM_TAB | FRM_ROW | FRM_CELL; 3268 do 3269 { if ( pFrm->GetType() & nTyp ) 3270 { 3271 if( pFrm == pKontext ) 3272 return sal_True; 3273 if( pFrm->IsCellFrm() ) 3274 return sal_False; 3275 } 3276 if( pFrm->IsFlyFrm() ) 3277 { 3278 Point aPos( pFrm->Frm().Pos() ); 3279 pFrm = GetVirtualUpper( ((const SwFlyFrm*)pFrm)->GetAnchorFrm(), aPos ); 3280 } 3281 else 3282 pFrm = pFrm->GetUpper(); 3283 } while( pFrm ); 3284 3285 return sal_False; 3286 } 3287 3288 3289 //--------------------------------- 3290 3291 SwTwips MA_FASTCALL lcl_CalcCellRstHeight( SwLayoutFrm *pCell ) 3292 { 3293 if ( pCell->Lower()->IsCntntFrm() || pCell->Lower()->IsSctFrm() ) 3294 { 3295 SwFrm *pLow = pCell->Lower(); 3296 long nHeight = 0, nFlyAdd = 0; 3297 do 3298 { 3299 long nLow = pLow->Frm().Height(); 3300 if( pLow->IsTxtFrm() && ((SwTxtFrm*)pLow)->IsUndersized() ) 3301 nLow += ((SwTxtFrm*)pLow)->GetParHeight()-pLow->Prt().Height(); 3302 else if( pLow->IsSctFrm() && ((SwSectionFrm*)pLow)->IsUndersized() ) 3303 nLow += ((SwSectionFrm*)pLow)->Undersize(); 3304 nFlyAdd = Max( 0L, nFlyAdd - nLow ); 3305 nFlyAdd = Max( nFlyAdd, ::CalcHeightWidthFlys( pLow ) ); 3306 nHeight += nLow; 3307 pLow = pLow->GetNext(); 3308 } while ( pLow ); 3309 if ( nFlyAdd ) 3310 nHeight += nFlyAdd; 3311 3312 //Der Border will natuerlich auch mitspielen, er kann leider nicht 3313 //aus PrtArea und Frm errechnet werden, da diese in beliebiger 3314 //Kombination ungueltig sein koennen. 3315 SwBorderAttrAccess aAccess( SwFrm::GetCache(), pCell ); 3316 const SwBorderAttrs &rAttrs = *aAccess.Get(); 3317 nHeight += rAttrs.CalcTop() + rAttrs.CalcBottom(); 3318 3319 return pCell->Frm().Height() - nHeight; 3320 } 3321 else 3322 { 3323 long nRstHeight = 0; 3324 SwFrm *pLow = pCell->Lower(); 3325 do 3326 { nRstHeight += ::CalcRowRstHeight( (SwLayoutFrm*)pLow ); 3327 pLow = pLow->GetNext(); 3328 3329 } while ( pLow ); 3330 3331 return nRstHeight; 3332 } 3333 } 3334 3335 SwTwips MA_FASTCALL CalcRowRstHeight( SwLayoutFrm *pRow ) 3336 { 3337 SwTwips nRstHeight = LONG_MAX; 3338 SwLayoutFrm *pLow = (SwLayoutFrm*)pRow->Lower(); 3339 while ( pLow ) 3340 { 3341 nRstHeight = Min( nRstHeight, ::lcl_CalcCellRstHeight( pLow ) ); 3342 pLow = (SwLayoutFrm*)pLow->GetNext(); 3343 } 3344 return nRstHeight; 3345 } 3346 3347 const SwFrm* MA_FASTCALL FindPage( const SwRect &rRect, const SwFrm *pPage ) 3348 { 3349 if ( !rRect.IsOver( pPage->Frm() ) ) 3350 { 3351 const SwRootFrm* pRootFrm = static_cast<const SwRootFrm*>(pPage->GetUpper()); 3352 const SwFrm* pTmpPage = pRootFrm ? pRootFrm->GetPageAtPos( rRect.TopLeft(), &rRect.SSize(), true ) : 0; 3353 if ( pTmpPage ) 3354 pPage = pTmpPage; 3355 } 3356 3357 return pPage; 3358 } 3359 3360 #include <svl/smplhint.hxx> 3361 class SwFrmHolder : private SfxListener 3362 { 3363 SwFrm* pFrm; 3364 bool bSet; 3365 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); 3366 public: 3367 SwFrmHolder() : pFrm(0), bSet(false) {} 3368 void SetFrm( SwFrm* pHold ); 3369 SwFrm* GetFrm() { return pFrm; } 3370 void Reset(); 3371 bool IsSet() { return bSet; } 3372 }; 3373 3374 void SwFrmHolder::SetFrm( SwFrm* pHold ) 3375 { 3376 bSet = true; 3377 pFrm = pHold; 3378 StartListening(*pHold); 3379 } 3380 3381 void SwFrmHolder::Reset() 3382 { 3383 if (pFrm) 3384 EndListening(*pFrm); 3385 bSet = false; 3386 pFrm = 0; 3387 } 3388 3389 void SwFrmHolder::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 3390 { 3391 if ( rHint.IsA(TYPE(SfxSimpleHint)) ) 3392 { 3393 if ( ( (SfxSimpleHint&) rHint ).GetId() == SFX_HINT_DYING && &rBC == pFrm ) 3394 pFrm = 0; 3395 } 3396 } 3397 3398 SwFrm* GetFrmOfModify( const SwRootFrm* pLayout, SwModify const& rMod, sal_uInt16 const nFrmType, 3399 const Point* pPoint, const SwPosition *pPos, const sal_Bool bCalcFrm ) 3400 { 3401 SwFrm *pMinFrm = 0, *pTmpFrm; 3402 SwFrmHolder aHolder; 3403 SwRect aCalcRect; 3404 bool bClientIterChanged = false; 3405 3406 SwIterator<SwFrm,SwModify> aIter( rMod ); 3407 do { 3408 pMinFrm = 0; 3409 aHolder.Reset(); 3410 sal_uInt64 nMinDist = 0; 3411 bClientIterChanged = false; 3412 3413 for( pTmpFrm = aIter.First(); pTmpFrm; pTmpFrm = aIter.Next() ) 3414 { 3415 if( pTmpFrm->GetType() & nFrmType && 3416 ( !pLayout || pLayout == pTmpFrm->getRootFrm() ) && 3417 (!pTmpFrm->IsFlowFrm() || 3418 !SwFlowFrm::CastFlowFrm( pTmpFrm )->IsFollow() )) 3419 { 3420 if( pPoint ) 3421 { 3422 // watch for Frm being deleted 3423 if ( pMinFrm ) 3424 aHolder.SetFrm( pMinFrm ); 3425 else 3426 aHolder.Reset(); 3427 3428 if( bCalcFrm ) 3429 { 3430 // --> OD 2005-03-04 #b6234250# - format parent Writer 3431 // fly frame, if it isn't been formatted yet. 3432 // Note: The Writer fly frame could be the frame itself. 3433 SwFlyFrm* pFlyFrm( pTmpFrm->FindFlyFrm() ); 3434 if ( pFlyFrm && 3435 pFlyFrm->Frm().Pos().X() == WEIT_WECH && 3436 pFlyFrm->Frm().Pos().Y() == WEIT_WECH ) 3437 { 3438 SwObjectFormatter::FormatObj( *pFlyFrm ); 3439 } 3440 // <-- 3441 pTmpFrm->Calc(); 3442 } 3443 3444 // #127369# 3445 // aIter.IsChanged checks if the current pTmpFrm has been deleted while 3446 // it is the current iterator 3447 // FrmHolder watches for deletion of the current pMinFrm 3448 if( aIter.IsChanged() || ( aHolder.IsSet() && !aHolder.GetFrm() ) ) 3449 { 3450 // restart iteration 3451 bClientIterChanged = true; 3452 break; 3453 } 3454 3455 // bei Flys ggfs. ueber den Parent gehen wenn sie selbst 3456 // nocht nicht "formatiert" sind 3457 if( !bCalcFrm && nFrmType & FRM_FLY && 3458 ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm() && 3459 WEIT_WECH == pTmpFrm->Frm().Pos().X() && 3460 WEIT_WECH == pTmpFrm->Frm().Pos().Y() ) 3461 aCalcRect = ((SwFlyFrm*)pTmpFrm)->GetAnchorFrm()->Frm(); 3462 else 3463 aCalcRect = pTmpFrm->Frm(); 3464 3465 if ( aCalcRect.IsInside( *pPoint ) ) 3466 { 3467 pMinFrm = pTmpFrm; 3468 break; 3469 } 3470 3471 // Point not in rectangle. Compare distances: 3472 const Point aCalcRectCenter = aCalcRect.Center(); 3473 const Point aDiff = aCalcRectCenter - *pPoint; 3474 const sal_uInt64 nCurrentDist = aDiff.X() * aDiff.X() + aDiff.Y() * aDiff.Y(); // opt: no sqrt 3475 if ( !pMinFrm || nCurrentDist < nMinDist ) 3476 { 3477 pMinFrm = pTmpFrm; 3478 nMinDist = nCurrentDist; 3479 } 3480 } 3481 else 3482 { 3483 // Wenn kein pPoint angegeben ist, dann reichen 3484 // wir irgendeinen raus: den ersten! 3485 pMinFrm = pTmpFrm; 3486 break; 3487 } 3488 } 3489 } 3490 } while( bClientIterChanged ); 3491 3492 if( pPos && pMinFrm && pMinFrm->IsTxtFrm() ) 3493 return ((SwTxtFrm*)pMinFrm)->GetFrmAtPos( *pPos ); 3494 3495 return pMinFrm; 3496 } 3497 3498 sal_Bool IsExtraData( const SwDoc *pDoc ) 3499 { 3500 const SwLineNumberInfo &rInf = pDoc->GetLineNumberInfo(); 3501 return rInf.IsPaintLineNumbers() || 3502 rInf.IsCountInFlys() || 3503 ((sal_Int16)SW_MOD()->GetRedlineMarkPos() != text::HoriOrientation::NONE && 3504 pDoc->GetRedlineTbl().Count()); 3505 } 3506 3507 // OD 22.09.2003 #110978# 3508 const SwRect SwPageFrm::PrtWithoutHeaderAndFooter() const 3509 { 3510 SwRect aPrtWithoutHeaderFooter( Prt() ); 3511 aPrtWithoutHeaderFooter.Pos() += Frm().Pos(); 3512 3513 const SwFrm* pLowerFrm = Lower(); 3514 while ( pLowerFrm ) 3515 { 3516 // Note: independent on text direction page header and page footer are 3517 // always at top respectively at bottom of the page frame. 3518 if ( pLowerFrm->IsHeaderFrm() ) 3519 { 3520 aPrtWithoutHeaderFooter.Top( aPrtWithoutHeaderFooter.Top() + 3521 pLowerFrm->Frm().Height() ); 3522 } 3523 if ( pLowerFrm->IsFooterFrm() ) 3524 { 3525 aPrtWithoutHeaderFooter.Bottom( aPrtWithoutHeaderFooter.Bottom() - 3526 pLowerFrm->Frm().Height() ); 3527 } 3528 3529 pLowerFrm = pLowerFrm->GetNext(); 3530 } 3531 3532 return aPrtWithoutHeaderFooter; 3533 } 3534 3535 /** method to determine the spacing values of a frame 3536 3537 OD 2004-03-10 #i28701# 3538 OD 2009-08-28 #i102458# 3539 Add output parameter <obIsLineSpacingProportional> 3540 3541 @author OD 3542 */ 3543 void GetSpacingValuesOfFrm( const SwFrm& rFrm, 3544 SwTwips& onLowerSpacing, 3545 SwTwips& onLineSpacing, 3546 bool& obIsLineSpacingProportional ) 3547 { 3548 if ( !rFrm.IsFlowFrm() ) 3549 { 3550 onLowerSpacing = 0; 3551 onLineSpacing = 0; 3552 } 3553 else 3554 { 3555 const SvxULSpaceItem& rULSpace = rFrm.GetAttrSet()->GetULSpace(); 3556 onLowerSpacing = rULSpace.GetLower(); 3557 3558 onLineSpacing = 0; 3559 obIsLineSpacingProportional = false; 3560 if ( rFrm.IsTxtFrm() ) 3561 { 3562 onLineSpacing = static_cast<const SwTxtFrm&>(rFrm).GetLineSpace(); 3563 obIsLineSpacingProportional = 3564 onLineSpacing != 0 && 3565 static_cast<const SwTxtFrm&>(rFrm).GetLineSpace( true ) == 0; 3566 } 3567 3568 ASSERT( onLowerSpacing >= 0 && onLineSpacing >= 0, 3569 "<GetSpacingValuesOfFrm(..)> - spacing values aren't positive!" ); 3570 } 3571 } 3572 3573 /** method to get the content of the table cell, skipping content from nested tables 3574 */ 3575 const SwCntntFrm* GetCellCntnt( const SwLayoutFrm& rCell ) 3576 { 3577 const SwCntntFrm* pCntnt = rCell.ContainsCntnt(); 3578 const SwTabFrm* pTab = rCell.FindTabFrm(); 3579 3580 while ( pCntnt && rCell.IsAnLower( pCntnt ) ) 3581 { 3582 const SwTabFrm* pTmpTab = pCntnt->FindTabFrm(); 3583 if ( pTmpTab != pTab ) 3584 { 3585 pCntnt = pTmpTab->FindLastCntnt(); 3586 if ( pCntnt ) 3587 3588 pCntnt = pCntnt->FindNextCnt(); 3589 3590 } 3591 else 3592 break; 3593 } 3594 return pCntnt; 3595 } 3596 3597 /** Can be used to check if a frame has been deleted 3598 */ 3599 bool SwDeletionChecker::HasBeenDeleted() 3600 { 3601 if ( !mpFrm || !mpRegIn ) 3602 return false; 3603 3604 SwIterator<SwFrm,SwModify> aIter(*mpRegIn); 3605 SwFrm* pLast = aIter.First(); 3606 while ( pLast ) 3607 { 3608 if ( pLast == mpFrm ) 3609 return false; 3610 pLast = aIter.Next(); 3611 } 3612 3613 return true; 3614 } 3615 3616 3617