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