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