1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 #include <svl/smplhint.hxx> 28 #include <svl/itemiter.hxx> 29 #include <hints.hxx> 30 #include <txtftn.hxx> 31 #include <fmtftn.hxx> 32 #include <fmtclbl.hxx> 33 #include "sectfrm.hxx" 34 #include "section.hxx" // SwSection 35 #include "frmtool.hxx" // StackHack 36 #include "doc.hxx" // SwDoc 37 #include "cntfrm.hxx" // SwCntntFrm 38 #include "rootfrm.hxx" // SwRootFrm 39 #include "pagefrm.hxx" // SwPageFrm 40 #include "fmtpdsc.hxx" // SwFmtPageDesc 41 #include "fmtcntnt.hxx" // SwFmtCntnt 42 #include "ndindex.hxx" // SwNodeIndex 43 #include "ftnidx.hxx" 44 #include "txtfrm.hxx" // SwTxtFrm 45 #include "fmtclds.hxx" // SwFmtCol 46 #include "colfrm.hxx" // SwColumnFrm 47 #include "tabfrm.hxx" // SwTabFrm 48 #include "flyfrm.hxx" // SwFlyFrm 49 #include "ftnfrm.hxx" // SwFtnFrm 50 #include "layouter.hxx" // SwLayouter 51 #include "dbg_lay.hxx" 52 #include "viewsh.hxx" 53 #include "viewopt.hxx" 54 #include "viewimp.hxx" 55 #include <editeng/ulspitem.hxx> 56 #include <editeng/lrspitem.hxx> 57 #include <editeng/brshitem.hxx> 58 #include <fmtftntx.hxx> 59 // OD 2004-05-24 #i28701# 60 #include <dflyobj.hxx> 61 #include <flyfrms.hxx> 62 #include <sortedobjs.hxx> 63 64 SV_IMPL_PTRARR_SORT( SwDestroyList, SwSectionFrmPtr ) 65 66 /************************************************************************* 67 |* 68 |* SwSectionFrm::SwSectionFrm(), ~SwSectionFrm() 69 |* 70 |* Ersterstellung AMA 26. Nov. 97 71 |* Letzte Aenderung AMA 26. Nov. 97 72 |* 73 |*************************************************************************/ 74 SwSectionFrm::SwSectionFrm( SwSection &rSect, SwFrm* pSib ) : 75 SwLayoutFrm( rSect.GetFmt(), pSib ), 76 SwFlowFrm( (SwFrm&)*this ), 77 pSection( &rSect ) 78 { 79 nType = FRMC_SECTION; 80 81 CalcFtnAtEndFlag(); 82 CalcEndAtEndFlag(); 83 } 84 85 SwSectionFrm::SwSectionFrm( SwSectionFrm &rSect, sal_Bool bMaster ) : 86 SwLayoutFrm( rSect.GetFmt(), rSect.getRootFrm() ), 87 SwFlowFrm( (SwFrm&)*this ), 88 pSection( rSect.GetSection() ) 89 { 90 bFtnAtEnd = rSect.IsFtnAtEnd(); 91 bEndnAtEnd = rSect.IsEndnAtEnd(); 92 bLockJoin = sal_False; 93 nType = FRMC_SECTION; 94 95 PROTOCOL( this, PROT_SECTION, bMaster ? ACT_CREATE_MASTER : ACT_CREATE_FOLLOW, &rSect ) 96 97 if( bMaster ) 98 { 99 if( rSect.IsFollow() ) 100 { 101 SwSectionFrm* pMaster = rSect.FindMaster(); 102 pMaster->SetFollow( this ); 103 bIsFollow = sal_True; 104 } 105 else 106 rSect.bIsFollow = sal_True; 107 SetFollow( &rSect ); 108 } 109 else 110 { 111 bIsFollow = sal_True; 112 SetFollow( rSect.GetFollow() ); 113 rSect.SetFollow( this ); 114 if( !GetFollow() ) 115 rSect.SimpleFormat(); 116 if( !rSect.IsColLocked() ) 117 rSect.InvalidateSize(); 118 } 119 } 120 121 // NOTE: call <SwSectionFrm::Init()> directly after creation of a new section 122 // frame and its insert in the layout. 123 void SwSectionFrm::Init() 124 { 125 ASSERT( GetUpper(), "SwSectionFrm::Init before insertion?!" ); 126 SWRECTFN( this ) 127 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 128 (Frm().*fnRect->fnSetWidth)( nWidth ); 129 (Frm().*fnRect->fnSetHeight)( 0 ); 130 131 // #109700# LRSpace for sections 132 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace(); 133 (Prt().*fnRect->fnSetLeft)( rLRSpace.GetLeft() ); 134 (Prt().*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() - 135 rLRSpace.GetRight() ); 136 (Prt().*fnRect->fnSetHeight)( 0 ); 137 138 const SwFmtCol &rCol = GetFmt()->GetCol(); 139 if( ( rCol.GetNumCols() > 1 || IsAnyNoteAtEnd() ) && !IsInFtn() ) 140 { 141 const SwFmtCol *pOld = Lower() ? &rCol : new SwFmtCol; 142 ChgColumns( *pOld, rCol, IsAnyNoteAtEnd() ); 143 if( pOld != &rCol ) 144 delete pOld; 145 } 146 } 147 148 SwSectionFrm::~SwSectionFrm() 149 { 150 if( GetFmt() && !GetFmt()->GetDoc()->IsInDtor() ) 151 { 152 SwRootFrm *pRootFrm = getRootFrm(); 153 if( pRootFrm ) 154 pRootFrm->RemoveFromList( this ); //swmod 071108//swmod 071225 155 if( IsFollow() ) 156 { 157 SwSectionFrm *pMaster = FindMaster(); 158 if( pMaster ) 159 { 160 PROTOCOL( this, PROT_SECTION, ACT_DEL_FOLLOW, pMaster ) 161 pMaster->SetFollow( GetFollow() ); 162 // Ein Master greift sich immer den Platz bis zur Unterkante seines 163 // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder 164 // freigeben, deshalb wird die Size des Masters invalidiert. 165 if( !GetFollow() ) 166 pMaster->InvalidateSize(); 167 } 168 } 169 else if( HasFollow() ) 170 { 171 PROTOCOL( this, PROT_SECTION, ACT_DEL_MASTER, GetFollow() ) 172 GetFollow()->bIsFollow = sal_False; 173 } 174 } 175 } 176 177 178 /************************************************************************* 179 |* 180 |* SwSectionFrm::DelEmpty() 181 |* 182 |* Ersterstellung AMA 17. Dec. 97 183 |* Letzte Aenderung AMA 17. Dec. 97 184 |* 185 |*************************************************************************/ 186 void SwSectionFrm::DelEmpty( sal_Bool bRemove ) 187 { 188 if( IsColLocked() ) 189 { 190 ASSERT( !bRemove, "Don't delete locked SectionFrms" ); 191 return; 192 } 193 SwFrm* pUp = GetUpper(); 194 if( pUp ) 195 { 196 // --> OD 2005-12-01 #i27138# 197 // notify accessibility paragraphs objects about changed 198 // CONTENT_FLOWS_FROM/_TO relation. 199 // Relation CONTENT_FLOWS_FROM for current next paragraph will change 200 // and relation CONTENT_FLOWS_TO for current previous paragraph will change. 201 { 202 ViewShell* pViewShell( getRootFrm()->GetCurrShell() ); 203 if ( pViewShell && pViewShell->GetLayout() && 204 pViewShell->GetLayout()->IsAnyShellAccessible() ) 205 { 206 pViewShell->InvalidateAccessibleParaFlowRelation( 207 dynamic_cast<SwTxtFrm*>(FindNextCnt( true )), 208 dynamic_cast<SwTxtFrm*>(FindPrevCnt( true )) ); 209 } 210 } 211 // <-- 212 _Cut( bRemove ); 213 } 214 if( IsFollow() ) 215 { 216 SwSectionFrm *pMaster = FindMaster(); 217 pMaster->SetFollow( GetFollow() ); 218 // Ein Master greift sich immer den Platz bis zur Unterkante seines 219 // Uppers. Wenn er keinen Follow mehr hat, kann er diesen ggf. wieder 220 // freigeben, deshalb wird die Size des Masters invalidiert. 221 if( !GetFollow() && !pMaster->IsColLocked() ) 222 pMaster->InvalidateSize(); 223 bIsFollow = sal_False; 224 } 225 else if( HasFollow() ) 226 GetFollow()->bIsFollow = sal_False; 227 pFollow = NULL; 228 if( pUp ) 229 { 230 Frm().Height( 0 ); 231 // Wenn wir sowieso sofort zerstoert werden, brauchen/duerfen wir 232 // uns gar nicht erst in die Liste eintragen 233 if( bRemove ) 234 { // Wenn wir bereits halbtot waren vor diesem DelEmpty, so 235 // stehen wir vermutlich auch in der Liste und muessen uns 236 // dort austragen 237 if( !pSection && getRootFrm() ) 238 getRootFrm()->RemoveFromList( this ); 239 } 240 else if( getRootFrm() ) 241 getRootFrm()->InsertEmptySct( this ); //swmod 071108//swmod 071225 242 pSection = NULL; // damit ist allerdings eine Reanimierung quasi ausgeschlossen 243 } 244 } 245 246 /************************************************************************* 247 |* 248 |* SwSectionFrm::Cut() 249 |* 250 |* Ersterstellung AMA 02. Dec. 97 251 |* Letzte Aenderung AMA 02. Dec. 97 252 |* 253 |*************************************************************************/ 254 void SwSectionFrm::Cut() 255 { 256 _Cut( sal_True ); 257 } 258 259 void SwSectionFrm::_Cut( sal_Bool bRemove ) 260 { 261 ASSERT( GetUpper(), "Cut ohne Upper()." ); 262 263 PROTOCOL( this, PROT_CUT, 0, GetUpper() ) 264 265 SwPageFrm *pPage = FindPageFrm(); 266 InvalidatePage( pPage ); 267 SwFrm *pFrm = GetNext(); 268 SwFrm* pPrepFrm = NULL; 269 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() ) 270 pFrm = pFrm->GetNext(); 271 if( pFrm ) 272 { //Der alte Nachfolger hat evtl. einen Abstand zum Vorgaenger 273 //berechnet der ist jetzt wo er der erste wird obsolete 274 pFrm->_InvalidatePrt(); 275 pFrm->_InvalidatePos(); 276 if( pFrm->IsSctFrm() ) 277 pFrm = ((SwSectionFrm*)pFrm)->ContainsAny(); 278 if ( pFrm && pFrm->IsCntntFrm() ) 279 { 280 pFrm->InvalidatePage( pPage ); 281 if( IsInFtn() && !GetIndPrev() ) 282 pPrepFrm = pFrm; 283 } 284 } 285 else 286 { 287 InvalidateNextPos(); 288 //Einer muss die Retusche uebernehmen: Vorgaenger oder Upper 289 if ( 0 != (pFrm = GetPrev()) ) 290 { pFrm->SetRetouche(); 291 pFrm->Prepare( PREP_WIDOWS_ORPHANS ); 292 if ( pFrm->IsCntntFrm() ) 293 pFrm->InvalidatePage( pPage ); 294 } 295 //Wenn ich der einzige FlowFrm in meinem Upper bin (war), so muss 296 //er die Retouche uebernehmen. 297 //Ausserdem kann eine Leerseite entstanden sein. 298 else 299 { SwRootFrm *pRoot = (SwRootFrm*)pPage->GetUpper(); 300 pRoot->SetSuperfluous(); 301 GetUpper()->SetCompletePaint(); 302 } 303 } 304 //Erst removen, dann Upper Shrinken. 305 SwLayoutFrm *pUp = GetUpper(); 306 if( bRemove ) 307 { 308 Remove(); 309 if( pUp && !pUp->Lower() && pUp->IsFtnFrm() && !pUp->IsColLocked() && 310 pUp->GetUpper() ) 311 { 312 pUp->Cut(); 313 delete pUp; 314 pUp = NULL; 315 } 316 } 317 if( pPrepFrm ) 318 pPrepFrm->Prepare( PREP_FTN ); 319 if ( pUp ) 320 { 321 SWRECTFN( this ); 322 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)(); 323 if( nFrmHeight > 0 ) 324 { 325 if( !bRemove ) 326 { 327 (Frm().*fnRect->fnSetHeight)( 0 ); 328 (Prt().*fnRect->fnSetHeight)( 0 ); 329 } 330 pUp->Shrink( nFrmHeight ); 331 } 332 } 333 } 334 335 /************************************************************************* 336 |* 337 |* SwSectionFrm::Paste() 338 |* 339 |* Ersterstellung AMA 04. Dec. 97 340 |* Letzte Aenderung AMA 04. Dec. 97 341 |* 342 |*************************************************************************/ 343 344 void SwSectionFrm::Paste( SwFrm* pParent, SwFrm* pSibling ) 345 { 346 ASSERT( pParent, "Kein Parent fuer Paste." ); 347 ASSERT( pParent->IsLayoutFrm(), "Parent ist CntntFrm." ); 348 ASSERT( pParent != this, "Bin selbst der Parent." ); 349 ASSERT( pSibling != this, "Bin mein eigener Nachbar." ); 350 ASSERT( !GetPrev() && !GetUpper(), 351 "Bin noch irgendwo angemeldet." ); 352 353 PROTOCOL( this, PROT_PASTE, 0, GetUpper() ) 354 355 //In den Baum einhaengen. 356 SwSectionFrm* pSect = pParent->FindSctFrm(); 357 // --> OD 2008-06-23 #156927# 358 // Assure that parent is not inside a table frame, which is inside the found section frame. 359 if ( pSect ) 360 { 361 SwTabFrm* pTableFrm = pParent->FindTabFrm(); 362 if ( pTableFrm && 363 pSect->IsAnLower( pTableFrm ) ) 364 { 365 pSect = 0; 366 } 367 } 368 // <-- 369 370 SWRECTFN( pParent ) 371 if( pSect && HasToBreak( pSect ) ) 372 { 373 if( pParent->IsColBodyFrm() ) // handelt es sich um einen spaltigen Bereich 374 { 375 // Falls wir zufaellig am Ende einer Spalte stehen, muss pSibling 376 // auf den ersten Frame der naechsten Spalte zeigen, damit 377 // der Inhalt der naechsten Spalte von InsertGroup richtig in den 378 // neu angelegten pSect umgehaengt wird. 379 SwColumnFrm *pCol = (SwColumnFrm*)pParent->GetUpper(); 380 while( !pSibling && 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) ) 381 pSibling = ((SwLayoutFrm*)((SwColumnFrm*)pCol)->Lower())->Lower(); 382 if( pSibling ) 383 { 384 // Schlimmer noch: alle folgenden Spalteninhalte muessen 385 // an die pSibling-Kette angehaengt werden, damit sie 386 // mitgenommen werden. 387 SwFrm *pTmp = pSibling; 388 while ( 0 != ( pCol = (SwColumnFrm*)pCol->GetNext() ) ) 389 { 390 while ( pTmp->GetNext() ) 391 pTmp = pTmp->GetNext(); 392 SwFrm* pSave = ::SaveCntnt( pCol ); 393 ::RestoreCntnt( pSave, pSibling->GetUpper(), pTmp, true ); 394 } 395 } 396 } 397 pParent = pSect; 398 pSect = new SwSectionFrm( *((SwSectionFrm*)pParent)->GetSection(), pParent ); 399 // Wenn pParent in zwei Teile zerlegt wird, so muss sein Follow am 400 // neuen, zweiten Teil angebracht werden. 401 pSect->SetFollow( ((SwSectionFrm*)pParent)->GetFollow() ); 402 ((SwSectionFrm*)pParent)->SetFollow( NULL ); 403 if( pSect->GetFollow() ) 404 pParent->_InvalidateSize(); 405 406 InsertGroupBefore( pParent, pSibling, pSect ); 407 pSect->Init(); 408 (pSect->*fnRect->fnMakePos)( pSect->GetUpper(), pSect->GetPrev(), sal_True); 409 if( !((SwLayoutFrm*)pParent)->Lower() ) 410 { 411 SwSectionFrm::MoveCntntAndDelete( (SwSectionFrm*)pParent, sal_False ); 412 pParent = this; 413 } 414 } 415 else 416 InsertGroupBefore( pParent, pSibling, NULL ); 417 418 _InvalidateAll(); 419 SwPageFrm *pPage = FindPageFrm(); 420 InvalidatePage( pPage ); 421 422 if ( pSibling ) 423 { 424 pSibling->_InvalidatePos(); 425 pSibling->_InvalidatePrt(); 426 if ( pSibling->IsCntntFrm() ) 427 pSibling->InvalidatePage( pPage ); 428 } 429 430 SwTwips nFrmHeight = (Frm().*fnRect->fnGetHeight)(); 431 if( nFrmHeight ) 432 pParent->Grow( nFrmHeight ); 433 434 if ( GetPrev() ) 435 { 436 if ( !IsFollow() ) 437 { 438 GetPrev()->InvalidateSize(); 439 if ( GetPrev()->IsCntntFrm() ) 440 GetPrev()->InvalidatePage( pPage ); 441 } 442 } 443 } 444 445 446 /************************************************************************* 447 |* 448 |* SwSectionFrm::HasToBreak() 449 |* 450 |* Hier wird entschieden, ob der this-SectionFrm den uebergebenen 451 |* (Section)Frm aufbrechen soll oder nicht. 452 |* Zunaechst werden uebergeordnete Bereiche immer aufgebrochen, 453 |* spaeter koennte man es einstellbar machen. 454 |* 455 |* Ersterstellung AMA 12. Dec. 97 456 |* Letzte Aenderung AMA 12. Dec. 97 457 |* 458 |*************************************************************************/ 459 460 sal_Bool SwSectionFrm::HasToBreak( const SwFrm* pFrm ) const 461 { 462 if( !pFrm->IsSctFrm() ) 463 return sal_False; 464 465 SwSectionFmt *pTmp = (SwSectionFmt*)GetFmt(); 466 // if( !pTmp->GetSect().GetValue() ) 467 // return sal_False; 468 469 const SwFrmFmt *pOtherFmt = ((SwSectionFrm*)pFrm)->GetFmt(); 470 do 471 { 472 pTmp = pTmp->GetParent(); 473 if( !pTmp ) 474 return sal_False; 475 if( pTmp == pOtherFmt ) 476 return sal_True; 477 } while( sal_True ); // ( pTmp->GetSect().GetValue() ); 478 } 479 480 /************************************************************************* 481 |* 482 |* SwSectionFrm::MergeNext() 483 |* 484 |* Ersterstellung AMA 04. Dec. 97 485 |* Letzte Aenderung AMA 04. Dec. 97 486 |* 487 |* Verschmilzt zwei SectionFrms, falls es sich um den 488 |* gleichen Bereich handelt. 489 |* Notwendig kann dies sein, wenn ein (Unter-)Bereich geloescht wird, der 490 |* einen anderen in zwei Teile zerlegt hatte. 491 |* 492 |*************************************************************************/ 493 494 void SwSectionFrm::MergeNext( SwSectionFrm* pNxt ) 495 { 496 if( !pNxt->IsJoinLocked() && GetSection() == pNxt->GetSection() ) 497 { 498 PROTOCOL( this, PROT_SECTION, ACT_MERGE, pNxt ) 499 500 SwFrm* pTmp = ::SaveCntnt( pNxt ); 501 if( pTmp ) 502 { 503 SwFrm* pLast = Lower(); 504 SwLayoutFrm* pLay = this; 505 if( pLast ) 506 { 507 while( pLast->GetNext() ) 508 pLast = pLast->GetNext(); 509 if( pLast->IsColumnFrm() ) 510 { // Spalten jetzt mit BodyFrm 511 pLay = (SwLayoutFrm*)((SwLayoutFrm*)pLast)->Lower(); 512 pLast = pLay->Lower(); 513 if( pLast ) 514 while( pLast->GetNext() ) 515 pLast = pLast->GetNext(); 516 } 517 } 518 ::RestoreCntnt( pTmp, pLay, pLast, true ); 519 } 520 SetFollow( pNxt->GetFollow() ); 521 pNxt->SetFollow( NULL ); 522 pNxt->bIsFollow = sal_False; 523 pNxt->Cut(); 524 delete pNxt; 525 InvalidateSize(); 526 } 527 } 528 529 /************************************************************************* 530 |* 531 |* SwSectionFrm::SplitSect() 532 |* 533 |* Ersterstellung AMA 29. Apr. 99 534 |* Letzte Aenderung AMA 29. Apr. 99 535 |* 536 |* Zerteilt einen SectionFrm in zwei Teile, der zweite Teil beginnt mit dem 537 |* uebergebenen Frame. 538 |* Benoetigt wird dies beim Einfuegen eines inneren Bereichs, weil innerhalb 539 |* von Rahmen oder Tabellenzellen das MoveFwd nicht den erwuenschten Effekt 540 |* haben kann. 541 |* 542 |*************************************************************************/ 543 544 sal_Bool SwSectionFrm::SplitSect( SwFrm* pFrm, sal_Bool bApres ) 545 { 546 ASSERT( pFrm, "SplitSect: Why?" ); 547 SwFrm* pOther = bApres ? pFrm->FindNext() : pFrm->FindPrev(); 548 if( !pOther ) 549 return sal_False; 550 SwSectionFrm* pSect = pOther->FindSctFrm(); 551 if( pSect != this ) 552 return sal_False; 553 // Den Inhalt zur Seite stellen 554 SwFrm* pSav = ::SaveCntnt( this, bApres ? pOther : pFrm ); 555 ASSERT( pSav, "SplitSect: What's on?" ); 556 if( pSav ) // Robust 557 { // Einen neuen SctFrm anlegen, nicht als Follow/Master 558 SwSectionFrm* pNew = new SwSectionFrm( *pSect->GetSection(), pSect ); 559 pNew->InsertBehind( pSect->GetUpper(), pSect ); 560 pNew->Init(); 561 SWRECTFN( this ) 562 (pNew->*fnRect->fnMakePos)( NULL, pSect, sal_True ); 563 // OD 25.03.2003 #108339# - restore content: 564 // determine layout frame for restoring content after the initialization 565 // of the section frame. In the section initialization the columns are 566 // created. 567 { 568 SwLayoutFrm* pLay = pNew; 569 // Search for last layout frame, e.g. for columned sections. 570 while( pLay->Lower() && pLay->Lower()->IsLayoutFrm() ) 571 pLay = (SwLayoutFrm*)pLay->Lower(); 572 ::RestoreCntnt( pSav, pLay, NULL, true ); 573 } 574 _InvalidateSize(); 575 if( HasFollow() ) 576 { 577 pNew->SetFollow( GetFollow() ); 578 SetFollow( NULL ); 579 } 580 return sal_True; 581 } 582 return sal_False; 583 } 584 585 /************************************************************************* 586 |* 587 |* SwSectionFrm::MoveCntntAndDelete() 588 |* 589 |* Ersterstellung AMA 29. Jan 99 590 |* Letzte Aenderung AMA 29. Jan 99 591 |* 592 |* MoveCntnt wird zur Zerstoerung eines SectionFrms wg. Aufhebung oder 593 |* Verstecken des Bereichs gerufen, um den Inhalt umzuhaengen. 594 |* Wenn der SectionFrm keinen anderen aufbrach, so wird der Inhalt in 595 |* den Upper bewegt. Anderfalls wird der Inhalt in den anderen SectionFrm 596 |* umgehaengt, dieser muss ggf. gemergt werden. 597 |* 598 |*************************************************************************/ 599 // Wenn ein mehrspaltiger Bereich aufgehoben wird, muessen die ContentFrms 600 // invalidiert werden 601 602 void lcl_InvalidateInfFlags( SwFrm* pFrm, sal_Bool bInva ) 603 { 604 while ( pFrm ) 605 { 606 pFrm->InvalidateInfFlags(); 607 if( bInva ) 608 { 609 pFrm->_InvalidatePos(); 610 pFrm->_InvalidateSize(); 611 pFrm->_InvalidatePrt(); 612 } 613 if( pFrm->IsLayoutFrm() ) 614 lcl_InvalidateInfFlags( ((SwLayoutFrm*)pFrm)->GetLower(), sal_False ); 615 pFrm = pFrm->GetNext(); 616 } 617 } 618 619 620 // 621 // Works like SwCntntFrm::ImplGetNextCntntFrm, but starts with a LayoutFrm 622 // 623 SwCntntFrm* lcl_GetNextCntntFrm( const SwLayoutFrm* pLay, bool bFwd ) 624 { 625 if ( bFwd ) 626 { 627 if ( pLay->GetNext() && pLay->GetNext()->IsCntntFrm() ) 628 return (SwCntntFrm*)pLay->GetNext(); 629 } 630 else 631 { 632 if ( pLay->GetPrev() && pLay->GetPrev()->IsCntntFrm() ) 633 return (SwCntntFrm*)pLay->GetPrev(); 634 } 635 636 // #100926# 637 const SwFrm* pFrm = pLay; 638 SwCntntFrm *pCntntFrm = 0; 639 sal_Bool bGoingUp = sal_True; 640 do { 641 const SwFrm *p = 0; 642 sal_Bool bGoingFwdOrBwd = sal_False, bGoingDown = sal_False; 643 644 bGoingDown = !bGoingUp && ( 0 != ( p = pFrm->IsLayoutFrm() ? ((SwLayoutFrm*)pFrm)->Lower() : 0 ) ); 645 if ( !bGoingDown ) 646 { 647 bGoingFwdOrBwd = ( 0 != ( p = pFrm->IsFlyFrm() ? 648 ( bFwd ? ((SwFlyFrm*)pFrm)->GetNextLink() : ((SwFlyFrm*)pFrm)->GetPrevLink() ) : 649 ( bFwd ? pFrm->GetNext() :pFrm->GetPrev() ) ) ); 650 if ( !bGoingFwdOrBwd ) 651 { 652 bGoingUp = (0 != (p = pFrm->GetUpper() ) ); 653 if ( !bGoingUp ) 654 return 0; 655 } 656 } 657 658 bGoingUp = !( bGoingFwdOrBwd || bGoingDown ); 659 660 if( !bFwd && bGoingDown && p ) 661 while ( p->GetNext() ) 662 p = p->GetNext(); 663 664 pFrm = p; 665 } while ( 0 == (pCntntFrm = (pFrm->IsCntntFrm() ? (SwCntntFrm*)pFrm:0) )); 666 667 return pCntntFrm; 668 } 669 670 #define FIRSTLEAF( pLayFrm ) ( ( pLayFrm->Lower() && pLayFrm->Lower()->IsColumnFrm() )\ 671 ? pLayFrm->GetNextLayoutLeaf() \ 672 : pLayFrm ) 673 674 void SwSectionFrm::MoveCntntAndDelete( SwSectionFrm* pDel, sal_Bool bSave ) 675 { 676 sal_Bool bSize = pDel->Lower() && pDel->Lower()->IsColumnFrm(); 677 SwFrm* pPrv = pDel->GetPrev(); 678 SwLayoutFrm* pUp = pDel->GetUpper(); 679 // OD 27.03.2003 #i12711# - initialize local pointer variables. 680 SwSectionFrm* pPrvSct = NULL; 681 SwSectionFrm* pNxtSct = NULL; 682 SwSectionFmt* pParent = static_cast<SwSectionFmt*>(pDel->GetFmt())->GetParent(); 683 if( pDel->IsInTab() && pParent ) 684 { 685 SwTabFrm *pTab = pDel->FindTabFrm(); 686 // Wenn wir innerhalb einer Tabelle liegen, koennen wir nur Bereiche 687 // aufgebrochen haben, die ebenfalls innerhalb liegen, nicht etwa 688 // einen Bereich, der die gesamte Tabelle umfasst. 689 if( pTab->IsInSct() && pParent == pTab->FindSctFrm()->GetFmt() ) 690 pParent = NULL; 691 } 692 // Wenn unser Format einen Parent besitzt, so haben wir vermutlich 693 // einen anderen SectionFrm aufgebrochen, dies muss geprueft werden, 694 // dazu besorgen wir uns zunaechst den vorhergehende und den nach- 695 // folgenden CntntFrm, mal sehen, ob diese in SectionFrms liegen. 696 // OD 27.03.2003 #i12711# - check, if previous and next section belonging 697 // together and can be joined, *not* only if deleted section contains content. 698 if ( pParent ) 699 { 700 SwFrm* pPrvCntnt = lcl_GetNextCntntFrm( pDel, false ); 701 pPrvSct = pPrvCntnt ? pPrvCntnt->FindSctFrm() : NULL; 702 SwFrm* pNxtCntnt = lcl_GetNextCntntFrm( pDel, true ); 703 pNxtSct = pNxtCntnt ? pNxtCntnt->FindSctFrm() : NULL; 704 } 705 else 706 { 707 pParent = NULL; 708 pPrvSct = pNxtSct = NULL; 709 } 710 711 // Jetzt wird der Inhalt beseite gestellt und der Frame zerstoert 712 SwFrm *pSave = bSave ? ::SaveCntnt( pDel ) : NULL; 713 sal_Bool bOldFtn = sal_True; 714 if( pSave && pUp->IsFtnFrm() ) 715 { 716 bOldFtn = ((SwFtnFrm*)pUp)->IsColLocked(); 717 ((SwFtnFrm*)pUp)->ColLock(); 718 } 719 pDel->DelEmpty( sal_True ); 720 delete pDel; 721 if( pParent ) 722 { // Hier wird die geeignete Einfuegeposition gesucht 723 if( pNxtSct && pNxtSct->GetFmt() == pParent ) 724 { // Hier koennen wir uns am Anfang einfuegen 725 pUp = FIRSTLEAF( pNxtSct ); 726 pPrv = NULL; 727 if( pPrvSct && !( pPrvSct->GetFmt() == pParent ) ) 728 pPrvSct = NULL; // damit nicht gemergt wird 729 } 730 else if( pPrvSct && pPrvSct->GetFmt() == pParent ) 731 { // Wunderbar, hier koennen wir uns am Ende einfuegen 732 pUp = pPrvSct; 733 if( pUp->Lower() && pUp->Lower()->IsColumnFrm() ) 734 { 735 pUp = static_cast<SwLayoutFrm*>(pUp->GetLastLower()); 736 // Der Body der letzten Spalte 737 pUp = static_cast<SwLayoutFrm*>(pUp->Lower()); 738 } 739 // damit hinter dem letzten eingefuegt wird 740 pPrv = pUp->GetLastLower(); 741 pPrvSct = NULL; // damit nicht gemergt wird 742 } 743 else 744 { 745 if( pSave ) 746 { // Folgende Situationen: Vor und hinter dem zu loeschenden Bereich 747 // ist entweder die Bereichsgrenze des umfassenden Bereichs oder 748 // es schliesst ein anderer (Geschwister-)Bereich direkt an, der 749 // vom gleichen Parent abgeleitet ist. 750 // Dann gibt es (noch) keinen Teil unseres Parents, der den Inhalt 751 // aufnehmen kann,also bauen wir ihn uns. 752 pPrvSct = new SwSectionFrm( *pParent->GetSection(), pUp ); 753 pPrvSct->InsertBehind( pUp, pPrv ); 754 pPrvSct->Init(); 755 SWRECTFN( pUp ) 756 (pPrvSct->*fnRect->fnMakePos)( pUp, pPrv, sal_True ); 757 pUp = FIRSTLEAF( pPrvSct ); 758 pPrv = NULL; 759 } 760 pPrvSct = NULL; // damit nicht gemergt wird 761 } 762 } 763 // Der Inhalt wird eingefuegt.. 764 if( pSave ) 765 { 766 lcl_InvalidateInfFlags( pSave, bSize ); 767 ::RestoreCntnt( pSave, pUp, pPrv, true ); 768 pUp->FindPageFrm()->InvalidateCntnt(); 769 if( !bOldFtn ) 770 ((SwFtnFrm*)pUp)->ColUnlock(); 771 } 772 // jetzt koennen eventuell zwei Teile des uebergeordneten Bereich verschmelzen 773 if( pPrvSct && !pPrvSct->IsJoinLocked() ) 774 { 775 ASSERT( pNxtSct, "MoveCntnt: No Merge" ); 776 pPrvSct->MergeNext( pNxtSct ); 777 } 778 } 779 780 void SwSectionFrm::MakeAll() 781 { 782 if ( IsJoinLocked() || IsColLocked() || StackHack::IsLocked() || StackHack::Count() > 50 ) 783 return; 784 if( !pSection ) // Durch DelEmpty 785 { 786 ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" ); 787 if( !bValidPos ) 788 { 789 if( GetUpper() ) 790 { 791 SWRECTFN( GetUpper() ) 792 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False ); 793 } 794 } 795 bValidSize = bValidPos = bValidPrtArea = sal_True; 796 return; 797 } 798 LockJoin(); //Ich lass mich nicht unterwegs vernichten. 799 800 while( GetNext() && GetNext() == GetFollow() ) 801 { 802 const SwFrm* pFoll = GetFollow(); 803 MergeNext( (SwSectionFrm*)GetNext() ); 804 if( pFoll == GetFollow() ) 805 break; 806 } 807 808 // OD 2004-03-15 #116561# - In online layout join the follows, if section 809 // can grow. 810 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 811 if( pSh && pSh->GetViewOptions()->getBrowseMode() && 812 ( Grow( LONG_MAX, true ) > 0 ) ) 813 { 814 while( GetFollow() ) 815 { 816 const SwFrm* pFoll = GetFollow(); 817 MergeNext( GetFollow() ); 818 if( pFoll == GetFollow() ) 819 break; 820 } 821 } 822 823 // Ein Bereich mit Follow nimmt allen Platz bis zur Unterkante des Uppers 824 // in Anspruch. Bewegt er sich, so kann seine Groesse zu- oder abnehmen... 825 if( !bValidPos && ToMaximize( sal_False ) ) 826 bValidSize = sal_False; 827 828 #if OSL_DEBUG_LEVEL > 1 829 const SwFmtCol &rCol = GetFmt()->GetCol(); 830 (void)rCol; 831 #endif 832 SwLayoutFrm::MakeAll(); 833 UnlockJoin(); 834 if( pSection && IsSuperfluous() ) 835 DelEmpty( sal_False ); 836 } 837 838 sal_Bool SwSectionFrm::ShouldBwdMoved( SwLayoutFrm *, sal_Bool , sal_Bool & ) 839 { 840 ASSERT( sal_False, "Hups, wo ist meine Tarnkappe?" ); 841 return sal_False; 842 } 843 844 const SwSectionFmt* SwSectionFrm::_GetEndSectFmt() const 845 { 846 const SwSectionFmt *pFmt = pSection->GetFmt(); 847 while( !pFmt->GetEndAtTxtEnd().IsAtEnd() ) 848 { 849 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) ) 850 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn(); 851 else 852 return NULL; 853 } 854 return pFmt; 855 } 856 857 void lcl_FindCntntFrm( SwCntntFrm* &rpCntntFrm, SwFtnFrm* &rpFtnFrm, 858 SwFrm* pFrm, sal_Bool &rbChkFtn ) 859 { 860 if( pFrm ) 861 { 862 while( pFrm->GetNext() ) 863 pFrm = pFrm->GetNext(); 864 while( !rpCntntFrm && pFrm ) 865 { 866 if( pFrm->IsCntntFrm() ) 867 rpCntntFrm = (SwCntntFrm*)pFrm; 868 else if( pFrm->IsLayoutFrm() ) 869 { 870 if( pFrm->IsFtnFrm() ) 871 { 872 if( rbChkFtn ) 873 { 874 rpFtnFrm = (SwFtnFrm*)pFrm; 875 rbChkFtn = rpFtnFrm->GetAttr()->GetFtn().IsEndNote(); 876 } 877 } 878 else 879 lcl_FindCntntFrm( rpCntntFrm, rpFtnFrm, 880 ((SwLayoutFrm*)pFrm)->Lower(), rbChkFtn ); 881 } 882 pFrm = pFrm->GetPrev(); 883 } 884 } 885 } 886 887 SwCntntFrm *SwSectionFrm::FindLastCntnt( sal_uInt8 nMode ) 888 { 889 SwCntntFrm *pRet = NULL; 890 SwFtnFrm *pFtnFrm = NULL; 891 SwSectionFrm *pSect = this; 892 if( nMode ) 893 { 894 const SwSectionFmt *pFmt = IsEndnAtEnd() ? GetEndSectFmt() : 895 pSection->GetFmt(); 896 do { 897 while( pSect->HasFollow() ) 898 pSect = pSect->GetFollow(); 899 SwFrm* pTmp = pSect->FindNext(); 900 while( pTmp && pTmp->IsSctFrm() && 901 !((SwSectionFrm*)pTmp)->GetSection() ) 902 pTmp = pTmp->FindNext(); 903 if( pTmp && pTmp->IsSctFrm() && 904 ((SwSectionFrm*)pTmp)->IsDescendantFrom( pFmt ) ) 905 pSect = (SwSectionFrm*)pTmp; 906 else 907 break; 908 } while( sal_True ); 909 } 910 sal_Bool bFtnFound = nMode == FINDMODE_ENDNOTE; 911 do 912 { 913 lcl_FindCntntFrm( pRet, pFtnFrm, pSect->Lower(), bFtnFound ); 914 if( pRet || !pSect->IsFollow() || !nMode || 915 ( FINDMODE_MYLAST == nMode && this == pSect ) ) 916 break; 917 pSect = pSect->FindMaster(); 918 } while( pSect ); 919 if( ( nMode == FINDMODE_ENDNOTE ) && pFtnFrm ) 920 pRet = pFtnFrm->ContainsCntnt(); 921 return pRet; 922 } 923 924 sal_Bool SwSectionFrm::CalcMinDiff( SwTwips& rMinDiff ) const 925 { 926 if( ToMaximize( sal_True ) ) 927 { 928 SWRECTFN( this ) 929 rMinDiff = (GetUpper()->*fnRect->fnGetPrtBottom)(); 930 rMinDiff = (Frm().*fnRect->fnBottomDist)( rMinDiff ); 931 return sal_True; 932 } 933 return sal_False; 934 } 935 936 /************************************************************************* 937 * 938 * SwSectionFrm::CollectEndnotes( ) 939 * 940 * Ersterstellung AMA 03. Nov 99 941 * Letzte Aenderung AMA 03. Nov 99 942 * 943 * CollectEndnotes looks for endnotes in the sectionfrm and his follows, 944 * the endnotes will cut off the layout and put into the array. 945 * If the first endnote is not a master-SwFtnFrm, the whole sectionfrm 946 * contains only endnotes and it is not necessary to collect them. 947 * 948 *************************************************************************/ 949 950 SwFtnFrm* lcl_FindEndnote( SwSectionFrm* &rpSect, sal_Bool &rbEmpty, 951 SwLayouter *pLayouter ) 952 { 953 // if rEmpty is set, the rpSect is already searched 954 SwSectionFrm* pSect = rbEmpty ? rpSect->GetFollow() : rpSect; 955 while( pSect ) 956 { 957 ASSERT( (pSect->Lower() && pSect->Lower()->IsColumnFrm()) || pSect->GetUpper()->IsFtnFrm(), 958 "InsertEndnotes: Where's my column?" ); 959 960 // i73332: Columned section in endnote 961 SwColumnFrm* pCol = 0; 962 if(pSect->Lower() && pSect->Lower()->IsColumnFrm()) 963 pCol = (SwColumnFrm*)pSect->Lower(); 964 965 while( pCol ) // check all columns 966 { 967 SwFtnContFrm* pFtnCont = pCol->FindFtnCont(); 968 if( pFtnCont ) 969 { 970 SwFtnFrm* pRet = (SwFtnFrm*)pFtnCont->Lower(); 971 while( pRet ) // look for endnotes 972 { 973 if( pRet->GetAttr()->GetFtn().IsEndNote() ) 974 { 975 if( pRet->GetMaster() ) 976 { 977 if( pLayouter ) 978 pLayouter->CollectEndnote( pRet ); 979 else 980 return 0; 981 } 982 else 983 return pRet; // Found 984 } 985 pRet = (SwFtnFrm*)pRet->GetNext(); 986 } 987 } 988 pCol = (SwColumnFrm*)pCol->GetNext(); 989 } 990 rpSect = pSect; 991 pSect = pLayouter ? pSect->GetFollow() : NULL; 992 rbEmpty = sal_True; 993 } 994 return NULL; 995 } 996 997 void lcl_ColumnRefresh( SwSectionFrm* pSect, sal_Bool bFollow ) 998 { 999 while( pSect ) 1000 { 1001 sal_Bool bOldLock = pSect->IsColLocked(); 1002 pSect->ColLock(); 1003 if( pSect->Lower() && pSect->Lower()->IsColumnFrm() ) 1004 { 1005 SwColumnFrm *pCol = (SwColumnFrm*)pSect->Lower(); 1006 do 1007 { pCol->_InvalidateSize(); 1008 pCol->_InvalidatePos(); 1009 ((SwLayoutFrm*)pCol)->Lower()->_InvalidateSize(); 1010 pCol->Calc(); // calculation of column and 1011 ((SwLayoutFrm*)pCol)->Lower()->Calc(); // body 1012 pCol = (SwColumnFrm*)pCol->GetNext(); 1013 } while ( pCol ); 1014 } 1015 if( !bOldLock ) 1016 pSect->ColUnlock(); 1017 if( bFollow ) 1018 pSect = pSect->GetFollow(); 1019 else 1020 pSect = NULL; 1021 } 1022 } 1023 1024 void SwSectionFrm::CollectEndnotes( SwLayouter* pLayouter ) 1025 { 1026 ASSERT( IsColLocked(), "CollectEndnotes: You love the risk?" ); 1027 // i73332: Section in footnode does not have columns! 1028 ASSERT( (Lower() && Lower()->IsColumnFrm()) || GetUpper()->IsFtnFrm(), "Where's my column?" ); 1029 1030 SwSectionFrm* pSect = this; 1031 SwFtnFrm* pFtn; 1032 sal_Bool bEmpty = sal_False; 1033 // pSect is the last sectionfrm without endnotes or the this-pointer 1034 // the first sectionfrm with endnotes may be destroyed, when the endnotes 1035 // is cutted 1036 while( 0 != (pFtn = lcl_FindEndnote( pSect, bEmpty, pLayouter )) ) 1037 pLayouter->CollectEndnote( pFtn ); 1038 if( pLayouter->HasEndnotes() ) 1039 lcl_ColumnRefresh( this, sal_True ); 1040 } 1041 1042 /************************************************************************* 1043 |* 1044 |* SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize ) 1045 |* 1046 |* Beschreibung: Passt die Groesse an die Umgebung an. 1047 |* Wer einen Follow oder Fussnoten besitzt, soll bis zur Unterkante 1048 |* des Uppers gehen (bMaximize). 1049 |* Niemand darf ueber den Upper hinausgehen, ggf. darf man versuchen (bGrow) 1050 |* seinen Upper zu growen. 1051 |* Wenn die Groesse veraendert werden musste, wird der Inhalt kalkuliert. 1052 |* 1053 |*************************************************************************/ 1054 1055 /// OD 18.09.2002 #100522# 1056 /// perform calculation of content, only if height has changed. 1057 void SwSectionFrm::_CheckClipping( sal_Bool bGrow, sal_Bool bMaximize ) 1058 { 1059 SWRECTFN( this ) 1060 long nDiff; 1061 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)(); 1062 if( bGrow && ( !IsInFly() || !GetUpper()->IsColBodyFrm() || 1063 !FindFlyFrm()->IsLocked() ) ) 1064 { 1065 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine ); 1066 if( !bMaximize ) 1067 nDiff += Undersize(); 1068 if( nDiff > 0 ) 1069 { 1070 long nAdd = GetUpper()->Grow( nDiff ); 1071 if( bVert && !bRev ) 1072 nDeadLine -= nAdd; 1073 else 1074 nDeadLine += nAdd; 1075 } 1076 } 1077 nDiff = -(Frm().*fnRect->fnBottomDist)( nDeadLine ); 1078 SetUndersized( !bMaximize && nDiff >= 0 ); 1079 const bool bCalc = ( IsUndersized() || bMaximize ) && 1080 ( nDiff || 1081 (Prt().*fnRect->fnGetTop)() > (Frm().*fnRect->fnGetHeight)() ); 1082 // OD 03.11.2003 #i19737# - introduce local variable <bExtraCalc> to indicate 1083 // that a calculation has to be done beside the value of <bCalc>. 1084 bool bExtraCalc = false; 1085 if( !bCalc && !bGrow && IsAnyNoteAtEnd() && !IsInFtn() ) 1086 { 1087 SwSectionFrm *pSect = this; 1088 sal_Bool bEmpty = sal_False; 1089 SwLayoutFrm* pFtn = IsEndnAtEnd() ? 1090 lcl_FindEndnote( pSect, bEmpty, NULL ) : NULL; 1091 if( pFtn ) 1092 { 1093 pFtn = pFtn->FindFtnBossFrm(); 1094 SwFrm* pTmp = FindLastCntnt( FINDMODE_LASTCNT ); 1095 // OD 08.11.2002 #104840# - use <SwLayoutFrm::IsBefore(..)> 1096 if ( pTmp && pFtn->IsBefore( pTmp->FindFtnBossFrm() ) ) 1097 bExtraCalc = true; 1098 } 1099 else if( GetFollow() && !GetFollow()->ContainsAny() ) 1100 bExtraCalc = true; 1101 } 1102 if ( bCalc || bExtraCalc ) 1103 { 1104 nDiff = (*fnRect->fnYDiff)( nDeadLine, (Frm().*fnRect->fnGetTop)() ); 1105 if( nDiff < 0 ) 1106 { 1107 nDiff = 0; 1108 nDeadLine = (Frm().*fnRect->fnGetTop)(); 1109 } 1110 const Size aOldSz( Prt().SSize() ); 1111 long nTop = (this->*fnRect->fnGetTopMargin)(); 1112 (Frm().*fnRect->fnSetBottom)( nDeadLine ); 1113 nDiff = (Frm().*fnRect->fnGetHeight)(); 1114 if( nTop > nDiff ) 1115 nTop = nDiff; 1116 (this->*fnRect->fnSetYMargins)( nTop, 0 ); 1117 1118 // OD 18.09.2002 #100522# 1119 // Determine, if height has changed. 1120 // Note: In vertical layout the height equals the width value. 1121 bool bHeightChanged = bVert ? 1122 (aOldSz.Width() != Prt().Width()) : 1123 (aOldSz.Height() != Prt().Height()); 1124 // Wir haben zu guter Letzt noch einmal die Hoehe geaendert, 1125 // dann wird das innere Layout (Columns) kalkuliert und 1126 // der Inhalt ebenfalls. 1127 // OD 18.09.2002 #100522# 1128 // calculate content, only if height has changed. 1129 // OD 03.11.2003 #i19737# - restriction of content calculation too strong. 1130 // If an endnote has an incorrect position or a follow section contains 1131 // no content except footnotes/endnotes, the content has also been calculated. 1132 if ( ( bHeightChanged || bExtraCalc ) && Lower() ) 1133 { 1134 if( Lower()->IsColumnFrm() ) 1135 { 1136 lcl_ColumnRefresh( this, sal_False ); 1137 ::CalcCntnt( this ); 1138 } 1139 else 1140 { 1141 ChgLowersProp( aOldSz ); 1142 if( !bMaximize && !IsCntntLocked() ) 1143 ::CalcCntnt( this ); 1144 } 1145 } 1146 } 1147 } 1148 1149 void SwSectionFrm::SimpleFormat() 1150 { 1151 if ( IsJoinLocked() || IsColLocked() ) 1152 return; 1153 // ASSERT( pFollow, "SimpleFormat: Follow required" ); 1154 LockJoin(); 1155 SWRECTFN( this ) 1156 if( GetPrev() || GetUpper() ) 1157 { 1158 // --> OD 2009-09-28 #b6882166# 1159 // assure notifications on position changes. 1160 const SwLayNotify aNotify( this ); 1161 // <-- 1162 (this->*fnRect->fnMakePos)( GetUpper(), GetPrev(), sal_False ); 1163 bValidPos = sal_True; 1164 } 1165 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)(); 1166 // OD 22.10.2002 #97265# - call always method <lcl_ColumnRefresh(..)>, in 1167 // order to get calculated lowers, not only if there space left in its upper. 1168 if( (Frm().*fnRect->fnBottomDist)( nDeadLine ) >= 0 ) 1169 { 1170 (Frm().*fnRect->fnSetBottom)( nDeadLine ); 1171 long nHeight = (Frm().*fnRect->fnGetHeight)(); 1172 long nTop = CalcUpperSpace(); 1173 if( nTop > nHeight ) 1174 nTop = nHeight; 1175 (this->*fnRect->fnSetYMargins)( nTop, 0 ); 1176 } 1177 lcl_ColumnRefresh( this, sal_False ); 1178 UnlockJoin(); 1179 } 1180 1181 // --> OD 2005-01-11 #i40147# - helper class to perform extra section format 1182 // to position anchored objects and to keep the position of whose objects locked. 1183 class ExtraFormatToPositionObjs 1184 { 1185 private: 1186 SwSectionFrm* mpSectFrm; 1187 bool mbExtraFormatPerformed; 1188 1189 public: 1190 ExtraFormatToPositionObjs( SwSectionFrm& _rSectFrm) 1191 : mpSectFrm( &_rSectFrm ), 1192 mbExtraFormatPerformed( false ) 1193 {} 1194 1195 ~ExtraFormatToPositionObjs() 1196 { 1197 if ( mbExtraFormatPerformed ) 1198 { 1199 // release keep locked position of lower floating screen objects 1200 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm(); 1201 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L; 1202 if ( pObjs ) 1203 { 1204 sal_uInt32 i = 0; 1205 for ( i = 0; i < pObjs->Count(); ++i ) 1206 { 1207 SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 1208 1209 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) ) 1210 { 1211 pAnchoredObj->SetKeepPosLocked( false ); 1212 } 1213 } 1214 } 1215 } 1216 } 1217 1218 // --> OD 2008-06-20 #i81555# 1219 void InitObjs( SwFrm& rFrm ) 1220 { 1221 SwSortedObjs* pObjs = rFrm.GetDrawObjs(); 1222 if ( pObjs ) 1223 { 1224 sal_uInt32 i = 0; 1225 for ( i = 0; i < pObjs->Count(); ++i ) 1226 { 1227 SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 1228 1229 pAnchoredObj->UnlockPosition(); 1230 pAnchoredObj->SetClearedEnvironment( false ); 1231 } 1232 } 1233 SwLayoutFrm* pLayoutFrm = dynamic_cast<SwLayoutFrm*>(&rFrm); 1234 if ( pLayoutFrm != 0 ) 1235 { 1236 SwFrm* pLowerFrm = pLayoutFrm->GetLower(); 1237 while ( pLowerFrm != 0 ) 1238 { 1239 InitObjs( *pLowerFrm ); 1240 1241 pLowerFrm = pLowerFrm->GetNext(); 1242 } 1243 } 1244 } 1245 // <-- 1246 1247 void FormatSectionToPositionObjs() 1248 { 1249 // perform extra format for multi-columned section. 1250 if ( mpSectFrm->Lower() && mpSectFrm->Lower()->IsColumnFrm() && 1251 mpSectFrm->Lower()->GetNext() ) 1252 { 1253 // grow section till bottom of printing area of upper frame 1254 SWRECTFN( mpSectFrm ); 1255 SwTwips nTopMargin = (mpSectFrm->*fnRect->fnGetTopMargin)(); 1256 Size aOldSectPrtSize( mpSectFrm->Prt().SSize() ); 1257 SwTwips nDiff = (mpSectFrm->Frm().*fnRect->fnBottomDist)( 1258 (mpSectFrm->GetUpper()->*fnRect->fnGetPrtBottom)() ); 1259 (mpSectFrm->Frm().*fnRect->fnAddBottom)( nDiff ); 1260 (mpSectFrm->*fnRect->fnSetYMargins)( nTopMargin, 0 ); 1261 // --> OD 2006-05-08 #i59789# 1262 // suppress formatting, if printing area of section is too narrow 1263 if ( (mpSectFrm->Prt().*fnRect->fnGetHeight)() <= 0 ) 1264 { 1265 return; 1266 } 1267 // <-- 1268 mpSectFrm->ChgLowersProp( aOldSectPrtSize ); 1269 1270 // format column frames and its body and footnote container 1271 SwColumnFrm* pColFrm = static_cast<SwColumnFrm*>(mpSectFrm->Lower()); 1272 while ( pColFrm ) 1273 { 1274 pColFrm->Calc(); 1275 pColFrm->Lower()->Calc(); 1276 if ( pColFrm->Lower()->GetNext() ) 1277 { 1278 pColFrm->Lower()->GetNext()->Calc(); 1279 } 1280 1281 pColFrm = static_cast<SwColumnFrm*>(pColFrm->GetNext()); 1282 } 1283 1284 // unlock position of lower floating screen objects for the extra format 1285 // --> OD 2008-06-20 #i81555# 1286 // Section frame can already have changed the page and its content 1287 // can still be on the former page. 1288 // Thus, initialize objects via lower-relationship 1289 InitObjs( *mpSectFrm ); 1290 // <-- 1291 1292 // format content - first with collecting its foot-/endnotes before content 1293 // format, second without collecting its foot-/endnotes. 1294 ::CalcCntnt( mpSectFrm ); 1295 ::CalcCntnt( mpSectFrm, true ); 1296 1297 // keep locked position of lower floating screen objects 1298 SwPageFrm* pPageFrm = mpSectFrm->FindPageFrm(); 1299 SwSortedObjs* pObjs = pPageFrm ? pPageFrm->GetSortedObjs() : 0L; 1300 if ( pObjs ) 1301 { 1302 sal_uInt32 i = 0; 1303 for ( i = 0; i < pObjs->Count(); ++i ) 1304 { 1305 SwAnchoredObject* pAnchoredObj = (*pObjs)[i]; 1306 1307 if ( mpSectFrm->IsAnLower( pAnchoredObj->GetAnchorFrm() ) ) 1308 { 1309 pAnchoredObj->SetKeepPosLocked( true ); 1310 } 1311 } 1312 } 1313 1314 mbExtraFormatPerformed = true; 1315 } 1316 } 1317 }; 1318 1319 /************************************************************************* 1320 |* 1321 |* SwSectionFrm::Format() 1322 |* 1323 |* Beschreibung: "Formatiert" den Frame; Frm und PrtArea. 1324 |* Ersterstellung AMA 03. Dec. 97 1325 |* Letzte Aenderung MA 09. Oct. 98 1326 |* 1327 |*************************************************************************/ 1328 1329 void SwSectionFrm::Format( const SwBorderAttrs *pAttr ) 1330 { 1331 if( !pSection ) // Durch DelEmpty 1332 { 1333 ASSERT( getRootFrm()->IsInDelList( this ), "SectionFrm without Section" ); 1334 bValidSize = bValidPos = bValidPrtArea = sal_True; 1335 return; 1336 } 1337 SWRECTFN( this ) 1338 if ( !bValidPrtArea ) 1339 { 1340 PROTOCOL( this, PROT_PRTAREA, 0, 0 ) 1341 bValidPrtArea = sal_True; 1342 SwTwips nUpper = CalcUpperSpace(); 1343 1344 // #109700# LRSpace for sections 1345 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace(); 1346 (this->*fnRect->fnSetXMargins)( rLRSpace.GetLeft(), rLRSpace.GetRight() ); 1347 1348 if( nUpper != (this->*fnRect->fnGetTopMargin)() ) 1349 { 1350 bValidSize = sal_False; 1351 SwFrm* pOwn = ContainsAny(); 1352 if( pOwn ) 1353 pOwn->_InvalidatePos(); 1354 } 1355 (this->*fnRect->fnSetYMargins)( nUpper, 0 ); 1356 } 1357 1358 if ( !bValidSize ) 1359 { 1360 PROTOCOL_ENTER( this, PROT_SIZE, 0, 0 ) 1361 const long nOldHeight = (Frm().*fnRect->fnGetHeight)(); 1362 sal_Bool bOldLock = IsColLocked(); 1363 ColLock(); 1364 1365 bValidSize = sal_True; 1366 1367 //die Groesse wird nur dann vom Inhalt bestimmt, wenn der SectFrm 1368 //keinen Follow hat. Anderfalls fuellt er immer den Upper bis 1369 //zur Unterkante aus. Fuer den Textfluss ist nicht er, sondern sein 1370 //Inhalt selbst verantwortlich. 1371 sal_Bool bMaximize = ToMaximize( sal_False ); 1372 1373 // OD 2004-05-17 #i28701# - If the wrapping style has to be considered 1374 // on object positioning, an extra formatting has to be performed 1375 // to determine the correct positions the floating screen objects. 1376 // --> OD 2005-01-11 #i40147# 1377 // use new helper class <ExtraFormatToPositionObjs>. 1378 // This class additionally keep the locked position of the objects 1379 // and releases this position lock keeping on destruction. 1380 ExtraFormatToPositionObjs aExtraFormatToPosObjs( *this ); 1381 if ( !bMaximize && 1382 GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) && 1383 !GetFmt()->GetBalancedColumns().GetValue() ) 1384 { 1385 aExtraFormatToPosObjs.FormatSectionToPositionObjs(); 1386 } 1387 // <-- 1388 1389 // Column widths have to be adjusted before calling _CheckClipping. 1390 // _CheckClipping can cause the formatting of the lower frames 1391 // which still have a width of 0. 1392 const sal_Bool bHasColumns = Lower() && Lower()->IsColumnFrm(); 1393 if ( bHasColumns && Lower()->GetNext() ) 1394 AdjustColumns( 0, sal_False ); 1395 1396 if( GetUpper() ) 1397 { 1398 long nWidth = (GetUpper()->Prt().*fnRect->fnGetWidth)(); 1399 (aFrm.*fnRect->fnSetWidth)( nWidth ); 1400 1401 // #109700# LRSpace for sections 1402 const SvxLRSpaceItem& rLRSpace = GetFmt()->GetLRSpace(); 1403 (aPrt.*fnRect->fnSetWidth)( nWidth - rLRSpace.GetLeft() - 1404 rLRSpace.GetRight() ); 1405 1406 // OD 15.10.2002 #103517# - allow grow in online layout 1407 // Thus, set <..IsBrowseMode()> as parameter <bGrow> on calling 1408 // method <_CheckClipping(..)>. 1409 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 1410 _CheckClipping( pSh && pSh->GetViewOptions()->getBrowseMode(), bMaximize ); 1411 bMaximize = ToMaximize( sal_False ); 1412 bValidSize = sal_True; 1413 } 1414 1415 //Breite der Spalten pruefen und ggf. einstellen. 1416 if ( bHasColumns && ! Lower()->GetNext() && bMaximize ) 1417 ((SwColumnFrm*)Lower())->Lower()->Calc(); 1418 1419 if ( !bMaximize ) 1420 { 1421 SwTwips nRemaining = (this->*fnRect->fnGetTopMargin)(); 1422 SwFrm *pFrm = pLower; 1423 if( pFrm ) 1424 { 1425 if( pFrm->IsColumnFrm() && pFrm->GetNext() ) 1426 { 1427 // --> OD 2006-05-08 #i61435# 1428 // suppress formatting, if upper frame has height <= 0 1429 if ( (GetUpper()->Frm().*fnRect->fnGetHeight)() > 0 ) 1430 { 1431 FormatWidthCols( *pAttr, nRemaining, MINLAY ); 1432 } 1433 // <-- 1434 // --> OD 2006-01-04 #126020# - adjust check for empty section 1435 // --> OD 2006-02-01 #130797# - correct fix #126020# 1436 while( HasFollow() && !GetFollow()->ContainsCntnt() && 1437 !GetFollow()->ContainsAny( true ) ) 1438 // <-- 1439 { 1440 SwFrm* pOld = GetFollow(); 1441 GetFollow()->DelEmpty( sal_False ); 1442 if( pOld == GetFollow() ) 1443 break; 1444 } 1445 bMaximize = ToMaximize( sal_False ); 1446 nRemaining += (pFrm->Frm().*fnRect->fnGetHeight)(); 1447 } 1448 else 1449 { 1450 if( pFrm->IsColumnFrm() ) 1451 { 1452 pFrm->Calc(); 1453 pFrm = ((SwColumnFrm*)pFrm)->Lower(); 1454 pFrm->Calc(); 1455 pFrm = ((SwLayoutFrm*)pFrm)->Lower(); 1456 CalcFtnCntnt(); 1457 } 1458 // Wenn wir in einem spaltigen Rahmen stehen und dieser 1459 // gerade im FormatWidthCols ein CalcCntnt ruft, muss 1460 // unser Inhalt ggf. kalkuliert werden. 1461 if( pFrm && !pFrm->IsValid() && IsInFly() && 1462 FindFlyFrm()->IsColLocked() ) 1463 ::CalcCntnt( this ); 1464 nRemaining += InnerHeight(); 1465 bMaximize = HasFollow(); 1466 } 1467 } 1468 1469 SwTwips nDiff = (Frm().*fnRect->fnGetHeight)() - nRemaining; 1470 if( nDiff < 0) 1471 { 1472 SwTwips nDeadLine = (GetUpper()->*fnRect->fnGetPrtBottom)(); 1473 { 1474 long nBottom = (Frm().*fnRect->fnGetBottom)(); 1475 nBottom = (*fnRect->fnYInc)( nBottom, -nDiff ); 1476 long nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine ); 1477 if( nTmpDiff > 0 ) 1478 { 1479 nTmpDiff = GetUpper()->Grow( nTmpDiff, sal_True ); 1480 nDeadLine = (*fnRect->fnYInc)( nDeadLine, nTmpDiff ); 1481 nTmpDiff = (*fnRect->fnYDiff)( nBottom, nDeadLine ); 1482 if( nTmpDiff > 0 ) 1483 nDiff += nTmpDiff; 1484 if( nDiff > 0 ) 1485 nDiff = 0; 1486 } 1487 } 1488 } 1489 if( nDiff ) 1490 { 1491 long nTmp = nRemaining - (Frm().*fnRect->fnGetHeight)(); 1492 long nTop = (this->*fnRect->fnGetTopMargin)(); 1493 (Frm().*fnRect->fnAddBottom)( nTmp ); 1494 (this->*fnRect->fnSetYMargins)( nTop, 0 ); 1495 InvalidateNextPos(); 1496 if( pLower && ( !pLower->IsColumnFrm() || !pLower->GetNext() ) ) 1497 { 1498 // Wenn ein einspaltiger Bereich gerade den Platz geschaffen 1499 // hat, den sich die "undersized" Absaetze gewuenscht haben, 1500 // muessen diese invalidiert und kalkuliert werden, damit 1501 // sie diesen ausfuellen. 1502 pFrm = pLower; 1503 if( pFrm->IsColumnFrm() ) 1504 { 1505 pFrm->_InvalidateSize(); 1506 pFrm->_InvalidatePos(); 1507 pFrm->Calc(); 1508 pFrm = ((SwColumnFrm*)pFrm)->Lower(); 1509 pFrm->Calc(); 1510 pFrm = ((SwLayoutFrm*)pFrm)->Lower(); 1511 CalcFtnCntnt(); 1512 } 1513 sal_Bool bUnderSz = sal_False; 1514 while( pFrm ) 1515 { 1516 if( pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsUndersized() ) 1517 { 1518 pFrm->Prepare( PREP_ADJUST_FRM ); 1519 bUnderSz = sal_True; 1520 } 1521 pFrm = pFrm->GetNext(); 1522 } 1523 if( bUnderSz && !IsCntntLocked() ) 1524 ::CalcCntnt( this ); 1525 } 1526 } 1527 } 1528 1529 //Unterkante des Uppers nicht ueberschreiten. Fuer Sections mit 1530 //Follows die Unterkante auch nicht unterschreiten. 1531 if ( GetUpper() ) 1532 _CheckClipping( sal_True, bMaximize ); 1533 if( !bOldLock ) 1534 ColUnlock(); 1535 long nDiff = nOldHeight - (Frm().*fnRect->fnGetHeight)(); 1536 if( nDiff > 0 ) 1537 { 1538 if( !GetNext() ) 1539 SetRetouche(); // Dann muessen wir die Retusche selbst uebernehmen 1540 if( GetUpper() && !GetUpper()->IsFooterFrm() ) 1541 GetUpper()->Shrink( nDiff ); 1542 } 1543 if( IsUndersized() ) 1544 bValidPrtArea = sal_True; 1545 } 1546 } 1547 1548 /************************************************************************* 1549 |* 1550 |* SwFrm::GetNextSctLeaf() 1551 |* 1552 |* Beschreibung Liefert das naechste Layoutblatt in das der Frame 1553 |* gemoved werden kann. 1554 |* Neue Seiten werden nur dann erzeugt, wenn der Parameter sal_True ist. 1555 |* Ersterstellung AMA 07. Jan. 98 1556 |* Letzte Aenderung AMA 07. Jan. 98 1557 |* 1558 |*************************************************************************/ 1559 1560 1561 SwLayoutFrm *SwFrm::GetNextSctLeaf( MakePageType eMakePage ) 1562 { 1563 //Achtung: Geschachtelte Bereiche werden zur Zeit nicht unterstuetzt. 1564 1565 PROTOCOL_ENTER( this, PROT_LEAF, ACT_NEXT_SECT, GetUpper()->FindSctFrm() ) 1566 1567 // Abkuerzungen fuer spaltige Bereiche, wenn wir noch nicht in der letzten Spalte sind. 1568 // Koennen wir in die naechste Spalte des Bereichs rutschen? 1569 if( IsColBodyFrm() && GetUpper()->GetNext() ) 1570 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetNext())->Lower(); 1571 if( GetUpper()->IsColBodyFrm() && GetUpper()->GetUpper()->GetNext() ) 1572 return (SwLayoutFrm*)((SwLayoutFrm*)GetUpper()->GetUpper()->GetNext())->Lower(); 1573 // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann 1574 // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette zuschlagen muessen 1575 if( GetUpper()->IsInTab() || FindFooterOrHeader() ) 1576 return 0; 1577 1578 //MA 03. Feb. 99: Warum GetUpper()? Das knallt mit Buch.sgl weil im 1579 //FlyAtCnt::MakeFlyPos ein Orient der SectionFrm ist und auf diesen ein 1580 //GetLeaf gerufen wird. 1581 // SwSectionFrm *pSect = GetUpper()->FindSctFrm(); 1582 SwSectionFrm *pSect = FindSctFrm(); 1583 sal_Bool bWrongPage = sal_False; 1584 ASSERT( pSect, "GetNextSctLeaf: Missing SectionFrm" ); 1585 1586 // Hier eine Abkuerzung fuer Bereiche mit Follows, 1587 // dieser kann akzeptiert werden, wenn keine Spalten oder Seiten (ausser Dummyseiten) 1588 // dazwischen liegen. 1589 // Bei verketteten Rahmen und ind Fussnoten wuerde die Abkuerzung noch aufwendiger 1590 if( pSect->HasFollow() && pSect->IsInDocBody() ) 1591 { 1592 if( pSect->GetFollow() == pSect->GetNext() ) 1593 { 1594 SwPageFrm *pPg = pSect->GetFollow()->FindPageFrm(); 1595 if( WrongPageDesc( pPg ) ) 1596 bWrongPage = sal_True; 1597 else 1598 return FIRSTLEAF( pSect->GetFollow() ); 1599 } 1600 else 1601 { 1602 SwFrm* pTmp; 1603 if( !pSect->GetUpper()->IsColBodyFrm() || 1604 0 == ( pTmp = pSect->GetUpper()->GetUpper()->GetNext() ) ) 1605 pTmp = pSect->FindPageFrm()->GetNext(); 1606 if( pTmp ) // ist jetzt die naechste Spalte oder Seite 1607 { 1608 SwFrm* pTmpX = pTmp; 1609 if( pTmp->IsPageFrm() && ((SwPageFrm*)pTmp)->IsEmptyPage() ) 1610 pTmp = pTmp->GetNext(); // Dummyseiten ueberspringen 1611 SwFrm *pUp = pSect->GetFollow()->GetUpper(); 1612 // pUp wird die Spalte, wenn der Follow in einer "nicht ersten" Spalte 1613 // liegt, ansonsten die Seite: 1614 if( !pUp->IsColBodyFrm() || 1615 !( pUp = pUp->GetUpper() )->GetPrev() ) 1616 pUp = pUp->FindPageFrm(); 1617 // Jetzt muessen pUp und pTmp die gleiche Seite/Spalte sein, 1618 // sonst liegen Seiten oder Spalten zwischen Master und Follow. 1619 if( pUp == pTmp || pUp->GetNext() == pTmpX ) 1620 { 1621 SwPageFrm* pNxtPg = pUp->IsPageFrm() ? 1622 (SwPageFrm*)pUp : pUp->FindPageFrm(); 1623 if( WrongPageDesc( pNxtPg ) ) 1624 bWrongPage = sal_True; 1625 else 1626 return FIRSTLEAF( pSect->GetFollow() ); 1627 } 1628 } 1629 } 1630 } 1631 1632 // Immer im gleichen Bereich landen: Body wieder in Body etc. 1633 const sal_Bool bBody = IsInDocBody(); 1634 const sal_Bool bFtnPage = FindPageFrm()->IsFtnPage(); 1635 1636 SwLayoutFrm *pLayLeaf; 1637 // Eine Abkuerzung fuer TabFrms, damit nicht alle Zellen abgehuehnert werden 1638 if( bWrongPage ) 1639 pLayLeaf = 0; 1640 else if( IsTabFrm() ) 1641 { 1642 SwCntntFrm* pTmpCnt = ((SwTabFrm*)this)->FindLastCntnt(); 1643 pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : 0; 1644 } 1645 else 1646 { 1647 pLayLeaf = GetNextLayoutLeaf(); 1648 if( IsColumnFrm() ) 1649 { 1650 while( pLayLeaf && ((SwColumnFrm*)this)->IsAnLower( pLayLeaf ) ) 1651 pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); 1652 } 1653 } 1654 1655 SwLayoutFrm *pOldLayLeaf = 0; //Damit bei neu erzeugten Seiten 1656 //nicht wieder vom Anfang gesucht 1657 //wird. 1658 1659 while( sal_True ) 1660 { 1661 if( pLayLeaf ) 1662 { 1663 // Ein Layoutblatt wurde gefunden, mal sehen, ob er mich aufnehmen kann, 1664 // ob hier ein weiterer SectionFrm eingefuegt werden kann 1665 // oder ob wir weitersuchen muessen. 1666 SwPageFrm* pNxtPg = pLayLeaf->FindPageFrm(); 1667 if ( !bFtnPage && pNxtPg->IsFtnPage() ) 1668 { //Wenn ich bei den Endnotenseiten angelangt bin hat sichs. 1669 pLayLeaf = 0; 1670 continue; 1671 } 1672 // Einmal InBody, immer InBody, nicht in Tabellen hinein 1673 // und nicht in fremde Bereiche hinein 1674 if ( (bBody && !pLayLeaf->IsInDocBody()) || 1675 (IsInFtn() != pLayLeaf->IsInFtn() ) || 1676 pLayLeaf->IsInTab() || 1677 ( pLayLeaf->IsInSct() && ( !pSect->HasFollow() 1678 || pSect->GetFollow() != pLayLeaf->FindSctFrm() ) ) ) 1679 { 1680 //Er will mich nicht; neuer Versuch, neues Glueck 1681 pOldLayLeaf = pLayLeaf; 1682 pLayLeaf = pLayLeaf->GetNextLayoutLeaf(); 1683 continue; 1684 } 1685 if( WrongPageDesc( pNxtPg ) ) 1686 { 1687 if( bWrongPage ) 1688 break; // there's a column between me and my right page 1689 pLayLeaf = 0; 1690 bWrongPage = sal_True; 1691 pOldLayLeaf = 0; 1692 continue; 1693 } 1694 } 1695 //Es gibt keinen passenden weiteren LayoutFrm, also muss eine 1696 //neue Seite her, allerdings nuetzen uns innerhalb eines Rahmens 1697 //neue Seiten nichts. 1698 else if( !pSect->IsInFly() && 1699 ( eMakePage == MAKEPAGE_APPEND || eMakePage == MAKEPAGE_INSERT ) ) 1700 { 1701 InsertPage(pOldLayLeaf ? pOldLayLeaf->FindPageFrm() : FindPageFrm(), 1702 sal_False ); 1703 //und nochmal das ganze 1704 pLayLeaf = pOldLayLeaf ? pOldLayLeaf : GetNextLayoutLeaf(); 1705 continue; 1706 } 1707 break; 1708 } 1709 1710 if( pLayLeaf ) 1711 { 1712 // Das passende Layoutblatt haben wir gefunden, wenn es dort bereits einen 1713 // Follow unseres Bereichs gibt, nehmen wir dessen erstes Layoutblatt, 1714 // andernfalls wird es Zeit, einen Bereichsfollow zu erzeugen 1715 SwSectionFrm* pNew; 1716 1717 //Dies kann entfallen, wenn bei existierenden Follows bereits abgekuerzt wurde 1718 SwFrm* pFirst = pLayLeaf->Lower(); 1719 // Auch hier muessen zum Loeschen angemeldete SectionFrms ignoriert werden 1720 while( pFirst && pFirst->IsSctFrm() && !((SwSectionFrm*)pFirst)->GetSection() ) 1721 pFirst = pFirst->GetNext(); 1722 if( pFirst && pFirst->IsSctFrm() && pSect->GetFollow() == pFirst ) 1723 pNew = pSect->GetFollow(); 1724 else if( MAKEPAGE_NOSECTION == eMakePage ) 1725 return pLayLeaf; 1726 else 1727 { 1728 pNew = new SwSectionFrm( *pSect, sal_False ); 1729 pNew->InsertBefore( pLayLeaf, pLayLeaf->Lower() ); 1730 pNew->Init(); 1731 SWRECTFN( pNew ) 1732 (pNew->*fnRect->fnMakePos)( pLayLeaf, NULL, sal_True ); 1733 1734 // Wenn unser Bereichsframe einen Nachfolger hat, so muss dieser 1735 // umgehaengt werden hinter den neuen Follow der Bereichsframes. 1736 SwFrm* pTmp = pSect->GetNext(); 1737 if( pTmp && pTmp != pSect->GetFollow() ) 1738 { 1739 SwFlowFrm* pNxt; 1740 SwCntntFrm* pNxtCntnt = NULL; 1741 if( pTmp->IsCntntFrm() ) 1742 { 1743 pNxt = (SwCntntFrm*)pTmp; 1744 pNxtCntnt = (SwCntntFrm*)pTmp; 1745 } 1746 else 1747 { 1748 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt(); 1749 if( pTmp->IsSctFrm() ) 1750 pNxt = (SwSectionFrm*)pTmp; 1751 else 1752 { 1753 ASSERT( pTmp->IsTabFrm(), "GetNextSctLeaf: Wrong Type" ); 1754 pNxt = (SwTabFrm*)pTmp; 1755 } 1756 while( !pNxtCntnt && 0 != ( pTmp = pTmp->GetNext() ) ) 1757 { 1758 if( pTmp->IsCntntFrm() ) 1759 pNxtCntnt = (SwCntntFrm*)pTmp; 1760 else 1761 pNxtCntnt = ((SwLayoutFrm*)pTmp)->ContainsCntnt(); 1762 } 1763 } 1764 if( pNxtCntnt ) 1765 { 1766 SwFtnBossFrm* pOldBoss = pSect->FindFtnBossFrm( sal_True ); 1767 if( pOldBoss == pNxtCntnt->FindFtnBossFrm( sal_True ) ) 1768 { 1769 SwSaveFtnHeight aHeight( pOldBoss, 1770 pOldBoss->Frm().Top() + pOldBoss->Frm().Height() ); 1771 pSect->GetUpper()->MoveLowerFtns( pNxtCntnt, pOldBoss, 1772 pLayLeaf->FindFtnBossFrm( sal_True ), sal_False ); 1773 } 1774 } 1775 ((SwFlowFrm*)pNxt)->MoveSubTree( pLayLeaf, pNew->GetNext() ); 1776 } 1777 if( pNew->GetFollow() ) 1778 pNew->SimpleFormat(); 1779 } 1780 // Das gesuchte Layoutblatt ist jetzt das erste des ermittelten SctFrms: 1781 pLayLeaf = FIRSTLEAF( pNew ); 1782 } 1783 return pLayLeaf; 1784 } 1785 1786 /************************************************************************* 1787 |* 1788 |* SwFrm::GetPrevSctLeaf() 1789 |* 1790 |* Beschreibung Liefert das vorhergehende LayoutBlatt in das der 1791 |* Frame gemoved werden kann. 1792 |* Ersterstellung AMA 07. Jan. 98 1793 |* Letzte Aenderung AMA 07. Jan. 98 1794 |* 1795 |*************************************************************************/ 1796 1797 1798 SwLayoutFrm *SwFrm::GetPrevSctLeaf( MakePageType ) 1799 { 1800 PROTOCOL_ENTER( this, PROT_LEAF, ACT_PREV_SECT, GetUpper()->FindSctFrm() ) 1801 1802 SwLayoutFrm* pCol; 1803 // ColumnFrm beinhalten jetzt stets einen BodyFrm 1804 if( IsColBodyFrm() ) 1805 pCol = GetUpper(); 1806 else if( GetUpper()->IsColBodyFrm() ) 1807 pCol = GetUpper()->GetUpper(); 1808 else 1809 pCol = NULL; 1810 sal_Bool bJump = sal_False; 1811 if( pCol ) 1812 { 1813 if( pCol->GetPrev() ) 1814 { 1815 do 1816 { 1817 pCol = (SwLayoutFrm*)pCol->GetPrev(); 1818 // Gibt es dort Inhalt? 1819 if( ((SwLayoutFrm*)pCol->Lower())->Lower() ) 1820 { 1821 if( bJump ) // Haben wir eine leere Spalte uebersprungen? 1822 SwFlowFrm::SetMoveBwdJump( sal_True ); 1823 return (SwLayoutFrm*)pCol->Lower(); // Der Spaltenbody 1824 } 1825 bJump = sal_True; 1826 } while( pCol->GetPrev() ); 1827 1828 // Hier landen wir, wenn alle Spalten leer sind, 1829 // pCol ist jetzt die erste Spalte, wir brauchen aber den Body: 1830 pCol = (SwLayoutFrm*)pCol->Lower(); 1831 } 1832 else 1833 pCol = NULL; 1834 } 1835 1836 if( bJump ) // Haben wir eine leere Spalte uebersprungen? 1837 SwFlowFrm::SetMoveBwdJump( sal_True ); 1838 1839 // Innerhalb von Bereichen in Tabellen oder Bereichen in Kopf/Fusszeilen kann 1840 // nur ein Spaltenwechsel erfolgen, eine der oberen Abkuerzungen haette 1841 // zuschlagen muessen, ebenso wenn der Bereich einen pPrev hat. 1842 // Jetzt ziehen wir sogar eine leere Spalte in Betracht... 1843 ASSERT( FindSctFrm(), "GetNextSctLeaf: Missing SectionFrm" ); 1844 if( ( IsInTab() && !IsTabFrm() ) || FindFooterOrHeader() ) 1845 return pCol; 1846 1847 // === IMPORTANT === 1848 // Precondition, which needs to be hold, is that the <this> frame can be 1849 // inside a table, but then the found section frame <pSect> is also inside 1850 // this table. 1851 SwSectionFrm *pSect = FindSctFrm(); 1852 1853 // --> OD 2009-01-16 #i95698# 1854 // A table cell containing directly a section does not break - see lcl_FindSectionsInRow(..) 1855 // Thus, a table inside a section, which is inside another table can only 1856 // flow backward in the columns of its section. 1857 // Note: The table cell, which contains the section, can not have a master table cell. 1858 if ( IsTabFrm() && pSect->IsInTab() ) 1859 { 1860 return pCol; 1861 } 1862 // <-- 1863 1864 { 1865 SwFrm *pPrv; 1866 if( 0 != ( pPrv = pSect->GetIndPrev() ) ) 1867 { 1868 // Herumlungernde, halbtote SectionFrms sollen uns nicht beirren 1869 while( pPrv && pPrv->IsSctFrm() && !((SwSectionFrm*)pPrv)->GetSection() ) 1870 pPrv = pPrv->GetPrev(); 1871 if( pPrv ) 1872 return pCol; 1873 } 1874 } 1875 1876 const sal_Bool bBody = IsInDocBody(); 1877 const sal_Bool bFly = IsInFly(); 1878 1879 SwLayoutFrm *pLayLeaf = GetPrevLayoutLeaf(); 1880 SwLayoutFrm *pPrevLeaf = 0; 1881 1882 while ( pLayLeaf ) 1883 { 1884 //In Tabellen oder Bereiche geht's niemals hinein. 1885 if ( pLayLeaf->IsInTab() || pLayLeaf->IsInSct() ) 1886 { 1887 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); 1888 } 1889 else if ( bBody && pLayLeaf->IsInDocBody() ) 1890 { 1891 // If there is a pLayLeaf has a lower pLayLeaf is the frame we are looking for. 1892 // Exception: pLayLeaf->Lower() is a zombie section frame 1893 const SwFrm* pTmp = pLayLeaf->Lower(); 1894 // OD 11.04.2003 #108824# - consider, that the zombie section frame 1895 // can have frame below it in the found layout leaf. 1896 // Thus, skipping zombie section frame, if possible. 1897 while ( pTmp && pTmp->IsSctFrm() && 1898 !( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) && 1899 pTmp->GetNext() 1900 ) 1901 { 1902 pTmp = pTmp->GetNext(); 1903 } 1904 if ( pTmp && 1905 ( !pTmp->IsSctFrm() || 1906 ( static_cast<const SwSectionFrm*>(pTmp)->GetSection() ) 1907 ) 1908 ) 1909 { 1910 break; 1911 } 1912 pPrevLeaf = pLayLeaf; 1913 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); 1914 if ( pLayLeaf ) 1915 SwFlowFrm::SetMoveBwdJump( sal_True ); 1916 } 1917 else if ( bFly ) 1918 break; //Cntnts in Flys sollte jedes Layout-Blatt recht sein. Warum? 1919 else 1920 pLayLeaf = pLayLeaf->GetPrevLayoutLeaf(); 1921 } 1922 if( !pLayLeaf ) 1923 { 1924 if( !pPrevLeaf ) 1925 return pCol; 1926 pLayLeaf = pPrevLeaf; 1927 } 1928 1929 SwSectionFrm* pNew = NULL; 1930 // Zunaechst einmal an das Ende des Layoutblatts gehen 1931 SwFrm *pTmp = pLayLeaf->Lower(); 1932 if( pTmp ) 1933 { 1934 while( pTmp->GetNext() ) 1935 pTmp = pTmp->GetNext(); 1936 if( pTmp->IsSctFrm() ) 1937 { 1938 // Halbtote stoeren hier nur... 1939 while( !((SwSectionFrm*)pTmp)->GetSection() && pTmp->GetPrev() && 1940 pTmp->GetPrev()->IsSctFrm() ) 1941 pTmp = pTmp->GetPrev(); 1942 if( ((SwSectionFrm*)pTmp)->GetFollow() == pSect ) 1943 pNew = (SwSectionFrm*)pTmp; 1944 } 1945 } 1946 if( !pNew ) 1947 { 1948 pNew = new SwSectionFrm( *pSect, sal_True ); 1949 pNew->InsertBefore( pLayLeaf, NULL ); 1950 pNew->Init(); 1951 SWRECTFN( pNew ) 1952 (pNew->*fnRect->fnMakePos)( pLayLeaf, pNew->GetPrev(), sal_True ); 1953 1954 pLayLeaf = FIRSTLEAF( pNew ); 1955 if( !pNew->Lower() ) // einspaltige Bereiche formatieren 1956 { 1957 pNew->MakePos(); 1958 pLayLeaf->Format(); // damit die PrtArea fuers MoveBwd stimmt 1959 } 1960 else 1961 pNew->SimpleFormat(); 1962 } 1963 else 1964 { 1965 pLayLeaf = FIRSTLEAF( pNew ); 1966 if( pLayLeaf->IsColBodyFrm() ) 1967 { 1968 // In existent section columns we're looking for the last not empty 1969 // column. 1970 SwLayoutFrm *pTmpLay = pLayLeaf; 1971 while( pLayLeaf->GetUpper()->GetNext() ) 1972 { 1973 pLayLeaf = (SwLayoutFrm*)((SwLayoutFrm*)pLayLeaf->GetUpper()->GetNext())->Lower(); 1974 if( pLayLeaf->Lower() ) 1975 pTmpLay = pLayLeaf; 1976 } 1977 // If we skipped an empty column, we've to set the jump-flag 1978 if( pLayLeaf != pTmpLay ) 1979 { 1980 pLayLeaf = pTmpLay; 1981 SwFlowFrm::SetMoveBwdJump( sal_True ); 1982 } 1983 } 1984 } 1985 return pLayLeaf; 1986 } 1987 1988 SwTwips lcl_DeadLine( const SwFrm* pFrm ) 1989 { 1990 const SwLayoutFrm* pUp = pFrm->GetUpper(); 1991 while( pUp && pUp->IsInSct() ) 1992 { 1993 if( pUp->IsSctFrm() ) 1994 pUp = pUp->GetUpper(); 1995 // Spalten jetzt mit BodyFrm 1996 else if( pUp->IsColBodyFrm() && pUp->GetUpper()->GetUpper()->IsSctFrm() ) 1997 pUp = pUp->GetUpper()->GetUpper(); 1998 else 1999 break; 2000 } 2001 SWRECTFN( pFrm ) 2002 return pUp ? (pUp->*fnRect->fnGetPrtBottom)() : 2003 (pFrm->Frm().*fnRect->fnGetBottom)(); 2004 } 2005 2006 // SwSectionFrm::Growable(..) prueft, ob der SectionFrm noch wachsen kann, 2007 // ggf. muss die Umgebung gefragt werden 2008 2009 sal_Bool SwSectionFrm::Growable() const 2010 { 2011 SWRECTFN( this ) 2012 if( (*fnRect->fnYDiff)( lcl_DeadLine( this ), 2013 (Frm().*fnRect->fnGetBottom)() ) > 0 ) 2014 return sal_True; 2015 2016 return ( GetUpper() && ((SwFrm*)GetUpper())->Grow( LONG_MAX, sal_True ) ); 2017 } 2018 2019 /************************************************************************* 2020 |* 2021 |* SwSectionFrm::_Grow(), _Shrink() 2022 |* 2023 |* Ersterstellung AMA 14. Jan. 98 2024 |* Letzte Aenderung AMA 14. Jan. 98 2025 |* 2026 |*************************************************************************/ 2027 2028 SwTwips SwSectionFrm::_Grow( SwTwips nDist, sal_Bool bTst ) 2029 { 2030 if ( !IsColLocked() && !HasFixSize() ) 2031 { 2032 SWRECTFN( this ) 2033 long nFrmHeight = (Frm().*fnRect->fnGetHeight)(); 2034 if( nFrmHeight > 0 && nDist > (LONG_MAX - nFrmHeight) ) 2035 nDist = LONG_MAX - nFrmHeight; 2036 2037 if ( nDist <= 0L ) 2038 return 0L; 2039 2040 sal_Bool bInCalcCntnt = GetUpper() && IsInFly() && FindFlyFrm()->IsLocked(); 2041 // OD 2004-03-15 #116561# - allow grow in online layout 2042 sal_Bool bGrow = !Lower() || !Lower()->IsColumnFrm() || !Lower()->GetNext() || 2043 GetSection()->GetFmt()->GetBalancedColumns().GetValue(); 2044 if( !bGrow ) 2045 { 2046 const ViewShell *pSh = getRootFrm()->GetCurrShell(); 2047 bGrow = pSh && pSh->GetViewOptions()->getBrowseMode(); 2048 } 2049 if( bGrow ) 2050 { 2051 SwTwips nGrow; 2052 if( IsInFtn() ) 2053 nGrow = 0; 2054 else 2055 { 2056 nGrow = lcl_DeadLine( this ); 2057 nGrow = (*fnRect->fnYDiff)( nGrow, 2058 (Frm().*fnRect->fnGetBottom)() ); 2059 } 2060 SwTwips nSpace = nGrow; 2061 if( !bInCalcCntnt && nGrow < nDist && GetUpper() ) 2062 nGrow += GetUpper()->Grow( LONG_MAX, sal_True ); 2063 2064 if( nGrow > nDist ) 2065 nGrow = nDist; 2066 if( nGrow <= 0 ) 2067 { 2068 nGrow = 0; 2069 if( nDist && !bTst ) 2070 { 2071 if( bInCalcCntnt ) 2072 _InvalidateSize(); 2073 else 2074 InvalidateSize(); 2075 } 2076 } 2077 else if( !bTst ) 2078 { 2079 if( bInCalcCntnt ) 2080 _InvalidateSize(); 2081 else if( nSpace < nGrow && nDist != nSpace + GetUpper()-> 2082 Grow( nGrow - nSpace, sal_False ) ) 2083 InvalidateSize(); 2084 else 2085 { 2086 const SvxGraphicPosition ePos = 2087 GetAttrSet()->GetBackground().GetGraphicPos(); 2088 if ( GPOS_RT < ePos && GPOS_TILED != ePos ) 2089 { 2090 SetCompletePaint(); 2091 InvalidatePage(); 2092 } 2093 if( GetUpper() && GetUpper()->IsHeaderFrm() ) 2094 GetUpper()->InvalidateSize(); 2095 } 2096 (Frm().*fnRect->fnAddBottom)( nGrow ); 2097 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() + nGrow; 2098 (Prt().*fnRect->fnSetHeight)( nPrtHeight ); 2099 2100 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() ) 2101 { 2102 SwFrm* pTmp = Lower(); 2103 do 2104 { 2105 pTmp->_InvalidateSize(); 2106 pTmp = pTmp->GetNext(); 2107 } while ( pTmp ); 2108 _InvalidateSize(); 2109 } 2110 if( GetNext() ) 2111 { 2112 SwFrm *pFrm = GetNext(); 2113 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() ) 2114 pFrm = pFrm->GetNext(); 2115 if( pFrm ) 2116 { 2117 if( bInCalcCntnt ) 2118 pFrm->_InvalidatePos(); 2119 else 2120 pFrm->InvalidatePos(); 2121 } 2122 } 2123 // --> OD 2004-07-05 #i28701# - Due to the new object positioning 2124 // the frame on the next page/column can flow backward (e.g. it 2125 // was moved forward due to the positioning of its objects ). 2126 // Thus, invalivate this next frame, if document compatibility 2127 // option 'Consider wrapping style influence on object positioning' is ON. 2128 else if ( GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) ) 2129 { 2130 InvalidateNextPos(); 2131 } 2132 // <-- 2133 } 2134 return nGrow; 2135 } 2136 if ( !bTst ) 2137 { 2138 if( bInCalcCntnt ) 2139 _InvalidateSize(); 2140 else 2141 InvalidateSize(); 2142 } 2143 } 2144 return 0L; 2145 } 2146 2147 SwTwips SwSectionFrm::_Shrink( SwTwips nDist, sal_Bool bTst ) 2148 { 2149 if ( Lower() && !IsColLocked() && !HasFixSize() ) 2150 { 2151 if( ToMaximize( sal_False ) ) 2152 { 2153 if( !bTst ) 2154 InvalidateSize(); 2155 } 2156 else 2157 { 2158 SWRECTFN( this ) 2159 long nFrmHeight = (Frm().*fnRect->fnGetHeight)(); 2160 if ( nDist > nFrmHeight ) 2161 nDist = nFrmHeight; 2162 2163 if ( Lower()->IsColumnFrm() && Lower()->GetNext() && // FtnAtEnd 2164 !GetSection()->GetFmt()->GetBalancedColumns().GetValue() ) 2165 { //Bei Spaltigkeit ubernimmt das Format die Kontrolle ueber 2166 //das Wachstum (wg. des Ausgleichs). 2167 if ( !bTst ) 2168 InvalidateSize(); 2169 return nDist; 2170 } 2171 else if( !bTst ) 2172 { 2173 const SvxGraphicPosition ePos = 2174 GetAttrSet()->GetBackground().GetGraphicPos(); 2175 if ( GPOS_RT < ePos && GPOS_TILED != ePos ) 2176 { 2177 SetCompletePaint(); 2178 InvalidatePage(); 2179 } 2180 (Frm().*fnRect->fnAddBottom)( -nDist ); 2181 long nPrtHeight = (Prt().*fnRect->fnGetHeight)() - nDist; 2182 (Prt().*fnRect->fnSetHeight)( nPrtHeight ); 2183 2184 SwTwips nReal = 0; 2185 // We do not allow a section frame to shrink the its upper 2186 // footer frame. This is because in the calculation of a 2187 // footer frame, the content of the section frame is _not_ 2188 // calculated. If there is a fly frame overlapping with the 2189 // footer frame, the section frame is not affected by this 2190 // during the calculation of the footer frame size. 2191 // The footer frame does not grow in its FormatSize function 2192 // but during the calculation of the content of the section 2193 // frame. The section frame grows until some of its text is 2194 // located on top of the fly frame. The next call of CalcCntnt 2195 // tries to shrink the section and here it would also shrink 2196 // the footer. This may not happen, because shrinking the footer 2197 // would cause the top of the section frame to overlap with the 2198 // fly frame again, this would result in a perfect loop. 2199 if( GetUpper() && !GetUpper()->IsFooterFrm() ) 2200 nReal = GetUpper()->Shrink( nDist, bTst ); 2201 2202 if( Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() ) 2203 { 2204 SwFrm* pTmp = Lower(); 2205 do 2206 { 2207 pTmp->_InvalidateSize(); 2208 pTmp = pTmp->GetNext(); 2209 } while ( pTmp ); 2210 } 2211 if( GetNext() ) 2212 { 2213 SwFrm* pFrm = GetNext(); 2214 while( pFrm && pFrm->IsSctFrm() && !((SwSectionFrm*)pFrm)->GetSection() ) 2215 pFrm = pFrm->GetNext(); 2216 if( pFrm ) 2217 pFrm->InvalidatePos(); 2218 else 2219 SetRetouche(); 2220 } 2221 else 2222 SetRetouche(); 2223 return nDist; 2224 } 2225 } 2226 } 2227 return 0L; 2228 } 2229 2230 /************************************************************************* 2231 |* 2232 |* SwSectionFrm::MoveAllowed() 2233 |* 2234 |* Ersterstellung MA 08. Oct. 98 2235 |* Letzte Aenderung MA 08. Oct. 98 2236 |* 2237 |* Wann sind Frms innerhalb eines SectionFrms moveable? 2238 |* Wenn sie noch nicht in der letzten Spalte des SectionFrms sind, 2239 |* wenn es einen Follow gibt, 2240 |* wenn der SectionFrm nicht mehr wachsen kann, wird es komplizierter, 2241 |* dann kommt es darauf an, ob der SectionFrm ein naechstes Layoutblatt 2242 |* finden kann. In (spaltigen/verketteten) Flys wird dies via GetNextLayout 2243 |* geprueft, in Tabellen und in Kopf/Fusszeilen gibt es keins, im DocBody 2244 |* und auch im Fussnoten dagegen immer. 2245 |* 2246 |* Benutzt wird diese Routine im TxtFormatter, um zu entscheiden, ob ein 2247 |* (Absatz-)Follow erzeugt werden darf oder ob der Absatz zusammenhalten muss. 2248 |* 2249 |*************************************************************************/ 2250 2251 sal_Bool SwSectionFrm::MoveAllowed( const SwFrm* pFrm) const 2252 { 2253 // Gibt es einen Follow oder ist der Frame nicht in der letzten Spalte? 2254 if( HasFollow() || ( pFrm->GetUpper()->IsColBodyFrm() && 2255 pFrm->GetUpper()->GetUpper()->GetNext() ) ) 2256 return sal_True; 2257 if( pFrm->IsInFtn() ) 2258 { 2259 if( IsInFtn() ) 2260 { 2261 if( GetUpper()->IsInSct() ) 2262 { 2263 if( Growable() ) 2264 return sal_False; 2265 return GetUpper()->FindSctFrm()->MoveAllowed( this ); 2266 } 2267 else 2268 return sal_True; 2269 } 2270 // The content of footnote inside a columned sectionfrm is moveable 2271 // except in the last column 2272 const SwLayoutFrm *pLay = pFrm->FindFtnFrm()->GetUpper()->GetUpper(); 2273 if( pLay->IsColumnFrm() && pLay->GetNext() ) 2274 { 2275 // The first paragraph in the first footnote in the first column 2276 // in the sectionfrm at the top of the page is not moveable, 2277 // if the columnbody is empty. 2278 sal_Bool bRet = sal_False; 2279 if( pLay->GetIndPrev() || pFrm->GetIndPrev() || 2280 pFrm->FindFtnFrm()->GetPrev() ) 2281 bRet = sal_True; 2282 else 2283 { 2284 SwLayoutFrm* pBody = ((SwColumnFrm*)pLay)->FindBodyCont(); 2285 if( pBody && pBody->Lower() ) 2286 bRet = sal_True; 2287 } 2288 if( bRet && ( IsFtnAtEnd() || !Growable() ) ) 2289 return sal_True; 2290 } 2291 } 2292 // Oder kann der Bereich noch wachsen? 2293 if( !IsColLocked() && Growable() ) 2294 return sal_False; 2295 // Jetzt muss untersucht werden, ob es ein Layoutblatt gibt, in dem 2296 // ein Bereichsfollow erzeugt werden kann. 2297 if( IsInTab() || ( !IsInDocBody() && FindFooterOrHeader() ) ) 2298 return sal_False; // In Tabellen/Kopf/Fusszeilen geht es nicht 2299 if( IsInFly() ) // Bei spaltigen oder verketteten Rahmen 2300 return 0 != ((SwFrm*)GetUpper())->GetNextLeaf( MAKEPAGE_NONE ); 2301 return sal_True; 2302 } 2303 2304 /** Called for a frame inside a section with no direct previous frame (or only 2305 previous empty section frames) the previous frame of the outer section is 2306 returned, if the frame is the first flowing content of this section. 2307 2308 Note: For a frame inside a table frame, which is inside a section frame, 2309 NULL is returned. 2310 */ 2311 SwFrm* SwFrm::_GetIndPrev() const 2312 { 2313 SwFrm *pRet = NULL; 2314 // --> OD 2007-09-04 #i79774#, #b659654# 2315 // Do not assert, if the frame has a direct previous frame, because it 2316 // could be an empty section frame. The caller has to assure, that the 2317 // frame has no direct previous frame or only empty section frames as 2318 // previous frames. 2319 ASSERT( /*!pPrev &&*/ IsInSct(), "Why?" ); 2320 // <-- 2321 const SwFrm* pSct = GetUpper(); 2322 if( !pSct ) 2323 return NULL; 2324 if( pSct->IsSctFrm() ) 2325 pRet = pSct->GetIndPrev(); 2326 else if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() ) 2327 { 2328 // Do not return the previous frame of the outer section, if in one 2329 // of the previous columns is content. 2330 const SwFrm* pCol = GetUpper()->GetUpper()->GetPrev(); 2331 while( pCol ) 2332 { 2333 ASSERT( pCol->IsColumnFrm(), "GetIndPrev(): ColumnFrm expected" ); 2334 ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(), 2335 "GetIndPrev(): Where's the body?"); 2336 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() ) 2337 return NULL; 2338 pCol = pCol->GetPrev(); 2339 } 2340 pRet = pSct->GetIndPrev(); 2341 } 2342 2343 // skip empty section frames 2344 while( pRet && pRet->IsSctFrm() && !((SwSectionFrm*)pRet)->GetSection() ) 2345 pRet = pRet->GetIndPrev(); 2346 return pRet; 2347 } 2348 2349 SwFrm* SwFrm::_GetIndNext() 2350 { 2351 ASSERT( !pNext && IsInSct(), "Why?" ); 2352 SwFrm* pSct = GetUpper(); 2353 if( !pSct ) 2354 return NULL; 2355 if( pSct->IsSctFrm() ) 2356 return pSct->GetIndNext(); 2357 if( pSct->IsColBodyFrm() && (pSct = pSct->GetUpper()->GetUpper())->IsSctFrm() ) 2358 { // Wir duerfen nur den Nachfolger des SectionFrms zurueckliefern, 2359 // wenn in keiner folgenden Spalte mehr Inhalt ist 2360 SwFrm* pCol = GetUpper()->GetUpper()->GetNext(); 2361 while( pCol ) 2362 { 2363 ASSERT( pCol->IsColumnFrm(), "GetIndNext(): ColumnFrm expected" ); 2364 ASSERT( pCol->GetLower() && pCol->GetLower()->IsBodyFrm(), 2365 "GetIndNext(): Where's the body?"); 2366 if( ((SwLayoutFrm*)((SwLayoutFrm*)pCol)->Lower())->Lower() ) 2367 return NULL; 2368 pCol = pCol->GetNext(); 2369 } 2370 return pSct->GetIndNext(); 2371 } 2372 return NULL; 2373 } 2374 2375 sal_Bool SwSectionFrm::IsDescendantFrom( const SwSectionFmt* pFmt ) const 2376 { 2377 if( !pSection || !pFmt ) 2378 return sal_False; 2379 const SwSectionFmt *pMyFmt = pSection->GetFmt(); 2380 while( pFmt != pMyFmt ) 2381 { 2382 if( pMyFmt->GetRegisteredIn()->ISA( SwSectionFmt ) ) 2383 pMyFmt = (SwSectionFmt*)pMyFmt->GetRegisteredIn(); 2384 else 2385 return sal_False; 2386 } 2387 return sal_True; 2388 } 2389 2390 void SwSectionFrm::CalcFtnAtEndFlag() 2391 { 2392 SwSectionFmt *pFmt = GetSection()->GetFmt(); 2393 sal_uInt16 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue(); 2394 bFtnAtEnd = FTNEND_ATPGORDOCEND != nVal; 2395 bOwnFtnNum = FTNEND_ATTXTEND_OWNNUMSEQ == nVal || 2396 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal; 2397 while( !bFtnAtEnd && !bOwnFtnNum ) 2398 { 2399 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) ) 2400 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn(); 2401 else 2402 break; 2403 nVal = pFmt->GetFtnAtTxtEnd( sal_False ).GetValue(); 2404 if( FTNEND_ATPGORDOCEND != nVal ) 2405 { 2406 bFtnAtEnd = sal_True; 2407 bOwnFtnNum = bOwnFtnNum ||FTNEND_ATTXTEND_OWNNUMSEQ == nVal || 2408 FTNEND_ATTXTEND_OWNNUMANDFMT == nVal; 2409 } 2410 } 2411 } 2412 2413 sal_Bool SwSectionFrm::IsEndnoteAtMyEnd() const 2414 { 2415 return pSection->GetFmt()->GetEndAtTxtEnd( sal_False ).IsAtEnd(); 2416 } 2417 2418 void SwSectionFrm::CalcEndAtEndFlag() 2419 { 2420 SwSectionFmt *pFmt = GetSection()->GetFmt(); 2421 bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd(); 2422 while( !bEndnAtEnd ) 2423 { 2424 if( pFmt->GetRegisteredIn()->ISA( SwSectionFmt ) ) 2425 pFmt = (SwSectionFmt*)pFmt->GetRegisteredIn(); 2426 else 2427 break; 2428 bEndnAtEnd = pFmt->GetEndAtTxtEnd( sal_False ).IsAtEnd(); 2429 } 2430 } 2431 2432 /************************************************************************* 2433 |* 2434 |* SwSectionFrm::Modify() 2435 |* 2436 |* Ersterstellung MA 08. Oct. 98 2437 |* Letzte Aenderung MA 08. Oct. 98 2438 |* 2439 |*************************************************************************/ 2440 2441 void SwSectionFrm::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew ) 2442 { 2443 sal_uInt8 nInvFlags = 0; 2444 2445 if( pNew && RES_ATTRSET_CHG == pNew->Which() ) 2446 { 2447 SfxItemIter aNIter( *((SwAttrSetChg*)pNew)->GetChgSet() ); 2448 SfxItemIter aOIter( *((SwAttrSetChg*)pOld)->GetChgSet() ); 2449 SwAttrSetChg aOldSet( *(SwAttrSetChg*)pOld ); 2450 SwAttrSetChg aNewSet( *(SwAttrSetChg*)pNew ); 2451 while( sal_True ) 2452 { 2453 _UpdateAttr( (SfxPoolItem*)aOIter.GetCurItem(), 2454 (SfxPoolItem*)aNIter.GetCurItem(), nInvFlags, 2455 &aOldSet, &aNewSet ); 2456 if( aNIter.IsAtEnd() ) 2457 break; 2458 aNIter.NextItem(); 2459 aOIter.NextItem(); 2460 } 2461 if ( aOldSet.Count() || aNewSet.Count() ) 2462 SwLayoutFrm::Modify( &aOldSet, &aNewSet ); 2463 } 2464 else 2465 _UpdateAttr( pOld, pNew, nInvFlags ); 2466 2467 if ( nInvFlags != 0 ) 2468 { 2469 if ( nInvFlags & 0x01 ) 2470 InvalidateSize(); 2471 if ( nInvFlags & 0x10 ) 2472 SetCompletePaint(); 2473 } 2474 } 2475 2476 void SwSectionFrm::SwClientNotify( const SwModify& rMod, const SfxHint& rHint ) 2477 { 2478 // --> OD #i117863# 2479 const SwSectionFrmMoveAndDeleteHint* pHint = 2480 dynamic_cast<const SwSectionFrmMoveAndDeleteHint*>(&rHint); 2481 if ( pHint && pHint->GetId() == SFX_HINT_DYING && &rMod == GetRegisteredIn() ) 2482 { 2483 SwSectionFrm::MoveCntntAndDelete( this, pHint->IsSaveCntnt() ); 2484 } 2485 // <-- 2486 } 2487 2488 void SwSectionFrm::_UpdateAttr( const SfxPoolItem *pOld, const SfxPoolItem *pNew, 2489 sal_uInt8 &rInvFlags, 2490 SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet ) 2491 { 2492 sal_Bool bClear = sal_True; 2493 const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0; 2494 switch( nWhich ) 2495 { // Mehrspaltigkeit in Fussnoten unterdruecken... 2496 case RES_FMT_CHG: 2497 { 2498 const SwFmtCol& rNewCol = GetFmt()->GetCol(); 2499 if( !IsInFtn() ) 2500 { 2501 //Dummer Fall. Bei der Zuweisung einer Vorlage k?nnen wir uns 2502 //nicht auf das alte Spaltenattribut verlassen. Da diese 2503 //wenigstens anzahlgemass fuer ChgColumns vorliegen muessen, 2504 //bleibt uns nur einen temporaeres Attribut zu basteln. 2505 SwFmtCol aCol; 2506 if ( Lower() && Lower()->IsColumnFrm() ) 2507 { 2508 sal_uInt16 nCol = 0; 2509 SwFrm *pTmp = Lower(); 2510 do 2511 { ++nCol; 2512 pTmp = pTmp->GetNext(); 2513 } while ( pTmp ); 2514 aCol.Init( nCol, 0, 1000 ); 2515 } 2516 sal_Bool bChgFtn = IsFtnAtEnd(); 2517 sal_Bool bChgEndn = IsEndnAtEnd(); 2518 sal_Bool bChgMyEndn = IsEndnoteAtMyEnd(); 2519 CalcFtnAtEndFlag(); 2520 CalcEndAtEndFlag(); 2521 bChgFtn = ( bChgFtn != IsFtnAtEnd() ) || 2522 ( bChgEndn != IsEndnAtEnd() ) || 2523 ( bChgMyEndn != IsEndnoteAtMyEnd() ); 2524 ChgColumns( aCol, rNewCol, bChgFtn ); 2525 rInvFlags |= 0x10; 2526 } 2527 rInvFlags |= 0x01; 2528 bClear = sal_False; 2529 } 2530 break; 2531 2532 case RES_COL: 2533 if( !IsInFtn() ) 2534 { 2535 ChgColumns( *(const SwFmtCol*)pOld, *(const SwFmtCol*)pNew ); 2536 rInvFlags |= 0x11; 2537 } 2538 break; 2539 2540 case RES_FTN_AT_TXTEND: 2541 if( !IsInFtn() ) 2542 { 2543 sal_Bool bOld = IsFtnAtEnd(); 2544 CalcFtnAtEndFlag(); 2545 if( bOld != IsFtnAtEnd() ) 2546 { 2547 const SwFmtCol& rNewCol = GetFmt()->GetCol(); 2548 ChgColumns( rNewCol, rNewCol, sal_True ); 2549 rInvFlags |= 0x01; 2550 } 2551 } 2552 break; 2553 2554 case RES_END_AT_TXTEND: 2555 if( !IsInFtn() ) 2556 { 2557 sal_Bool bOld = IsEndnAtEnd(); 2558 sal_Bool bMyOld = IsEndnoteAtMyEnd(); 2559 CalcEndAtEndFlag(); 2560 if( bOld != IsEndnAtEnd() || bMyOld != IsEndnoteAtMyEnd()) 2561 { 2562 const SwFmtCol& rNewCol = GetFmt()->GetCol(); 2563 ChgColumns( rNewCol, rNewCol, sal_True ); 2564 rInvFlags |= 0x01; 2565 } 2566 } 2567 break; 2568 case RES_COLUMNBALANCE: 2569 rInvFlags |= 0x01; 2570 break; 2571 2572 case RES_FRAMEDIR : 2573 SetDerivedR2L( sal_False ); 2574 CheckDirChange(); 2575 break; 2576 2577 case RES_PROTECT: 2578 { 2579 ViewShell *pSh = getRootFrm()->GetCurrShell(); 2580 if( pSh && pSh->GetLayout()->IsAnyShellAccessible() ) 2581 pSh->Imp()->InvalidateAccessibleEditableState( sal_True, this ); 2582 } 2583 break; 2584 2585 default: 2586 bClear = sal_False; 2587 } 2588 if ( bClear ) 2589 { 2590 if ( pOldSet || pNewSet ) 2591 { 2592 if ( pOldSet ) 2593 pOldSet->ClearItem( nWhich ); 2594 if ( pNewSet ) 2595 pNewSet->ClearItem( nWhich ); 2596 } 2597 else 2598 SwLayoutFrm::Modify( pOld, pNew ); 2599 } 2600 } 2601 2602 /*-----------------09.06.99 14:58------------------- 2603 * SwSectionFrm::ToMaximize(..): A follow or a ftncontainer at the end of the 2604 * page causes a maximal Size of the sectionframe. 2605 * --------------------------------------------------*/ 2606 2607 sal_Bool SwSectionFrm::ToMaximize( sal_Bool bCheckFollow ) const 2608 { 2609 if( HasFollow() ) 2610 { 2611 if( !bCheckFollow ) // Don't check superfluous follows 2612 return sal_True; 2613 const SwSectionFrm* pFoll = GetFollow(); 2614 while( pFoll && pFoll->IsSuperfluous() ) 2615 pFoll = pFoll->GetFollow(); 2616 if( pFoll ) 2617 return sal_True; 2618 } 2619 if( IsFtnAtEnd() ) 2620 return sal_False; 2621 const SwFtnContFrm* pCont = ContainsFtnCont(); 2622 if( !IsEndnAtEnd() ) 2623 return 0 != pCont; 2624 sal_Bool bRet = sal_False; 2625 while( pCont && !bRet ) 2626 { 2627 if( pCont->FindFootNote() ) 2628 bRet = sal_True; 2629 else 2630 pCont = ContainsFtnCont( pCont ); 2631 } 2632 return bRet; 2633 } 2634 2635 /*-----------------09.06.99 15:07------------------- 2636 * sal_Bool SwSectionFrm::ContainsFtnCont() 2637 * checks every Column for FtnContFrms. 2638 * --------------------------------------------------*/ 2639 2640 SwFtnContFrm* SwSectionFrm::ContainsFtnCont( const SwFtnContFrm* pCont ) const 2641 { 2642 SwFtnContFrm* pRet = NULL; 2643 const SwLayoutFrm* pLay; 2644 if( pCont ) 2645 { 2646 pLay = pCont->FindFtnBossFrm( 0 ); 2647 ASSERT( IsAnLower( pLay ), "ConatainsFtnCont: Wrong FtnContainer" ); 2648 pLay = (SwLayoutFrm*)pLay->GetNext(); 2649 } 2650 else if( Lower() && Lower()->IsColumnFrm() ) 2651 pLay = (SwLayoutFrm*)Lower(); 2652 else 2653 pLay = NULL; 2654 while ( !pRet && pLay ) 2655 { 2656 if( pLay->Lower() && pLay->Lower()->GetNext() ) 2657 { 2658 ASSERT( pLay->Lower()->GetNext()->IsFtnContFrm(), 2659 "ToMaximize: Unexspected Frame" ); 2660 pRet = (SwFtnContFrm*)pLay->Lower()->GetNext(); 2661 } 2662 ASSERT( !pLay->GetNext() || pLay->GetNext()->IsLayoutFrm(), 2663 "ToMaximize: ColFrm exspected" ); 2664 pLay = (SwLayoutFrm*)pLay->GetNext(); 2665 } 2666 return pRet; 2667 } 2668 2669 void SwSectionFrm::InvalidateFtnPos() 2670 { 2671 SwFtnContFrm* pCont = ContainsFtnCont( NULL ); 2672 if( pCont ) 2673 { 2674 SwFrm *pTmp = pCont->ContainsCntnt(); 2675 if( pTmp ) 2676 pTmp->_InvalidatePos(); 2677 } 2678 } 2679 2680 /*-----------------18.03.99 10:37------------------- 2681 * SwSectionFrm::Undersize() liefert den Betrag, um den der Bereich gern 2682 * groesser waere, wenn in ihm Undersized TxtFrms liegen, ansonsten Null. 2683 * Das Undersized-Flag wird ggf. korrigiert. 2684 * --------------------------------------------------*/ 2685 2686 long SwSectionFrm::Undersize( sal_Bool bOverSize ) 2687 { 2688 bUndersized = sal_False; 2689 SWRECTFN( this ) 2690 long nRet = InnerHeight() - (Prt().*fnRect->fnGetHeight)(); 2691 if( nRet > 0 ) 2692 bUndersized = sal_True; 2693 else if( !bOverSize ) 2694 nRet = 0; 2695 return nRet; 2696 } 2697 2698 /// OD 01.04.2003 #108446# - determine next frame for footnote/endnote formatting 2699 /// before format of current one, because current one can move backward. 2700 /// After moving backward to a previous page method <FindNext()> will return 2701 /// the text frame presenting the first page footnote, if it exists. Thus, the 2702 /// rest of the footnote/endnote container would not be formatted. 2703 void SwSectionFrm::CalcFtnCntnt() 2704 { 2705 SwFtnContFrm* pCont = ContainsFtnCont(); 2706 if( pCont ) 2707 { 2708 SwFrm* pFrm = pCont->ContainsAny(); 2709 if( pFrm ) 2710 pCont->Calc(); 2711 while( pFrm && IsAnLower( pFrm ) ) 2712 { 2713 SwFtnFrm* pFtn = pFrm->FindFtnFrm(); 2714 if( pFtn ) 2715 pFtn->Calc(); 2716 // OD 01.04.2003 #108446# - determine next frame before format current frame. 2717 SwFrm* pNextFrm = 0; 2718 { 2719 if( pFrm->IsSctFrm() ) 2720 { 2721 pNextFrm = static_cast<SwSectionFrm*>(pFrm)->ContainsAny(); 2722 } 2723 if( !pNextFrm ) 2724 { 2725 pNextFrm = pFrm->FindNext(); 2726 } 2727 } 2728 pFrm->Calc(); 2729 pFrm = pNextFrm; 2730 } 2731 } 2732 } 2733 2734 /* -----------------09.02.99 14:26------------------- 2735 * Wenn ein SectionFrm leerlaeuft, z.B. weil sein Inhalt die Seite/Spalte wechselt, 2736 * so wird er nicht sofort zerstoert (es koennte noch jemand auf dem Stack einen Pointer 2737 * auf ihn halten), sondern er traegt sich in eine Liste am RootFrm ein, die spaeter 2738 * abgearbeitet wird (in LayAction::Action u.a.). Seine Groesse wird auf Null gesetzt und 2739 * sein Zeiger auf seine Section ebenfalls. Solche zum Loeschen vorgesehene SectionFrms 2740 * muessen vom Layout/beim Formatieren ignoriert werden. 2741 * 2742 * Mit InsertEmptySct nimmt der RootFrm einen SectionFrm in die Liste auf, 2743 * mit RemoveFromList kann ein SectionFrm wieder aus der Liste entfernt werden (Dtor), 2744 * mit DeleteEmptySct wird die Liste abgearbeitet und die SectionFrms zerstoert 2745 * --------------------------------------------------*/ 2746 2747 void SwRootFrm::InsertEmptySct( SwSectionFrm* pDel ) 2748 { 2749 if( !pDestroy ) 2750 pDestroy = new SwDestroyList; 2751 sal_uInt16 nPos; 2752 if( !pDestroy->Seek_Entry( pDel, &nPos ) ) 2753 pDestroy->Insert( pDel ); 2754 } 2755 2756 void SwRootFrm::_DeleteEmptySct() 2757 { 2758 ASSERT( pDestroy, "Keine Liste, keine Kekse" ); 2759 while( pDestroy->Count() ) 2760 { 2761 SwSectionFrm* pSect = (*pDestroy)[0]; 2762 pDestroy->Remove( sal_uInt16(0) ); 2763 ASSERT( !pSect->IsColLocked() && !pSect->IsJoinLocked(), 2764 "DeleteEmptySct: Locked SectionFrm" ); 2765 if( !pSect->Frm().HasArea() && !pSect->ContainsCntnt() ) 2766 { 2767 SwLayoutFrm* pUp = pSect->GetUpper(); 2768 pSect->Remove(); 2769 delete pSect; 2770 if( pUp && !pUp->Lower() ) 2771 { 2772 if( pUp->IsPageBodyFrm() ) 2773 pUp->getRootFrm()->SetSuperfluous(); 2774 else if( pUp->IsFtnFrm() && !pUp->IsColLocked() && 2775 pUp->GetUpper() ) 2776 { 2777 pUp->Cut(); 2778 delete pUp; 2779 } 2780 } 2781 } 2782 else { 2783 ASSERT( pSect->GetSection(), "DeleteEmptySct: Halbtoter SectionFrm?!" ); 2784 } 2785 } 2786 } 2787 2788 void SwRootFrm::_RemoveFromList( SwSectionFrm* pSct ) 2789 { 2790 ASSERT( pDestroy, "Where's my list?" ); 2791 sal_uInt16 nPos; 2792 if( pDestroy->Seek_Entry( pSct, &nPos ) ) 2793 pDestroy->Remove( nPos ); 2794 } 2795 2796 #ifdef DBG_UTIL 2797 2798 sal_Bool SwRootFrm::IsInDelList( SwSectionFrm* pSct ) const 2799 { 2800 sal_uInt16 nPos; 2801 return ( pDestroy && pDestroy->Seek_Entry( pSct, &nPos ) ); 2802 } 2803 2804 #endif 2805 2806 bool SwSectionFrm::IsBalancedSection() const 2807 { 2808 bool bRet = false; 2809 if ( GetSection() && Lower() && Lower()->IsColumnFrm() && Lower()->GetNext() ) 2810 { 2811 bRet = !GetSection()->GetFmt()->GetBalancedColumns().GetValue(); 2812 } 2813 return bRet; 2814 } 2815 2816