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