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